【发布时间】:2014-07-18 12:43:10
【问题描述】:
如果我使用 -O3 -fno-vectorize 使用 Clang 3.3 编译以下代码,即使我删除了注释行,我也会得到相同的汇编输出。代码类型将所有可能的 32 位整数双关语为浮点数,并对 [0, 1] 范围内的整数进行计数。 Clang 的优化器是否真的足够聪明,可以意识到 0xFFFFFFFF 在双关语浮动时不在 [0, 1] 范围内,所以完全忽略对 fn 的第二次调用?当第二次调用被移除时,GCC 会产生不同的代码。
#include <limits>
#include <cstring>
#include <cstdint>
template <class TO, class FROM>
inline TO punning_cast(const FROM &input)
{
TO out;
std::memcpy(&out, &input, sizeof(TO));
return out;
}
int main()
{
uint32_t count = 0;
auto fn = [&count] (uint32_t x) {
float f = punning_cast<float>(x);
if (f >= 0.0f && f <= 1.0f)
count++;
};
for(uint32_t i = 0; i < std::numeric_limits<uint32_t>::max(); ++i)
{
fn(i);
}
fn(std::numeric_limits<uint32_t>::max()); //removing this changes nothing
return count;
}
请看这里:http://goo.gl/YZPw5i
【问题讨论】:
-
count在这两种情况下都正确吗? -
Clang 习惯于大规模优化仅常量函数(有效地对它们进行非常复杂的常量折叠)。 Figure 1.
-
@9dan 如今在现代 C 库和编译器中,
memcpy几乎总是一个编译器内部函数。 -
@9dan:这不是“了解 memcpy 的内部结构”(这可能需要编译器了解手动优化的库实现),而更多的是“了解 memcpy 的预期功能”。 C/C++ 允许您基本上执行您喜欢的任何优化,只要结果相对于规范没有变化。由于
memcpy是由C/C++指定的,原则上只要结果相同,就可以任意优化。
标签: c++ c++11 clang llvm compiler-optimization