https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88714
--- Comment #21 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Short testcase -O2 -mtune=cortex-a9 -mfloat-abi=hard -mfpu=vfpv3-d16 -mtls-dialect=gnu -marm -march=armv7-a+fp: struct S { int a, b, c; int *d; }; void bar (int, int, int, int); void foo (struct S *x, struct S *y, int *z) { x->d = z; if (y->d) y->c = y->c + y->d[0]; bar (0, 0, y->c, 0); } This one actually isn't miscompiled (dunno how to convince sched2 that it wants to schedule the ldrd before the x->d store), but if you put a breakpoint on true_dependence_1 if mem->mode == E_DImode || x->mode == E_DImode, then you should be able to see that it considers swapping those and doesn't find aliasing reason not to. What the peephole2 does is similar to what e.g. store-merging does, which for alias sets does: if (!n1->alias_set || alias_ptr_types_compatible_p (n1->alias_set, n2->alias_set)) n->alias_set = n1->alias_set; else n->alias_set = ptr_type_node; i.e. uses alias set 0 if they aren't compatible. Another possibility would be to use an alternate pattern for the ldrd when it is matched by such a peephole2, instead of presenting it as a DImode read present it as 2 SImode reads, so (set r2 (mem:SI ...)) (set r3 (mem:SI ...)). That way you could use the original MEM_ALIAS_SET and MEM_EXPRs. Seems arm.md even has similar patterns like *thumb2_ldrd_base. So, in ldrdstrd.md do a similar thing for TARGET_ARM as for TARGET_THUMB2, just the TARGET_ARM patterns would need to also verify the two registers are consecutive (can be done in the insn condition) and make sure it handles any cases where the two memory addresses are 4 bytes appart (again, can be done in the insn condition). I think this would be better than to drop alias set to 0, which then can prevent optimal scheduling etc.