https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64601

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Marc Glisse from comment #3)
> Actually there is no need for inlining.
> 
> struct A { int i; };
> void f(struct A *a){ *&a->i=0; }
> void g(struct A *a){ int*p=&a->i;*p=0; }
> 
> The main difference seems to be that the first one gets through fold-const.c
> while the second is handled by tree-ssa-forwprop.c.

&a->i is merely an address calculation, not an access to type A at a.  Thus
it's valid to write

 struct B { int i; int j; };
 struct B b;
 int *p = &((struct A *)&b)->i;
 *p = 0;

and it's only required that the actual access (here a int * dereference)
honors TBAA rules.

So generally you can't "reconstruct" access paths when forwarding address
calculations into dereferences.  We've had very elaborate code "guessing"
access paths in oder releases which broke down very easily for moderately
complex testcases.

We still have some of that code in forwprop (I still believe it's not
100% correct...) which handles

struct A { int i[4]; };
void g(struct A *a, int j) { int *p = &a->i[j]; *p = 0;}

generating

  MEM[(int *)a_1(D)].i[j_2(D)] = 0;
  return;

but the case comes after forwarding invariant addresses.  If we'd swap them
(really believing in its correctness) then we also handle your case.
But as I said - that "If ... and the value type is the same as that of the
pointed-to type of the address" is really bogus - the type of the address
doesn't have any meaning in GIMPLE (all pointer type conversions are
useless).

Reply via email to