https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97477

            Bug ID: 97477
           Summary: g++ doesn't accept __restrict keyword inside array
                    function parameter
           Product: gcc
           Version: 10.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dwwork at gmail dot com
  Target Milestone: ---

I was looking into how gcc treats the restrict keyword, when I discovered a
case that g++ does not accept using the __restrict gnu extension keyword.

The following function, compiled with gcc 10.2, and flags "-O3 -mavx", produces
vectorized assembly:

void func(const float a[restrict 3][8], const float b[restrict 3][8], float
c[restrict 3][8])
{

    a = __builtin_assume_aligned(a,32);
    b = __builtin_assume_aligned(b,32);
    c = __builtin_assume_aligned(c,32);

    for(int i=0; i<8; i++) {
        c[0][i] = a[0][i] + b[0][i];
        c[1][i] = a[1][i] + b[1][i];
        c[2][i] = a[2][i] + b[2][i];
    }

}

The restrict keyword inside the square brackets is legal according to
cppreference: https://en.cppreference.com/w/c/language/restrict

I then tested g++ 10.2, changing the restrict keyword to __restrict. This does
not compile:

void func(const float a[__restrict 3][8], const float b[__restrict 3][8], float
c[__restrict 3][8])
{

    a = __builtin_assume_aligned(a,32);
    b = __builtin_assume_aligned(b,32);
    c = __builtin_assume_aligned(c,32);

    for(int i=0; i<8; i++) {
        c[0][i] = a[0][i] + b[0][i];
        c[1][i] = a[1][i] + b[1][i];
        c[2][i] = a[2][i] + b[2][i];
    }

}

It gives me the following error (edited for brevity):

error: expected primary-expression before '__restrict'
error: expected ']' before '__restrict'
error: expected ')' before '__restrict'
error: expected initializer before numeric constant

I can get g++ to output vectorized code if I change the types to a pointer of
float[8]:

void func(const float (* __restrict a)[8], const float (* __restrict b)[8],
float (* __restrict c)[8])
{

    a =  static_cast<const float (*)[8]>( __builtin_assume_aligned(a,32) );
    b =  static_cast<const float (*)[8]>( __builtin_assume_aligned(b,32) );
    c =  static_cast<      float (*)[8]>( __builtin_assume_aligned(c,32) );

    for(int i=0; i<8; i++) {
        c[0][i] = a[0][i] + b[0][i];
        c[1][i] = a[1][i] + b[1][i];
        c[2][i] = a[2][i] + b[2][i];
    }

}

It's not a serious bug, but I do feel it is inconsistent.

I did browse the source code a bit to investigate, but I was way over my head.

Reply via email to