Hi, The attached patch is the same as posted in the PR with a test case added. Tested with on sh-elf with make -k check RUNTESTFLAGS="--target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
and on sh4-linux by Kaz. Committed as r221604. Cheers, Oleg gcc/ChangeLog: PR target/65505 * config/sh/predicates.md (simple_mem_operand, displacement_mem_operand): Add test for reg. (short_displacement_mem_operand): Test for displacement_mem_operand before invoking sh_disp_addr_displacement. * config/sh/constraints.md (Sdd, Sra): Simplify. * config/sh/sync.md (atomic_mem_operand_0, atomic_mem_operand_1): Remove redundant displacement_mem_operand tests. gcc/testsuite/ChangeLog: PR target/65505 * gcc.target/sh/torture/pr65505.c: New.
Index: gcc/testsuite/gcc.target/sh/torture/pr65505.c =================================================================== --- gcc/testsuite/gcc.target/sh/torture/pr65505.c (revision 0) +++ gcc/testsuite/gcc.target/sh/torture/pr65505.c (revision 0) @@ -0,0 +1,122 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=gnu99" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ + +struct thread_info { + struct task_struct *task; +}; + +static inline __attribute__((always_inline)) + __attribute__((no_instrument_function)) +struct thread_info *current_thread_info(void) +{ + struct thread_info *ti; + + unsigned long __dummy; + + __asm__ __volatile__ ( + "mov r15, %0\n\t" + "and %1, %0\n\t" + : "=&r" (ti), "=r" (__dummy) + : "1" (~((1 << 13) - 1)) + : "memory"); + + return ti; +} + +typedef struct seqcount { + unsigned sequence; +} seqcount_t; + +struct inode; + +struct dentry { + seqcount_t d_seq; + struct inode *d_inode; +}; + +struct path { + struct vfsmount *mnt; + struct dentry *dentry; +}; + +struct file { + struct path f_path; +} __attribute__((aligned(4))); + +struct task_struct +{ + int link_count, total_link_count; + struct fs_struct *fs; +}; + +struct fd { + struct file *file; + unsigned int flags; +}; + +static inline __attribute__((always_inline)) + __attribute__((no_instrument_function)) +struct fd +fdget_raw(unsigned int fd) +{ + return (struct fd){(struct file *)(fd & ~3),fd & 3}; +} + + +struct fs_struct; + +struct nameidata { + struct path path; + struct path root; + struct inode *inode; + unsigned int flags; + unsigned seq, m_seq; + struct file *base; +}; + +int read_seqcount_retry(const seqcount_t *s, unsigned start); + +int +path_init(int dfd, const char *name, unsigned int flags, + struct nameidata *nd) +{ + int retval = 0; + + if (*name=='/') { + nd->path = nd->root; + } else if (dfd == -100) { + + if (flags & 0x0040) { + struct fs_struct *fs = (current_thread_info()->task)->fs; + } + } else { + + struct fd f = fdget_raw(dfd); + struct dentry *dentry; + + if (!f.file) + return -9; + + dentry = f.file->f_path.dentry; + + nd->path = f.file->f_path; + if (flags & 0x0040) { + if (f.flags & 1) + nd->base = f.file; + } + } + + nd->inode = nd->path.dentry->d_inode; + if (!(flags & 0x0040)) + goto done; + if (__builtin_expect(!!(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)), 1)) + goto done; + if (!(nd->flags & 0x2000)) + nd->root.mnt = ((void *)0); + + return -10; +done: + (current_thread_info()->task)->total_link_count = 0; + return 0; +} Index: gcc/config/sh/predicates.md =================================================================== --- gcc/config/sh/predicates.md (revision 221537) +++ gcc/config/sh/predicates.md (working copy) @@ -437,12 +437,14 @@ ;; Returns 1 if OP is a simple register address. (define_predicate "simple_mem_operand" (and (match_code "mem") + (match_code "reg" "0") (match_test "arith_reg_operand (XEXP (op, 0), SImode)"))) ;; Returns 1 if OP is a valid displacement address. (define_predicate "displacement_mem_operand" (and (match_code "mem") - (match_test "GET_CODE (XEXP (op, 0)) == PLUS") + (match_code "plus" "0") + (match_code "reg" "00") (match_test "arith_reg_operand (XEXP (XEXP (op, 0), 0), SImode)") (match_test "sh_legitimate_index_p (GET_MODE (op), XEXP (XEXP (op, 0), 1), @@ -451,8 +453,10 @@ ;; Returns true if OP is a displacement address that can fit into a ;; 16 bit (non-SH2A) memory load / store insn. (define_predicate "short_displacement_mem_operand" - (match_test "sh_disp_addr_displacement (op) - <= sh_max_mov_insn_displacement (GET_MODE (op), false)")) + (and (match_code "mem") + (match_operand 0 "displacement_mem_operand") + (match_test "sh_disp_addr_displacement (op) + <= sh_max_mov_insn_displacement (GET_MODE (op), false)"))) ;; Returns 1 if the operand can be used in an SH2A movu.{b|w} insn. (define_predicate "zero_extend_movu_operand" Index: gcc/config/sh/constraints.md =================================================================== --- gcc/config/sh/constraints.md (revision 221537) +++ gcc/config/sh/constraints.md (working copy) @@ -300,9 +300,9 @@ (define_memory_constraint "Sdd" "A memory reference that uses displacement addressing." (and (match_code "mem") - (match_test "GET_CODE (XEXP (op, 0)) == PLUS") - (match_test "REG_P (XEXP (XEXP (op, 0), 0))") - (match_test "CONST_INT_P (XEXP (XEXP (op, 0), 1))"))) + (match_code "plus" "0") + (match_code "reg" "00") + (match_code "const_int" "01"))) (define_memory_constraint "Snd" "A memory reference that excludes displacement addressing." @@ -322,8 +322,8 @@ (define_memory_constraint "Sra" "A memory reference that uses simple register addressing." - (and (match_test "MEM_P (op)") - (match_test "REG_P (XEXP (op, 0))"))) + (and (match_code "mem") + (match_code "reg" "0"))) (define_memory_constraint "Ara" "A memory reference that uses simple register addressing suitable for Index: gcc/config/sh/sync.md =================================================================== --- gcc/config/sh/sync.md (revision 221537) +++ gcc/config/sh/sync.md (working copy) @@ -217,7 +217,6 @@ (and (match_test "mode == SImode") (and (match_test "!TARGET_ATOMIC_HARD_LLCS") (match_test "!TARGET_SH4A || TARGET_ATOMIC_STRICT")) - (match_operand 0 "displacement_mem_operand") (match_operand 0 "short_displacement_mem_operand"))))) (define_expand "atomic_compare_and_swap<mode>" @@ -707,7 +706,6 @@ (and (match_test "mode == SImode") (match_test "TARGET_ATOMIC_SOFT_GUSA && (!TARGET_SH4A || TARGET_ATOMIC_STRICT)") - (match_operand 0 "displacement_mem_operand") (match_operand 0 "short_displacement_mem_operand")) (and (ior (match_test "(TARGET_ATOMIC_SOFT_TCB || TARGET_ATOMIC_SOFT_IMASK) @@ -716,8 +714,7 @@ || TARGET_ATOMIC_SOFT_IMASK) && TARGET_SH4A && !TARGET_ATOMIC_STRICT && mode != SImode")) - (ior (and (match_operand 0 "displacement_mem_operand") - (match_operand 0 "short_displacement_mem_operand")) + (ior (match_operand 0 "short_displacement_mem_operand") (match_operand 0 "gbr_address_mem")))))) (define_expand "atomic_fetch_<fetchop_name><mode>"