C ++编译器会以少量术语内联for循环吗?

时间:2019-03-30 22:29:36

标签: c++ compiler-optimization loop-unrolling

假设我有一个类Matrix5x5(带有适当重载的索引运算符),并且编写了一种方法trace用于计算其对角元素的总和:

double Matrix5x5::trace(void){
    double t(0.0);
    for(int i(0); i <= 4; ++i){
        t += (*this)[i][i];
    }
    return t;
}

当然,如果我改为写:

return (*this)[0][0]+(*this)[1][1]+(*this)[2][2]+(*this)[3][3]+(*this)[4][4];

然后,我将确保避免声明和递增我的i变量的开销。但是写出所有这些术语感觉很愚蠢!

由于我的循环中有constexpr个词的数量非常少,因此编译器会为我内联吗?

2 个答案:

答案 0 :(得分:1)

如果编译器足够聪明,则可以使用as-if rule优化这种情况。 C ++编译器可能以这种方式优化了很多东西。但这也可能不会。绝对确定的唯一方法是检查特定编译器生成的代码。话虽如此,这不太可能成为您程序中的瓶颈。哪个版本的可读性也更高。

答案 1 :(得分:1)

是的! GCC在优化级别-O1及更高级别执行此操作,而clang在优化级别-O2及更高级别执行此操作。

我使用以下代码对其进行了测试:

struct Matrix5x5 {
    double values[5][5];
    Matrix5x5() : values() {}

    double trace() {
        double sum = 0.0;
        for(int i = 0; i < 5; i++) {
            sum += values[i][i]; 
        }
        return sum; 
    }
};

double trace_of(Matrix5x5& m) {
    return m.trace(); 
}

这是gcc和clang生成的程序集:

trace_of(Matrix5x5&):
    pxor    xmm0, xmm0
    addsd   xmm0, QWORD PTR [rdi]
    addsd   xmm0, QWORD PTR [rdi+48]
    addsd   xmm0, QWORD PTR [rdi+96]
    addsd   xmm0, QWORD PTR [rdi+144]
    addsd   xmm0, QWORD PTR [rdi+192]
    ret

您可以试用代码,并在此处查看相应的程序集:https://godbolt.org/z/p2uF0E

如果您重载operator[],则必须将优化级别提高到-O3,但是编译器仍会这样做:https://godbolt.org/z/JInIME