为什么 GCC 不优化此求和循环中的内存写入?

com*_*ude 3 c gcc

鉴于以下 C 代码,为什么 GCC(版本 10.1、x86-64、-O3)在循环内部写入内存,而不是在求和期间仅使用两个寄存器并仅在最后将结果写入内存?

void sum(unsigned int l, int *as, int *r) {
    r[0] = 0;
    r[1] = 0;
    for (int i = 0; i < l; i++) {
        r[0] += as[2 * i];
        r[1] += as[2 * i + 1];
    }
}
Run Code Online (Sandbox Code Playgroud)

此处生成说明。

我的猜测是这种行为与 GCC 具有“考虑”并发性有关。您可以有另一个线程,例如在执行求和时从同一地址的内存读取。
这是真正的(也是唯一的)原因吗?它甚至可能由 C 标准定义吗?

Eri*_*hil 7

编译器不知道是否asr点到同一阵列中,所以它不知道r[0] += as[2 * i];不改变的值as[2 * i + 1],这是需要在r[1] += as[2 * i + 1];,并且类似地针对其它之间的相互作用r[0]r[1]以及各种元件as

你可以告诉编译器的元素称为通过asr通过改变函数声明不重叠void sum(unsigned int l, int * restrict as, int * restrict r)