public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Revisit of pr38212 regarding restrict definition
@ 2010-11-30 14:36 Bingfeng Mei
  2010-11-30 14:40 ` Richard Guenther
  0 siblings, 1 reply; 4+ messages in thread
From: Bingfeng Mei @ 2010-11-30 14:36 UTC (permalink / raw)
  To: gcc; +Cc: Richard Guenther

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?  "q = p + 1" may be also undefined,
depending whether we regard parameter p from outer or inner block. 

Cheers,
Bingfeng

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Revisit of pr38212 regarding restrict definition
  2010-11-30 14:36 Revisit of pr38212 regarding restrict definition Bingfeng Mei
@ 2010-11-30 14:40 ` Richard Guenther
  2010-11-30 14:56   ` Bingfeng Mei
  0 siblings, 1 reply; 4+ messages in thread
From: Richard Guenther @ 2010-11-30 14:40 UTC (permalink / raw)
  To: Bingfeng Mei; +Cc: gcc

On Tue, Nov 30, 2010 at 2:07 PM, Bingfeng Mei <bmei@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).

  "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.

Of course the middle-end may not do optimizations based on what
C thinks are "blocks".

Richard.

> Cheers,
> Bingfeng
>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: Revisit of pr38212 regarding restrict definition
  2010-11-30 14:40 ` Richard Guenther
@ 2010-11-30 14:56   ` Bingfeng Mei
  2010-11-30 14:58     ` Richard Guenther
  0 siblings, 1 reply; 4+ messages in thread
From: Bingfeng Mei @ 2010-11-30 14:56 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc



> -----Original Message-----
> From: Richard Guenther [mailto:richard.guenther@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 <bmei@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;
}


Bingfeng

> Of course the middle-end may not do optimizations based on what
> C thinks are "blocks".
> 
> Richard.
> 
> > Cheers,
> > Bingfeng
> >
> >


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Revisit of pr38212 regarding restrict definition
  2010-11-30 14:56   ` Bingfeng Mei
@ 2010-11-30 14:58     ` Richard Guenther
  0 siblings, 0 replies; 4+ messages in thread
From: Richard Guenther @ 2010-11-30 14:58 UTC (permalink / raw)
  To: Bingfeng Mei; +Cc: gcc

On Tue, Nov 30, 2010 at 3:29 PM, Bingfeng Mei <bmei@broadcom.com> wrote:
>
>
>> -----Original Message-----
>> From: Richard Guenther [mailto:richard.guenther@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 <bmei@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
>> >
>> >
>
>
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-11-30 14:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-30 14:36 Revisit of pr38212 regarding restrict definition Bingfeng Mei
2010-11-30 14:40 ` Richard Guenther
2010-11-30 14:56   ` Bingfeng Mei
2010-11-30 14:58     ` Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).