It's not enough to just check that a memory operand is of the form mem(reg); after RA we also need to validate the register being used. The safest way to do this is to call memory_operand.
PR target/120351 gcc/ChangeLog: * config/arm/predicates.md (mem_noofs_operand): Also check the op is a valid memory_operand. gcc/testsuite/ChangeLog: * gcc.target/arm/pr120351.c: New test. --- gcc/config/arm/predicates.md | 3 +- gcc/testsuite/gcc.target/arm/pr120351.c | 47 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/arm/pr120351.c diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index 57d4ec66088..c683ec2c607 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -901,7 +901,8 @@ (define_special_predicate "add_operator" (define_predicate "mem_noofs_operand" (and (match_code "mem") - (match_code "reg" "0"))) + (match_code "reg" "0") + (match_operand 0 "memory_operand"))) (define_predicate "call_insn_operand" (ior (and (match_code "symbol_ref") diff --git a/gcc/testsuite/gcc.target/arm/pr120351.c b/gcc/testsuite/gcc.target/arm/pr120351.c new file mode 100644 index 00000000000..d8e9d73275c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr120351.c @@ -0,0 +1,47 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_neon_ok } */ +/* { dg-add-options arm_neon } */ +/* { dg-additional-options "-O2" } */ + + +typedef struct A +{ + int f1; +} A; + +__inline void ref (A* x) +{ + __atomic_fetch_add(&x->f1, 1, 0); +} + +typedef struct B +{ + A *d; + int *ptr; +} B; + +void insertOne (B*, B*); + +void init (B *); +__inline void copy (B *p, B *q) +{ + p->d = q->d; + p->ptr = q->ptr; + ref (p->d); +} + +__inline void emplace(B* x) +{ + B dummy; + B _tmp; + init (&dummy); + copy (&_tmp, &dummy); + insertOne(x, &_tmp); +} + +void testing () +{ + B test; + init (&test); + emplace(&test); +} -- 2.43.0