Skip to content

[x86] Could use cqo for sign-extending to 128 bits #148652

Open
@Kmeakin

Description

@Kmeakin

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions