DUALNUM: Improve/fix edge cases of unary minus.

Thanks to Sergey Kaplun. #1422 #1418
This commit is contained in:
Mike Pall
2026-01-09 18:46:32 +01:00
parent 3015b6187e
commit 707c12bf00
8 changed files with 33 additions and 7 deletions

View File

@@ -545,9 +545,8 @@ TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc)
rc = conv_str_tonum(J, rc, vc); rc = conv_str_tonum(J, rc, vc);
if (tref_isinteger(rc)) { if (tref_isinteger(rc)) {
uint32_t k = (uint32_t)numberVint(vc); 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); 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); return emitir(IRTGI(IR_SUBOV), zero, rc);
} }

View File

@@ -3125,13 +3125,16 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| bhi ->vmeta_unm | bhi ->vmeta_unm
| eorne CARG2, CARG2, #0x80000000 | eorne CARG2, CARG2, #0x80000000
| bne >5 | bne >5
| rsbseq CARG1, CARG1, #0 | rsbs CARG1, CARG1, #0
| ldrdeq CARG12, >8
| ldrdvs CARG12, >9 | ldrdvs CARG12, >9
|5: |5:
| strd CARG12, [BASE, RA] | strd CARG12, [BASE, RA]
| ins_next3 | ins_next3
| |
|.align 8 |.align 8
|8:
| .long 0x00000000, 0x80000000 // -0.
|9: |9:
| .long 0x00000000, 0x41e00000 // 2^31. | .long 0x00000000, 0x41e00000 // 2^31.
break; break;

View File

@@ -2687,6 +2687,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| movz CARG3, #0x41e0, lsl #48 // 2^31. | movz CARG3, #0x41e0, lsl #48 // 2^31.
| add_TISNUM TMP0, TMP0 | add_TISNUM TMP0, TMP0
| csel TMP0, TMP0, CARG3, vc | csel TMP0, TMP0, CARG3, vc
| movz CARG3, #0x8000, lsl #48 // -0.
| csel TMP0, TMP0, CARG3, ne
|5: |5:
| str TMP0, [BASE, RA, lsl #3] | str TMP0, [BASE, RA, lsl #3]
| ins_next | ins_next

View File

@@ -3566,7 +3566,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| addu RA, BASE, RA | addu RA, BASE, RA
| bne SFARG1HI, TISNUM, >2 | bne SFARG1HI, TISNUM, >2
|. lw SFARG1LO, LO(RB) |. lw SFARG1LO, LO(RB)
| lui TMP1, 0x8000 | beqz SFARG1LO, >3
|. lui TMP1, 0x8000
| beq SFARG1LO, TMP1, ->vmeta_unm // Meta handler deals with -2^31. | beq SFARG1LO, TMP1, ->vmeta_unm // Meta handler deals with -2^31.
|. negu SFARG1LO, SFARG1LO |. negu SFARG1LO, SFARG1LO
|1: |1:
@@ -3580,6 +3581,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|. lui TMP1, 0x8000 |. lui TMP1, 0x8000
| b <1 | b <1
|. xor SFARG1HI, SFARG1HI, TMP1 |. xor SFARG1HI, SFARG1HI, TMP1
|3:
| b <1
|. lui SFARG1HI, 0x8000 // -0.
break; break;
case BC_LEN: case BC_LEN:
| // RA = dst*8, RD = src*8 | // RA = dst*8, RD = src*8

View File

@@ -3804,7 +3804,8 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| sextw CARG1, CARG1 | sextw CARG1, CARG1
| beq CARG1, TMP1, ->vmeta_unm // Meta handler deals with -2^31. | beq CARG1, TMP1, ->vmeta_unm // Meta handler deals with -2^31.
|. negu CARG1, CARG1 |. negu CARG1, CARG1
| zextw CARG1, CARG1 | beqz CARG1, >3
|. zextw CARG1, CARG1
| settp CARG1, TISNUM | settp CARG1, TISNUM
|1: |1:
| ins_next1 | ins_next1
@@ -3816,6 +3817,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|. dsll TMP1, TMP1, 32 |. dsll TMP1, TMP1, 32
| b <1 | b <1
|. xor CARG1, CARG1, TMP1 |. xor CARG1, CARG1, TMP1
|3:
| b <1
|. dsll CARG1, TMP1, 32
break; break;
case BC_LEN: case BC_LEN:
| // RA = dst*8, RD = src*8 | // RA = dst*8, RD = src*8

View File

@@ -3962,11 +3962,13 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| bne >5 | bne >5
|.if GPR64 |.if GPR64
| lus TMP2, 0x8000 | lus TMP2, 0x8000
| neg TMP0, TMP0 | neg. TMP0, TMP0
| beq >8
| cmplw TMP0, TMP2 | cmplw TMP0, TMP2
| beq >4 | beq >4
|.else |.else
| nego. TMP0, TMP0 | nego. TMP0, TMP0
| beq >8
| bso >4 | bso >4
|1: |1:
|.endif |.endif
@@ -3993,6 +3995,9 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| stw TMP0, 4(RA) | stw TMP0, 4(RA)
|.if DUALNUM |.if DUALNUM
| b <3 | b <3
|8:
| lus TMP1, 0x8000 // -0.
| b <7
|.else |.else
| ins_next2 | ins_next2
|.endif |.endif

View File

@@ -3266,11 +3266,15 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|.if DUALNUM |.if DUALNUM
| checkint RB, >5 | checkint RB, >5
| neg RBd | neg RBd
| jz >3
| jo >4 | jo >4
| setint RB | setint RB
|9: |9:
| mov [BASE+RA*8], RB | mov [BASE+RA*8], RB
| ins_next | ins_next
|3:
| mov64 RB, U64x(80000000,00000000) // -0.
| jmp <9
|4: |4:
| mov64 RB, U64x(41e00000,00000000) // 2^31. | mov64 RB, U64x(41e00000,00000000) // 2^31.
| jmp <9 | jmp <9

View File

@@ -3856,11 +3856,16 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| checkint RD, >5 | checkint RD, >5
| mov RB, [BASE+RD*8] | mov RB, [BASE+RD*8]
| neg RB | neg RB
| jz >3
| jo >4 | jo >4
| mov dword [BASE+RA*8+4], LJ_TISNUM | mov dword [BASE+RA*8+4], LJ_TISNUM
|8:
| mov dword [BASE+RA*8], RB | mov dword [BASE+RA*8], RB
|9: |9:
| ins_next | ins_next
|3:
| mov dword [BASE+RA*8+4], 0x80000000 // -0.
| jmp <8
|4: |4:
| mov dword [BASE+RA*8+4], 0x41e00000 // 2^31. | mov dword [BASE+RA*8+4], 0x41e00000 // 2^31.
| mov dword [BASE+RA*8], 0 | mov dword [BASE+RA*8], 0