编译时循环优化

Compile-time loop optimisation

本文关键字:优化 循环 编译      更新时间:2023-10-16

我发现很难理解为什么以下会导致编译时间计算。我已经读过这个,这个,这个关于stackoverflow的更多问题告诉我以下代码(至少要涉及我的理解),因此不应在编译时间计算,因为该循环是一个循环(该代码只是说明问题的示例):

template< unsigned N >
constexpr unsigned isStringNice(const char (&arr)[N], unsigned pos = 0)
{
    //we do not like the 'D' char :)
    int currPos = 0;
    while(currPos < N){
        if(arr [currPos] == 'D'){
            throw 1;
        }
        currPos ++;
    }
    return 1;
}
constexpr unsigned isIdxValid( unsigned idx, unsigned len){
    return idx >= len?  throw 1 : idx;
}
template< unsigned N >
constexpr char nth_char(const char (&arr)[N], unsigned pos){
  return  isStringNice(arr),isIdxValid(pos, N),arr[pos];
}
int main(){
  constexpr char b = nth_char("ABC", 2);
  return b;
}

这无标志输出以下装配代码(GCC 8.2,谢谢Godbolt)主:

push    rbp
mov     rbp, rsp
mov     BYTE PTR [rbp-1], 67
mov     eax, 67
pop     rbp
ret

和-o3

main:
        mov     eax, 67
        ret

请注意,因为那里没有跳跃,在当时没有分支,什么也没有。我的印象是,在编译时无法评估循环和循环。但是,编译器(GCC 8.2)在编译时间评估结果。我唯一的想法是由于循环展开而发生这种情况,所以我尝试使用-fno-unroll-loops,但是这导致了相同的装配代码。另一方面,从我的经验中,此标志更像是编译器的建议,而不是保证,而GCC仍可能展开即使设置了标志。

我的问题的简短版本:在编译时如何评估我的constexpr函数中的我的way循环?

在C 14中,constexpr功能要求放松。

以前,在C 11中,constexpr函数只能包含typedef s, static_assert s和 using s,但只有一个返回语句。

在C 14中,可以在constexpr功能体中使用循环。

因为b被声明为constexpr char,因此必须在编译时评估必须评估。然后,编译器优化了isStringNice功能,因为它在运行时不使用。