From faaf663340347a78b22ed94c63c24fe090bd9784 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 28 Jul 2026 00:44:24 +0200 Subject: [PATCH] x86: Conditionally use SSE3 for 64 bit conversions. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reported by Gero Schwäricke. #1496 #1411 --- src/lib_jit.c | 6 ++++++ src/lj_meta.c | 4 ++-- src/lj_obj.h | 21 ++++++++++++++++++++- src/lj_vmmath.c | 5 +++++ src/vm_x86.dasc | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/lib_jit.c b/src/lib_jit.c index e6c5271f..6e01e374 100644 --- a/src/lib_jit.c +++ b/src/lib_jit.c @@ -657,6 +657,12 @@ static uint32_t jit_cpudetect(void) uint32_t features[4]; if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) { flags |= ((features[2] >> 0)&1) * JIT_F_SSE3; +#if LJ_TARGET_X86 + if (flags) { + lj_vm_num2i64_ptr = lj_vm_num2i64_sse3; + lj_vm_num2u64_ptr = lj_vm_num2u64_sse3; + } +#endif flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1; if (vendor[0] >= 7) { uint32_t xfeatures[4]; diff --git a/src/lj_meta.c b/src/lj_meta.c index ddb37a1a..5a08cf94 100644 --- a/src/lj_meta.c +++ b/src/lj_meta.c @@ -248,10 +248,10 @@ void lj_meta_bitop(lua_State *L, TValue *ra, cTValue *rb, cTValue *rc, BCReg op) uint64_t c = lj_carith_checkbit64(L, rc, op >= BC_BSHL ? &id_ignore : &id); if (id) { if (tvisnum(rb)) { - b = id == CTID_UINT64 ? lj_num2u64(numV(rb)) : lj_num2i64(numV(rb)); + b = id == CTID_UINT64 ? lj_num2u64(numV(rb)) : (uint64_t)lj_num2i64(numV(rb)); } if (tvisnum(rc)) { - c = id == CTID_UINT64 ? lj_num2u64(numV(rc)) : lj_num2i64(numV(rc)); + c = id == CTID_UINT64 ? lj_num2u64(numV(rc)) : (uint64_t)lj_num2i64(numV(rc)); } } switch (op) { diff --git a/src/lj_obj.h b/src/lj_obj.h index 96dc1e0d..30991a7e 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -1035,11 +1035,30 @@ LJ_ASMF LJ_CONSTF int64_t lj_vm_num2int_check(double x); ** The uint64_t conversion accepts the union of the unsigned + signed range. */ LJ_ASMF LJ_CONSTF int64_t lj_vm_num2i64(double x); -LJ_ASMF LJ_CONSTF int64_t lj_vm_num2u64(double x); +LJ_ASMF LJ_CONSTF uint64_t lj_vm_num2u64(double x); + +#if LJ_TARGET_X86 + +LJ_ASMF LJ_CONSTF int64_t lj_vm_num2i64_sse3(double x); +LJ_ASMF LJ_CONSTF uint64_t lj_vm_num2u64_sse3(double x); +LJ_ASMF int64_t (*lj_vm_num2i64_ptr)(double x); +LJ_ASMF uint64_t (*lj_vm_num2u64_ptr)(double x); +static LJ_AINLINE int64_t lj_num2i64(double x) +{ + return (*lj_vm_num2i64_ptr)(x); +} +static LJ_AINLINE uint64_t lj_num2u64(double x) +{ + return (*lj_vm_num2u64_ptr)(x); +} + +#else #define lj_num2i64(x) (lj_vm_num2i64((x))) #define lj_num2u64(x) (lj_vm_num2u64((x))) +#endif + /* Lua BitOp conversion semantics use the 2^52 + 2^51 trick. */ LJ_ASMF LJ_CONSTF int32_t lj_vm_tobit(double x); diff --git a/src/lj_vmmath.c b/src/lj_vmmath.c index 5aca7207..603b913e 100644 --- a/src/lj_vmmath.c +++ b/src/lj_vmmath.c @@ -13,6 +13,11 @@ #include "lj_ir.h" #include "lj_vm.h" +#if LJ_TARGET_X86 +int64_t (*lj_vm_num2i64_ptr)(double x) = lj_vm_num2i64; +uint64_t (*lj_vm_num2u64_ptr)(double x) = lj_vm_num2u64; +#endif + /* -- Wrapper functions --------------------------------------------------- */ #if LJ_TARGET_X86 && __ELF__ && __PIC__ diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc index c201c334..50becd46 100644 --- a/src/vm_x86.dasc +++ b/src/vm_x86.dasc @@ -3140,6 +3140,21 @@ static void build_subroutines(BuildCtx *ctx) |.else | sub esp, 12 | fld qword [esp+16] + | fnstcw word [esp+8] + | mov eax, 0x0c00 + | or ax, word [esp+8] + | mov word [esp+10], ax + | fldcw word [esp+10] + | fistp qword [esp] + | fldcw word [esp+8] + | mov eax, dword [esp] + | mov edx, dword [esp+4] + | add esp, 12 + | ret + | + |->vm_num2i64_sse3: + | sub esp, 12 + | fld qword [esp+16] | fisttp qword [esp] | mov eax, dword [esp] | mov edx, dword [esp+4] @@ -3164,6 +3179,37 @@ static void build_subroutines(BuildCtx *ctx) |.else | sub esp, 12 | fld qword [esp+16] + | fnstcw word [esp+8] + | mov eax, 0x0c00 + | or ax, word [esp+8] + | mov word [esp+10], ax + | fldcw word [esp+10] + | fld st0 + | fistp qword [esp] + | mov edx, dword [esp+4] + | mov eax, dword [esp] + | cmp edx, 1 + | jo >2 + |1: + | fpop + | fldcw word [esp+8] + | add esp, 12 + | ret + |2: + | cmp eax, 0 + | jne <1 + | mov dword [esp], 0xdf800000 // -0x1p64 (float). + | fadd dword [esp] + | fistp qword [esp] + | fldcw word [esp+8] + | mov eax, dword [esp] + | mov edx, dword [esp+4] + | add esp, 12 + | ret + | + |->vm_num2u64_sse3: + | sub esp, 12 + | fld qword [esp+16] | fld st0 | fisttp qword [esp] | mov edx, dword [esp+4] -- 2.47.3