Chr*_*s_F 8 c++ llvm clang compiler-optimization c++11
如果我使用Clang 3.3编译以下代码,-O3 -fno-vectorize即使删除了注释行,也会得到相同的汇编输出.代码类型将所有可能的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;
}
Run Code Online (Sandbox Code Playgroud)
见这里:http://goo.gl/YZPw5i
nne*_*neo 11
是的,看起来Clang真的很聪明.
测试:
#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);
}
#ifdef X
fn(0x3f800000); /* 1.0f */
#endif
return count;
}
Run Code Online (Sandbox Code Playgroud)
结果:
$ c++ -S -DX -O3 foo.cpp -std=c++11 -o foo.s
$ c++ -S -O3 foo.cpp -std=c++11 -o foo2.s
$ diff foo.s foo2.s
100d99
< incl %eax
Run Code Online (Sandbox Code Playgroud)
观察到Clang已将调用转换fn(0x3f800000)为简单的增量指令,因为该值解码为1.0.这是对的.
我的猜测是Clang正在跟踪函数调用,因为它们只涉及常量,并且Clang能够memcpy通过类型惩罚进行跟踪(可能只是通过模拟它对常量值的影响).
| 归档时间: |
|
| 查看次数: |
614 次 |
| 最近记录: |