最近的 C++ 编译器会自动检测重复的数学运算吗?

all*_*llo 1 c++ optimization

假设我有以下代码:

const int n = fun1();
const double x = fun2();
for(int i=0; i < n; i++) {
    double y = fun3(i) / std::sqrt(x);
    double z = fun4(i) / std::sqrt(x);
    // Do something with the values, e.g., assign them to an array outside the loop
}
Run Code Online (Sandbox Code Playgroud)

最近的编译器是否设法将其优化为

const int n = fun1();
const double x = fun2();
const double sqrtx = std::sqrt(x); // only computed once instead of possibly 2*n times
for(int i=0; i < n; i++) {
    double y = fun3(i) / sqrtx;
    double z = fun4(i) / sqrtx;
    // Do something with the values, e.g., assign them to an array outside the loop
}
Run Code Online (Sandbox Code Playgroud)

或者仍然值得手动进行此类优化吗?

Ala*_*les 6

(截至撰写本文时)clang 和 gcc 没有进行此优化,但 MSVC 进行了: https: //godbolt.org/z/eKcva1heT。Clang 和 GCC 都调用了sqrt两次,它们判断是否std::sqrt有副作用太复杂,因此无法优化调用。

使用 libc++ clangstd::sqrt使用一条sqrtsd指令实现,但仍使用该指令两次: https: //godbolt.org/z/G5sEPYqEP

如果它是内联函数,那么编译器可能可以删除重复操作。如果我们将您的示例更改为:

inline double square(double value)
{
    return value * value;
}

int main()
{
    const int n = fun1();
    const double x = fun2();
    for(int i=0; i < n; i++) {
        double y = fun3(i) / square(x);
        double z = fun4(i) / square(x);
        std::cout << x << y;
    }    
}
Run Code Online (Sandbox Code Playgroud)

那么所有三个编译器只做一次平方:https ://godbolt.org/z/Ys6xPcsc1