https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63483
Bug ID: 63483 Summary: Scheduler performs Invalid move of aliased memory reference Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: ubizjak at gmail dot com CC: rguenth at gcc dot gnu.org, rth at gcc dot gnu.org The original problem is present in [1], and can be illustrated by following test on alpha-linux-gnu: --cut here-- static char *a; static char *b; void foo (void) { a[1] = 1; b[2] = 1; } int bar (void) { return a && b; } --cut here-- The compilation with -O2 produces: $foo..ng: .prologue 1 lda $1,1($31) lda $2,a ldq $3,0($2) <-- load a lda $2,b lda $7,1($3) ldq_u $5,1($3) <-- load a insbl $1,$7,$4 ldq $2,0($2) <-- load b mskbl $5,$7,$5 lda $6,2($2) bis $4,$5,$4 stq_u $4,1($3) <-- store a insbl $1,$6,$1 ldq_u $3,2($2) <-- load b mskbl $3,$6,$3 cpys $f31,$f31,$f31 bis $1,$3,$1 stq_u $1,2($2) <-- store b ret $31,($26),1 .end foo if a and b alias to the same wide memory location, then "b" RMW sequence corrupts "a". There is am early shortcut for MEM_READOLNY_P in true_dependence_1 in alias.c. For the testcase above: (insn 15 13 18 2 (set (reg/f:DI 78 [ b ]) (mem/u/f/c:DI (reg/f:DI 79) [2 b+0 S8 A64])) rmw.c:7 226 {*movdi} (expr_list:REG_DEAD (reg/f:DI 79) (nil))) is free to be scheduled before (insn 13 12 15 2 (set (mem:DI (and:DI (plus:DI (reg/f:DI 72 [ a ]) (const_int 1 [0x1])) (const_int -8 [0xfffffffffffffff8])) [0 S8 A64]) (reg:DI 77)) rmw.c:6 226 {*movdi} (expr_list:REG_DEAD (reg:DI 77) (expr_list:REG_DEAD (reg/f:DI 72 [ a ]) (nil)))) rth explained situation on alpha a bit: --quote-- It's not the loads, per se, it's the stores that get in the way. Early alpha can't store sub-4-byte quantities. Altivec can't store anything but 16 byte quantities. In order to perform smaller stores, we have to do a read-modify-write sequence on a larger aligned chunk of memory. Two such RMW sequences must conflict, lest we interleave and thus bork the operation. I don't recall how much we ever did for this, exactly, but it's certainly possible to know that some memory operations cannot conflict with these RMW sequence. E.g. through size + alignment of the other memory operation. E.g. on Alpha, a byte RMW store can't conflict with a normal DImode memory access. --/quote-- And: > Btw, if the mem is MEM_READONLY_P how can it be part of > a {un}aligned_store sequence? This flag is copied from the original memory operand of the store by alpha_set_memflags to all memory operands in the expanded sequence. [1] https://gcc.gnu.org/ml/gcc-patches/2014-06/msg02251.html