https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89505
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |ASSIGNED Last reconfirmed| |2019-02-26 Assignee|unassigned at gcc dot gnu.org |rguenth at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- So what happens is that this points to an aggregate with a lot of fields and field-sensitive analysis when gathering what are restrict pointed-to's only looks at the first field. Thus if you'd have struct this { int x; void *p; }; and _13 = &this_29(D)->nColCount; # _116 = PHI <_13(9), &D.857772(10)> _15 = *_116; here _13 does not point to the _first_ field (note you need meaningful fields - aka pointers - for points-to to separate fields fod analysis) then we miss that _116 also points to the same thing as this_29. Then you need a plain this_29 based access and a indirect ref to _13 to get things wrong. struct S { int i; void *p; int j; }; int a; int foo (struct S * __restrict p, int q) { int *x = &p->j; if (q) x = &a; p->j = 1; *x = 2; return p->j; } shows wrong alias info: # PT = null { D.1921 } (nonlocal, restrict) struct S * restrict p_2(D) = p; ... <bb 4> : # PT = null { D.1909 D.1921 } (nonlocal, interposable) # x_1 = PHI <x_3(2), &a(3)> MEM[(struct S *)p_2(D) clique 1 base 1].j = 1; MEM[(int *)x_1 clique 1 base 0] = 2; _9 = MEM[(struct S *)p_2(D) clique 1 base 1].j; and FRE optimizing the load. struct S { int i; void *p; int j; }; int a; int __attribute__((noinline)) foo (struct S * __restrict p, int q) { int *x = &p->j; if (q) x = &a; p->j = 1; *x = 2; return p->j; } int main() { struct S s; if (foo (&s, 0) != 2) __builtin_abort (); return 0; }