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