public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* (gcc/)g++ and __restrict
@ 2013-09-20 10:07 Tobias Burnus
  2013-09-20 14:59 ` Ian Lance Taylor
  0 siblings, 1 reply; 3+ messages in thread
From: Tobias Burnus @ 2013-09-20 10:07 UTC (permalink / raw)
  To: gcc-help

Hi all,

I was wondering how to convey to GCC that two pointers do not alias.
That works nicely in the argument list,
  void foo(mytype *__restrict__ arg)

However, it does not seem to work for C++'s member variables. Even
if one has on the class the declaration with __restrict. Neither does
casting to a restrict pointer work.

(The issue of example 1 also applies C99.)

In example 1, one gets:
  test.cc:17:3: note: loop versioned for vectorization because of
                      possible aliasing
That's unchanged when one uncomments the casts. However, when one
#defines RESTRICT as __restrict, the loop versioning disappears.


In example 2, have the same problem: I get loop versioning and neither the
__restrict__ in the class definition nor the restrict casting has any
effect whatsoever.


Is this to be expected? And, if so, how can one otherwise convay
this information? 

Tobias

PS: For the big code, using a static array instead of a allocatable pointer
gives a speed-up of up to 40% - and I am highly suspicious that this is
mainly due to alias analysis.

PPS: For loops, using #pragma ivdep should help (and does with Intel; for
GCC it's still on my to-do list). And also the forced vectorization with
#pragma simd (Cilk+/OpenMPv4) should help. Still, __restrict__ should
go beyond. (Using Fortran's allocatables is also a solution ;-)


Example 1:

#define ASSUME_ALIGNED(lvalueptr, align) \
  lvalueptr = \
     ( __typeof(lvalueptr))( \
                         __builtin_assume_aligned(lvalueptr, align))

//#define RESTRICT __restrict__
#define RESTRICT
typedef double mytype;

void test(int size, mytype *RESTRICT a, mytype *RESTRICT b, mytype *RESTRICT c) {
  ASSUME_ALIGNED(a, 64);
  ASSUME_ALIGNED(b, 64);
  ASSUME_ALIGNED(c, 64);
// a = (mytype* __restrict__) a;
// b = (mytype* __restrict__) b;
// c = (mytype* __restrict__) c;
  for (int i = 0; i < size; ++i)
    a[i] = b[i] + c[i];
}


Example 2:

#define ASSUME_ALIGNED(lvalueptr, align) \
  lvalueptr = \
     ( __typeof(lvalueptr))( \
                         __builtin_assume_aligned(lvalueptr, align))

//#define RESTRICT __restrict__
#define RESTRICT
typedef double mytype;

void test(int size, mytype *RESTRICT a, mytype *RESTRICT b, mytype *RESTRICT c) {
  ASSUME_ALIGNED(a, 64);
  ASSUME_ALIGNED(b, 64);
  ASSUME_ALIGNED(c, 64);
 a = (mytype* __restrict__) a;
 b = (mytype* __restrict__) b;
 c = (mytype* __restrict__) c;
  for (int i = 0; i < size; ++i)
    a[i] = b[i] + c[i];
}

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

* Re: (gcc/)g++ and __restrict
  2013-09-20 10:07 (gcc/)g++ and __restrict Tobias Burnus
@ 2013-09-20 14:59 ` Ian Lance Taylor
  2013-09-22 22:42   ` Tobias Burnus
  0 siblings, 1 reply; 3+ messages in thread
From: Ian Lance Taylor @ 2013-09-20 14:59 UTC (permalink / raw)
  To: Tobias Burnus; +Cc: gcc-help

On Fri, Sep 20, 2013 at 3:07 AM, Tobias Burnus
<tobias.burnus@physik.fu-berlin.de> wrote:
>
> I was wondering how to convey to GCC that two pointers do not alias.
> That works nicely in the argument list,
>   void foo(mytype *__restrict__ arg)
>
> However, it does not seem to work for C++'s member variables. Even
> if one has on the class the declaration with __restrict. Neither does
> casting to a restrict pointer work.

I'm not sure how that could work.  By definition the restrict
qualifier is only meaningful in a specific context, with respect to
other pointers with the restrict qualifier.  It would not make sense
to declare that every restrict qualified pointer in the entire program
may not conflict with every other restrict qualified pointer in the
entire program.  That would be too limiting.

What GCC implements is what the C99 standard specifies.  Within a
function you can have a set of restrict qualified pointers.  Any write
through a restrict qualified pointer may not be read through any other
restrict qualified pointer (unless the second pointer is based on the
first, which is defined by the standard).

If we found it useful, we could introduce a new attribute for C++
class members.  We could declare that within a class, all members with
that attribute could not alias.  But to make that useful we would have
to make that attribute inheritable--we wouldn't want people to have to
use it for local variables.  I think it would be hard to define
correctly--it was hard to define the C99 restrict qualifier.

Another possibly more profitable approach would be to define a new
function attribute.  In functions with that attribute we would declare
that none of the pointers that were not based on each other could
alias.  This would be difficult to use correctly but it would be
fairly precise and might be sufficient for what you need.

Ian

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

* Re: (gcc/)g++ and __restrict
  2013-09-20 14:59 ` Ian Lance Taylor
@ 2013-09-22 22:42   ` Tobias Burnus
  0 siblings, 0 replies; 3+ messages in thread
From: Tobias Burnus @ 2013-09-22 22:42 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Tobias Burnus, gcc-help

Am 20.09.2013 16:59, schrieb Ian Lance Taylor:
> On Fri, Sep 20, 2013 at 3:07 AM, Tobias Burnus
> <tobias.burnus@physik.fu-berlin.de> wrote:
>> I was wondering how to convey to GCC that two pointers do not alias.
>> That works nicely in the argument list,
>>    void foo(mytype *__restrict__ arg)
>>
>> However, it does not seem to work for C++'s member variables. Even
>> if one has on the class the declaration with __restrict. Neither does
>> casting to a restrict pointer work.
> I'm not sure how that could work.  By definition the restrict
> qualifier is only meaningful in a specific context, with respect to
> other pointers with the restrict qualifier.  It would not make sense
> to declare that every restrict qualified pointer in the entire program
> may not conflict with every other restrict qualified pointer in the
> entire program.  That would be too limiting.

I admit that placing it on a C++ member variable is not the best place. 
However, being desperate, I thought I'd try it - and GCC accepted it. 
(As did Intel's icpc.)

> Another possibly more profitable approach would be to define a new
> function attribute.  In functions with that attribute we would declare
> that none of the pointers that were not based on each other could
> alias.  This would be difficult to use correctly but it would be
> fairly precise and might be sufficient for what you need.

Actually, I would find some casting approach best, namely:
   ptr = (__typeof(ptr) *__restrict) ptr;
or something like that. That would allow to put the restrict qualifier 
exactly on the pointer one wants to mark as such. I think one can 
already use such a cast for "volatile". Similarly, one can use ptr = 
__builtin_assume_aligned(ptr, size), which is also an assignment way to 
add an attribute to a pointer.

However, putting an attribute on the function itself would also work for me.

Tobias

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

end of thread, other threads:[~2013-09-22 22:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-20 10:07 (gcc/)g++ and __restrict Tobias Burnus
2013-09-20 14:59 ` Ian Lance Taylor
2013-09-22 22:42   ` Tobias Burnus

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