On Tue, Nov 30, 2010 at 3:29 PM, Bingfeng Mei <b...@broadcom.com> wrote: > > >> -----Original Message----- >> From: Richard Guenther [mailto:richard.guent...@gmail.com] >> Sent: 30 November 2010 13:53 >> To: Bingfeng Mei >> Cc: gcc@gcc.gnu.org >> Subject: Re: Revisit of pr38212 regarding restrict definition >> >> On Tue, Nov 30, 2010 at 2:07 PM, Bingfeng Mei <b...@broadcom.com> wrote: >> > Hi, >> > I am working on how to improve "restrict". I noticed >> > that my changes lead to failure of pr38212. After looking >> > at its code, I think the test may not be valid according >> > to c99 standard. >> > >> > C99 standard 6.7.3.1: >> > >> > EXAMPLE 4 The rule limiting assignments between restricted pointers >> does not distinguish between a >> > function call and an equivalent nested block. With one exception, >> only ''outer-to-inner'' assignments >> > between restricted pointers declared in nested blocks have defined >> behavior. >> > { >> > int * restrict p1; >> > int * restrict q1; >> > p1 = q1; // undefined behavior >> > { >> > int * restrict p2 = p1; // valid >> > int * restrict q2 = q1; // valid >> > p1 = q2; // undefined behavior >> > p2 = q2; // undefined behavior >> > } >> > } >> > >> > pr38212.c >> > int __attribute__((noinline)) >> > foo (int *__restrict p, int i) >> > { >> > int *__restrict q; >> > int *__restrict r; >> > int v, w; >> > q = p + 1; >> > r = q - i; >> > v = *r; >> > *p = 1; >> > w = *r; >> > return v + w; >> > } >> > extern void abort (void); >> > int main() >> > { >> > int i = 0; >> > if (foo (&i, 1) != 1) >> > abort (); >> > return 0; >> > } >> > >> > Isn't that "r = q - i" undefined? >> >> Why? r is based on q which is based on p. If you write the source >> as r = p + 1 - i; it'll have the same effect (and then it's clearly >> based on p). >> > > But standard just plainly says it is undefined when you assign one > restrict pointer to another restrict pointer in the same block level. > > "If P is assigned the value of a pointer expression E that is based > on another restricted pointer object P2, associated with block B2, > then either the execution of B2 shall begin before the execution of B, > or the execution of B2 shall end prior to the assignment. If these > requirements are not met, then the behavior is undefined." > > Whether r is based on p is not important, IMO. Suppose p is not > restrict qualified. If we write > > int *__restrict r = p + 1 - i; > > Programmer just assumes that access through r won't be aliased > with any other pointer, including p. If it turns out that i = 1 > and r is indeed aliased with p. It is not compiler's fault to > miscompile code, but programmer's fault to write wrong code. > >> "q = p + 1" may be also undefined, >> > depending whether we regard parameter p from outer or inner block. >> >> you can avoid all the named temporaries by substituting the >> pointer arithmetic into the dereferences. >> > > If we remove all the restricted temporary pointers, there is nothing > undefined here and is a valid test for sure. > int __attribute__((noinline)) > foo (int *__restrict p, int i) > { > int v, w; > v = *(p + 1 - i); > *p = 1; > w = *(p + 1 - i); > return v + w; > }
The middle-end will see exactly the same (temporaries with restrict qualification being assigned a pointer that is restrict qualified). The testcase basically models what the middle-end has to expect and deal with, it doesn't try to be literally compliant with the C standard. Richard. > > Bingfeng > >> Of course the middle-end may not do optimizations based on what >> C thinks are "blocks". >> >> Richard. >> >> > Cheers, >> > Bingfeng >> > >> > > > >