BZK*_*ZKN 14 c++ assembly loops clang compiler-optimization
为了更好地理解编译器,特别是汇编语言,我一直在尝试一段简单的代码,其中N计算第一个数字的总和,这应该导致N(N+1)/2or N(N-1)/2。
正如代码所示,有两个函数:
#include <cstdint>
// Once compiled with optimization, the generated assembly has a loop
uint64_t sum1( uint64_t n ) {
uint64_t sum = 0;
for ( uint64_t j=0; j<=n; ++j ) {
sum += j;
}
return sum;
}
// Once compiled with optimization, the generated assembly of the following has no loop
uint64_t sum2( uint64_t n ) {
uint64_t sum = 0;
for ( uint64_t j=0; j<n; ++j ) {
sum += j;
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
在第一个函数中,我从O 循环到 N ie j<=n,在第二个函数中,我从O 循环到 N-1 ie j<n。
我的理解/观察:
对于第一个函数,sum1生成的程序集有一个循环,而对于第二个函数,sum2程序集没有显示循环。但是,一旦我删除了编译器优化-O3,即,您终于可以看到汇编中第二个函数的循环。
要查看经过编译器优化生成的程序集,请参阅此Optimized。
要查看生成的未经编译器优化的程序集,请参阅此非优化的.
编译器是x86-64 clang
问题:为什么编译器优化不显示程序集中的其他循环?
Sam*_*hik 16
这是因为你的编译器非常非常聪明,它知道从 0 到 n 的所有值的总和可以用一个简单的数学公式来计算,而不是循环。
然而,您的 C++ 编译器还发现这个数学公式不能在该<=版本中使用,因为对于某些输入值,会触发错误,从而导致无限循环,因此所有的赌注都会被取消,并且编译器会完全按照给定的方式编译代码。