On Tue, 4 Oct 2011, Jakub Jelinek wrote:

> On Tue, Oct 04, 2011 at 11:55:17AM +0200, Richard Guenther wrote:
> > > On Tue, Oct 04, 2011 at 11:01:27AM +0200, Richard Guenther wrote:
> > > > > > > void foo (int *p)
> > > > > > > {    
> > > > > > >   int * __restrict p1 = p;
> > > > > > >   int * __restrict p2 = p + 32;
> > > > > > >   int *q;
> > > > > > >   int i;
> > > > > > >   for (i = 0; i < 32; ++i)
> > > > > > >     p1[i] = p2[i];
> > > > > > >   p = p1;
> > > > > > >   q = p2 - 31;
> > > > > > >   for (i = 0; i < 32; ++i)
> > > > > > >     p[i] = q[i];
> > > > > > > }
> > > > > > > 
> > > 
> > > > In the above first loop the restrict pointers p1 and p2 access
> > > > distinct object pieces.  The second loop uses non-restrict qualified
> > > > pointers p and q (that are based on the restrict variants p1 and p2
> > > > though) to access overlapping pieces.  Is the second loop invalid
> > > > because p and q are based on p1 and p2 even though they are not
> > > > restrict qualified?
> > > 
> > > IMHO yes.  The standard doesn't seem to talk about the accesses being done
> > > through the restricted pointer, but about accesses that are based on
> > > the restricted pointer, and as soon as you access in the associated block
> > > (here the foo function) some object through an lvalue whose address is
> > > based on some restricted pointer and the value is modified by any means,
> > > then all accesses to that object need to be done through something
> > > based on that restricted pointer.
> > 
> > So when I change the above to
> > 
> >  /*p = p;*/
> >  q = (p + 32) - 31;
> 
> void foo (int *p)
> {    
>   int * __restrict p1 = p;
>   int * __restrict p2 = p + 32;
>   int *q;
>   int i;
>   for (i = 0; i < 32; ++i)
>     p1[i] = p2[i];
>   q = (p + 32) - 31;
>   for (i = 0; i < 32; ++i)
>     p[i] = q[i];
> }
> 
> > then the code will be valid?  When I obfuscate that enough I
> > can get GCC CSEing p + 32 and thus effectively q will look
> > like it is based on p2.
> 
> The above is still invalid. p[0] through p[31] is modified and
> is accessed both through lvalue whose address is based on p1 (p1[i])
> and through lvalues whose address is not based on p1 (p[i] and
> q[i] (the latter only for p[0] through p[30])).  If you take
> the first loop out, it would be valid though.

So

  int *x;

> void foo (int *p)
> {
>   int * __restrict p1 = p;
>   int * __restrict p2 = p + 32;
>   int *q;
>   int i;
    x = p2;
>   q = p + 32;
    q = q - 31;
>   for (i = 0; i < 32; ++i)
>     p[i] = q[i];
> }

would be valid and we'd rely on CSE not to replace q = p + 32
with q = p2 (ignoring the fact that for a miscompile we need
similar tricks for p1).  It doesn't do that at the moment
because we fold int * __restrict p2 = p + 32 to
((int * __restrict)p) + 32 and thus see

  p.0_4 = (int * restrict) p_2(D);
  p2_5 = p.0_4 + 128;

vs.

  q_6 = p_2(D) + 128;

but you are going to change that ;)

Richard.

Reply via email to