Open
Description
Instead of sign-extending to 128 bits with a combination of movsx
and sar
, do a combination of movsx
and cqo
, like GCC does:
https://godbolt.org/z/xKb3jfKq7
#include <cstdint>
// clang-format off
using u8 = uint8_t; using i8 = int8_t;
using u16 = uint16_t; using i16 = int16_t;
using u32 = uint32_t; using i32 = int32_t;
using u64 = uint64_t; using i64 = int64_t;
using u128 = __uint128_t; using i128 = __int128_t;
// clang-format on
auto i8_to_i128(i8 x) -> i128 { return x; }
auto i16_to_i128(i16 x) -> i128 { return x; }
auto i32_to_i128(i32 x) -> i128 { return x; }
auto i64_to_i128(i64 x) -> i128 { return x; }
LLVM assembly:
i8_to_i128(signed char):
movsxd rax, edi
sar dil, 7
movsx rdx, dil
ret
i16_to_i128(short):
movsxd rax, edi
mov ecx, eax
shr ecx, 15
movsx rdx, cx
ret
i32_to_i128(int):
movsxd rax, edi
mov ecx, eax
sar ecx, 31
movsxd rdx, ecx
ret
i64_to_i128(long):
mov rax, rdi
mov rdx, rdi
sar rdx, 63
ret
GCC assembly:
"i8_to_i128(signed char)":
movsx rax, dil
cqo
ret
"i16_to_i128(short)":
movsx rax, di
cqo
ret
"i32_to_i128(int)":
movsx rax, edi
cqo
ret
"i64_to_i128(long)":
mov rax, rdi
cqo
ret