MSVC 不良装配生成

Dav*_*ger 5 c++ assembly gcc clang visual-c++

比较 MSVC、clang 和 GCC 中生成的程序集时。MSVC 程序集似乎比 Clang 代码差得多。


问题

GCC 和 MSVC 中是否有一个必需的标志来生成等效的程序集,或者在这种特定情况下 Clang 更好。我尝试了各种 MSVC 标志(不同的 /O 标志),但没有发生实质性变化。

或者我的代码是否有变化,可以让编译器实现更好的优化。我尝试过改变代码而不丢失基本结构也没有改变。


代码

我正在编译的代码只有 26 行,所以这里是:

#include <cstdint>
#include <type_traits>

template <typename A, typename B>
struct BitCast
{
    static_assert(std::is_pod<A>(), "BitCast<A, B> : A must be plain old data type.");
    static_assert(std::is_pod<B>(), "BitCast<A, B> : B must be plain old data type.");
    static_assert(sizeof(A) == sizeof(B), "BitCast<A, B> : A and B must be the same size.");
    static_assert(alignof(A) == alignof(B), "BitCast<A, B> : A and B must have the same alignment.");
    //
    union
    {
        A a;
        B b;
    };
    //
    constexpr BitCast(A const & value) noexcept : a{ value } {}
    constexpr BitCast(B const & value) noexcept : b{ value } {}
    //
    operator B const & () const noexcept { return b; }
};

float XOR(float a, float b) noexcept
{
    return BitCast<uint32_t, float>{ BitCast<float, uint32_t>{a} ^ BitCast<float, uint32_t>{b} };
}
Run Code Online (Sandbox Code Playgroud)

我一直在 godbolt 工作,以确定差异的原因https://godbolt.org/z/-VXqOT


Clang 9.0.0 与“-std=c++1z -O3”产生了一个漂亮的:

XOR(float, float):
        xorps   xmm0, xmm1
        ret
Run Code Online (Sandbox Code Playgroud)

我认为这基本上是最佳的。


使用“-std=c++1z -O3”的 GCC 9.2 产生的结果稍差:

XOR(float, float):
        movd    eax, xmm1
        movd    edx, xmm0
        xor     edx, eax
        movd    xmm0, edx
        ret
Run Code Online (Sandbox Code Playgroud)

然后带有“/std:c++latest /O2”的 MSVC 产生了更糟糕的结果:

float XOR(float,float)
        movss   DWORD PTR $T1[rsp], xmm1
        mov     eax, DWORD PTR $T1[rsp]
        movss   DWORD PTR $T3[rsp], xmm0
        xor     eax, DWORD PTR $T3[rsp]
        mov     DWORD PTR $T2[rsp], eax
        movss   xmm0, DWORD PTR $T2[rsp]
        ret     0
Run Code Online (Sandbox Code Playgroud)