MSVC Плохое Поколение Сборки - PullRequest
4 голосов
/ 20 сентября 2019

При сравнении сборок, генерируемых в 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} };
}

Я работал в Godbolt, чтобы определить причину различия https://godbolt.org/z/-VXqOT


Clang 9.0.0 с помощью "-std = c ++1z -O3 "производит красивое:

XOR(float, float):
        xorps   xmm0, xmm1
        ret

Что в принципе является оптимальным, на мой взгляд.


GCC 9.2 с" -std = c ++ 1z -O3 "производитнемного хуже:

XOR(float, float):
        movd    eax, xmm1
        movd    edx, xmm0
        xor     edx, eax
        movd    xmm0, edx
        ret

Тогда MSVC с "/ std: c ++ latest / O2" произвел намного хуже:

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
...