On Thu, 27 Apr 2017, Richard Biener wrote: > struct q { int n; long o[100]; }; > struct r { int n; long o[0]; }; > > union { > struct r r; > struct q q; > } u; > > int foo (int i, int j) > { > long *q = u.r.o; > u.r.o[i/j] = 1; > return q[2]; > } > > but nothing convinced scheduling to move the load before the store ;) > The two memory references are seen as not aliasing though. Stupid > scheduler.
On x86 there's an anti-dependence on %eax that prevents the second scheduler from performing the breaking motion; with -fschedule-insns, pre-RA scheduler is actually able to move the load too early, but then IRA immediately undoes that. Also, -fselective-scheduling2 is able to move the load early via renaming (and uncovers the miscompile, as nothing undoes it later). Applying division to the result of the load, rather than the address of the store, also produces code demonstrating the miscompile: struct q { int n; long o[100]; }; struct r { int n; long o[0]; }; union { struct r r; struct q q; } u; int foo (int i, int j) { long *q = u.r.o; u.r.o[i] = 1; return q[2]/j; } foo: .LFB0: .cfi_startproc movq u+24(%rip), %rax movslq %edi, %rdi movslq %esi, %rsi movq $1, u+8(,%rdi,8) cqto idivq %rsi ret Alexander