7

在下面的代码中,为什么第二个循环可以自动矢量化,而第一个不能?如何修改代码使其自动矢量化?gcc 说:

注意:未矢量化:循环中的控制流。

我正在使用 gcc 8.2,标志是 -O3 -fopt-info-vec-all。我正在为 x86-64 avx2 编译。

#include <stdlib.h>
#include <math.h>

void foo(const float * x, const float * y, const int * v, float * vec, float * novec, size_t size) {
    size_t i;
    float bar;
    for (i=0 ; i<size ; ++i){
        bar = x[i] - y[i];
        novec[i] = v[i] ? bar : NAN;
    }
    for (i=0 ; i<size ; ++i){
        bar = x[i];
        vec[i] = v[i] ? bar : NAN;
    }
}

更新:这确实自动矢量化:

for (i=0 ; i<size ; ++i){
    bar = x[i];
    novec[i] = v[i] ? bar : NAN;
    novec[i] -= y[i];
}

我仍然想知道为什么 gcc 说第一个循环的控制流。

4

1 回答 1

7

即使是第一个循环,clang 也会自动矢量化,但 gcc8.2 不会。( https://godbolt.org/z/cnlwuO )

gcc 用-ffast-math. 也许它担心从减法中保留 FP 异常标志状态?

-fno-trapping-math足以让 gcc 自动矢量化(没有其余的-ffast-math设置),所以显然它担心 FP exceptions。(https://godbolt.org/z/804ykV)。我认为这是过于谨慎了,因为 C 源代码每次都会计算,无论是否使用它。bar

a[i] = b[i]+c[i]gcc 将在没有任何 FP 数学选项的情况下自动矢量化简单的 FP循环。

于 2018-11-09T00:54:51.553 回答