Clang真的这么聪明吗? [英] Is Clang really this smart?

查看:172
本文介绍了Clang真的这么聪明吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用 -O3 -fno-vectorize 使用Clang 3.3编译以下代码,即使我删除了注释行,也会得到相同的汇编输出。代码类型使所有可能的32位整数浮动,并计算[0,1]范围内的值。 Clang的优化器实际上是聪明的,意识到0xFFFFFFFF当被设置为float不在范围[0,1],因此忽略第二次调用 fn 完全?当第二次调用被删除时,GCC产生不同的代码。

If I compile the following code with Clang 3.3 using -O3 -fno-vectorize I get the same assembly output even if I remove the commented line. The code type puns all possible 32-bit integers to floats and counts the ones in a [0, 1] range. Is Clang's optimizer actually smart enough to realize that 0xFFFFFFFF when punned to float is not in the range [0, 1], so ignore the second call to fn entirely? GCC produces different code when the second call is removed.

#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

推荐答案

是的,看起来像Clang真的是这个聪明。

Yes, it looks like Clang really is this smart.

测试:

#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;
}

结果:

$ 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



观察到Clang已将调用转换为 fn(0x3f800000) 变成简单的递增指令,因为值解码为 1.0 。这是正确的。

Observe that Clang has converted the call to fn(0x3f800000) into simply an increment instruction, since the value decodes to 1.0. This is correct.

我的猜测是,Clang正在跟踪函数调用,因为它们只涉及常量,并且Clang能够跟踪 memcpy 通过类型划分(可能通过简单地模拟其对常量值的影响)。

My guess is that Clang is tracing the function calls because they only involve constants, and that Clang is capable of tracing memcpy through type-punning (probably by simply emulating its effect on the constant value).

这篇关于Clang真的这么聪明吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆