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

--- Comment #15 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to vries from comment #14)
> (In reply to rguent...@suse.de from comment #13)
> > On Wed, 23 Sep 2015, vries at gcc dot gnu.org wrote:
> > 
> > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48885
> > > 
> > > --- Comment #12 from vries at gcc dot gnu.org ---
> > > (In reply to Richard Biener from comment #11)
> > > > I'm testing the above simple fix and amend the comment.
> > > 
> > > Consider the example with functions f and g I gave in comment 10. Using 
> > > the
> > > patch from comment 11, I get at ealias:
> > > ...
> > > void f(int* __restrict__&, int*) (intD.9 * restrict & restrict pD.2252, 
> > > intD.9
> > > * p2D.2253)
> > > {
> > >   intD.9 * _3;
> > > 
> > >   # VUSE <.MEM_1(D)>
> > >   # PT = { D.2265 } (nonlocal)
> > >   _3 = MEM[(intD.9 * restrict &)p_2(D) clique 1 base 1];
> > > 
> > >   # .MEM_4 = VDEF <.MEM_1(D)>
> > >   MEM[(intD.9 *)_3 clique 1 base 2] = 1;
> > > 
> > >   # .MEM_6 = VDEF <.MEM_4>
> > >   MEM[(intD.9 *)p2_5(D) clique 1 base 0] = 2;
> > > ...
> > > 
> > > AFAIU, this is incorrect. The two stores can be now disambiguated based 
> > > on same
> > > clique/different base, but in fact the stores can alias (in fact they do, 
> > > in
> > > the  "f (gp, gp)" call from g).
> > 
> > How is this a valid testcase?
> > You are accessing g()s *gp through
> > p and p2 even though p is marked as restrict.
> 
> To be exact, p is a restrict reference to a restrict pointer.
> And AFAIU it's a valid test-case.
> 
> >  Did you mean to write
> > 
> > void
> > f (int *&__restrict__ p, int *p2)
> > 
> > ?
> 
> No. I'll try explain, renaming variables to help clarification, and adding a
> call to g for completeness:
> ...
> void
> f (int *__restrict__ &__restrict__ fp, int *fp2)
> {
>   *fp = 1;
>   *fp2 = 2;
> }
> 
> void
> g (int *__restrict__ gp)
> {
>   f (gp, gp);
> }
> 
> void
> h (void)
> {
>   int ha;
>   g (&ha);
> }
> ...
> 
> Let's look at the three restricts in the example.
> 
> First, there's the second restrict in "int *__restrict &__restrict fp",
> which is a reference to object gp. Since object gp is not modified during f,
> the restrict has no consequence.
> 
> Then there's the restrict in "int *__restrict__ gp". The object pointed to
> is ha, and it's modified during g. So all accesses to ha during g need to be
> based on gp. And that is the case. The '*fp2 = 1' is based on gp. And the
> '*fp2 = 2' is based on gp.

No, *fp2 is _not_ based on gp.  Otherwise even simple cases like

int foo (int * __restrict p, int * __restrict q)
{
  *p = 1;
  *q = 0;
  return *p;
}

could not be optimized because calling foo like

int bar ()
{
  int i;
  int *r = &i;
  foo (r, r);
  return i;
}

would make that invalid.  With your reading both p and q are based on r
(in the context of bar).

The standard has some interesting wording to define "based-on".  IIRC
it goes like a pointer is based on 'p' if the value of the pointer
changes when you modify 'p'.  I think that only allows for expressions
based on p, like (p + 1) or &p[2].  It does _not_ allow for new
temporaries, like q = p + 1; as if you modify p q doesn't change.

IMHO the restrict qualifications on a function signature are to be
seen as constraints on the set of valid parameters it can be called
with and f (gp, gp) is not amongst that set.

> Finally, there's the first restrict in "int *__restrict &__restrict fp".
> That's a copy of the type of gp.

Reply via email to