From 707c12bf00dafdfd3899b1a6c36435dbbf6c7022 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Fri, 9 Jan 2026 18:46:32 +0100 Subject: DUALNUM: Improve/fix edge cases of unary minus. Thanks to Sergey Kaplun. #1422 #1418 --- src/lj_opt_narrow.c | 5 ++--- src/vm_arm.dasc | 5 ++++- src/vm_arm64.dasc | 2 ++ src/vm_mips.dasc | 6 +++++- src/vm_mips64.dasc | 6 +++++- src/vm_ppc.dasc | 7 ++++++- src/vm_x64.dasc | 4 ++++ src/vm_x86.dasc | 5 +++++ 8 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/lj_opt_narrow.c b/src/lj_opt_narrow.c index db5e8b5b..593bec39 100644 --- a/src/lj_opt_narrow.c +++ b/src/lj_opt_narrow.c @@ -545,10 +545,9 @@ TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc) rc = conv_str_tonum(J, rc, vc); if (tref_isinteger(rc)) { uint32_t k = (uint32_t)numberVint(vc); - if ((tvisint(vc) || k != 0) && k != 0x80000000u) { + if (k != 0 && k != 0x80000000u) { TRef zero = lj_ir_kint(J, 0); - if (!tvisint(vc)) - emitir(IRTGI(IR_NE), rc, zero); + emitir(IRTGI(IR_NE), rc, zero); return emitir(IRTGI(IR_SUBOV), zero, rc); } rc = emitir(IRTN(IR_CONV), rc, IRCONV_NUM_INT); diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc index d99cdaca..d67dbffc 100644 --- a/src/vm_arm.dasc +++ b/src/vm_arm.dasc @@ -3125,13 +3125,16 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | bhi ->vmeta_unm | eorne CARG2, CARG2, #0x80000000 | bne >5 - | rsbseq CARG1, CARG1, #0 + | rsbs CARG1, CARG1, #0 + | ldrdeq CARG12, >8 | ldrdvs CARG12, >9 |5: | strd CARG12, [BASE, RA] | ins_next3 | |.align 8 + |8: + | .long 0x00000000, 0x80000000 // -0. |9: | .long 0x00000000, 0x41e00000 // 2^31. break; diff --git a/src/vm_arm64.dasc b/src/vm_arm64.dasc index a0789efb..be8b76a7 100644 --- a/src/vm_arm64.dasc +++ b/src/vm_arm64.dasc @@ -2687,6 +2687,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | movz CARG3, #0x41e0, lsl #48 // 2^31. | add_TISNUM TMP0, TMP0 | csel TMP0, TMP0, CARG3, vc + | movz CARG3, #0x8000, lsl #48 // -0. + | csel TMP0, TMP0, CARG3, ne |5: | str TMP0, [BASE, RA, lsl #3] | ins_next diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc index 5063e7c6..9a39edd6 100644 --- a/src/vm_mips.dasc +++ b/src/vm_mips.dasc @@ -3566,7 +3566,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | addu RA, BASE, RA | bne SFARG1HI, TISNUM, >2 |. lw SFARG1LO, LO(RB) - | lui TMP1, 0x8000 + | beqz SFARG1LO, >3 + |. lui TMP1, 0x8000 | beq SFARG1LO, TMP1, ->vmeta_unm // Meta handler deals with -2^31. |. negu SFARG1LO, SFARG1LO |1: @@ -3580,6 +3581,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) |. lui TMP1, 0x8000 | b <1 |. xor SFARG1HI, SFARG1HI, TMP1 + |3: + | b <1 + |. lui SFARG1HI, 0x8000 // -0. break; case BC_LEN: | // RA = dst*8, RD = src*8 diff --git a/src/vm_mips64.dasc b/src/vm_mips64.dasc index 8365da8e..310269ce 100644 --- a/src/vm_mips64.dasc +++ b/src/vm_mips64.dasc @@ -3804,7 +3804,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | sextw CARG1, CARG1 | beq CARG1, TMP1, ->vmeta_unm // Meta handler deals with -2^31. |. negu CARG1, CARG1 - | zextw CARG1, CARG1 + | beqz CARG1, >3 + |. zextw CARG1, CARG1 | settp CARG1, TISNUM |1: | ins_next1 @@ -3816,6 +3817,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) |. dsll TMP1, TMP1, 32 | b <1 |. xor CARG1, CARG1, TMP1 + |3: + | b <1 + |. dsll CARG1, TMP1, 32 break; case BC_LEN: | // RA = dst*8, RD = src*8 diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc index 37be772d..440bf1c4 100644 --- a/src/vm_ppc.dasc +++ b/src/vm_ppc.dasc @@ -3962,11 +3962,13 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | bne >5 |.if GPR64 | lus TMP2, 0x8000 - | neg TMP0, TMP0 + | neg. TMP0, TMP0 + | beq >8 | cmplw TMP0, TMP2 | beq >4 |.else | nego. TMP0, TMP0 + | beq >8 | bso >4 |1: |.endif @@ -3993,6 +3995,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | stw TMP0, 4(RA) |.if DUALNUM | b <3 + |8: + | lus TMP1, 0x8000 // -0. + | b <7 |.else | ins_next2 |.endif diff --git a/src/vm_x64.dasc b/src/vm_x64.dasc index a2fa9bfa..9e0f58fd 100644 --- a/src/vm_x64.dasc +++ b/src/vm_x64.dasc @@ -3266,11 +3266,15 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) |.if DUALNUM | checkint RB, >5 | neg RBd + | jz >3 | jo >4 | setint RB |9: | mov [BASE+RA*8], RB | ins_next + |3: + | mov64 RB, U64x(80000000,00000000) // -0. + | jmp <9 |4: | mov64 RB, U64x(41e00000,00000000) // 2^31. | jmp <9 diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc index d7d82b32..7e3d68a0 100644 --- a/src/vm_x86.dasc +++ b/src/vm_x86.dasc @@ -3856,11 +3856,16 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop) | checkint RD, >5 | mov RB, [BASE+RD*8] | neg RB + | jz >3 | jo >4 | mov dword [BASE+RA*8+4], LJ_TISNUM + |8: | mov dword [BASE+RA*8], RB |9: | ins_next + |3: + | mov dword [BASE+RA*8+4], 0x80000000 // -0. + | jmp <8 |4: | mov dword [BASE+RA*8+4], 0x41e00000 // 2^31. | mov dword [BASE+RA*8], 0 -- cgit v1.2.3-55-g6feb