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.