`restrict` ignored unless function manually inlined

110 Views Asked by At

With GCC 9.4.0, the code

static inline double k(double const *restrict a) {
    return a[-1] + a[0] + a[1];
}

static void f(double const *restrict a, double *restrict b, int n) {
    for (int i = 0; i < n; ++i) {
        b[i] = k(a);
    }
}

static inline void swap(double **a, double **b) {
    double *tmp = *a;
    *a = *b;
    *b = tmp;
}

void g(double * a, double * b, int n, int nt) {
    for (int t = 0; t < nt; ++t) {
        f(a, b, n);
        swap(&a, &b);
    }
}

results in loop versioned for vectorization because of possible aliasing for the loop in f when compiled using gcc -march=native -Ofast -fopt-info-vec, suggesting that the restrict qualifiers in f are being ignored.

If I instead manually inline k into f:

static void f(double const *restrict a, double *restrict b, int n) {
    for (int i = 0; i < n; ++i) {
        b[i] = a[-1] + a[0] + a[1];
    }
}

the loop is vectorized without this versioning.

In both cases GCC reports that all of the functions are automatically inlined into each other.

The same occurs if I instead use __restrict and compile with g++.

Why does this happen? Is there a cleanly portable (using standard language features) way of causing GCC to respect the restrict qualifiers in the first case so that I can benefit from vectorization without versioning, without separating f and g into different translation units?

0

There are 0 best solutions below