以下代码在没有任何优化标志的情况下与没有任何优化标志的情况下编译时给出了截然不同的结果:
#include <iostream>
#include <cstdint>
// trailing zero count for __uint128_t
int u128_ctz(__uint128_t n) {
int count_hi = __builtin_ctzll(uint64_t(n >> 64));
int count_lo = __builtin_ctzll(uint64_t(n));
return count_lo == 64 ? 64 + count_hi : count_lo;
}
int main() {
__uint128_t one = 1;
__uint128_t t = one << 122;
std::cout << u128_ctz(t) << '\n';
return 0;
}
当用
g++ main.cpp
简单编译时,如我所料打印了122。然而,经过优化,结果变为 64。
我最初认为这可能是由于我使用了激进的优化标志,但即使
g++ -O1 main.cpp
显示结果为 64。我还认为 __builtin_ctzll(0ull)
可能由于某种原因未定义,但无论我使用什么编译标志,它都会返回 64。
这是编译器错误吗?这里究竟发生了什么?
int u128_ctz(__uint128_t n) {
int count_hi = __builtin_ctzll(uint64_t(n >> 64));
int count_lo = __builtin_ctzll(uint64_t(n));
if (count_lo == 64) {
std::cout << "count_lo == 64\n";
}
return count_lo == 64 ? 64 + count_hi : count_lo;
}
在打印之前添加 if 语句后,O1 优化似乎假定 count_lo 永远不会返回 64,因此它忽略了我的条件并直接返回 count_lo。