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

Reply via email to