diff --git a/src/lj_iropt.h b/src/lj_iropt.h index dd1128bc..82dc2e27 100644 --- a/src/lj_iropt.h +++ b/src/lj_iropt.h @@ -141,6 +141,7 @@ LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_cindex(jit_State *J, TRef key); #endif LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc, IROp op); +LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc); LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc); LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc); LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase); diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index 325b0372..edd376c9 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c @@ -701,7 +701,7 @@ LJFOLDF(shortcut_dropleft) } /* Note: no safe shortcuts with STRTO and TOSTR ("1e2" ==> +100 ==> "100"). */ -LJFOLD(NEG NEG KNUM) +LJFOLD(NEG NEG any) LJFOLD(BNOT BNOT) LJFOLD(BSWAP BSWAP) LJFOLDF(shortcut_leftleft) @@ -1067,6 +1067,18 @@ LJFOLDF(simplify_intsub_k) return RETRYFOLD; } +LJFOLD(SUB KINT any) +LJFOLD(SUB KINT64 any) +LJFOLDF(simplify_intsub_kleft) +{ + if (fleft->o == IR_KINT ? (fleft->i == 0) : (ir_kint64(fleft)->u64 == 0)) { + fins->o = IR_NEG; /* 0 - i ==> -i */ + fins->op1 = fins->op2; + return RETRYFOLD; + } + return NEXTFOLD; +} + LJFOLD(ADD any KINT64) LJFOLDF(simplify_intadd_k64) { diff --git a/src/lj_opt_narrow.c b/src/lj_opt_narrow.c index 1727e9b5..e7f280ec 100644 --- a/src/lj_opt_narrow.c +++ b/src/lj_opt_narrow.c @@ -535,6 +535,21 @@ TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc, return emitir(IRTN(op), rb, rc); } +/* Narrowing of unary minus operator. */ +TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc) +{ + if (tref_isstr(rc)) { + rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0); + lj_str_tonum(strV(vc), vc); + } + if (tref_isinteger(rc)) { + if ((uint32_t)numberVint(vc) != 0x80000000u) + return emitir(IRTGI(IR_SUBOV), lj_ir_kint(J, 0), rc); + rc = emitir(IRTN(IR_CONV), rc, IRCONV_NUM_INT); + } + return emitir(IRTN(IR_NEG), rc, lj_ir_knum_neg(J)); +} + /* Narrowing of modulo operator. */ TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc) { diff --git a/src/lj_record.c b/src/lj_record.c index 613e458e..ea23c758 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -1666,8 +1666,7 @@ void lj_record_ins(jit_State *J) case BC_UNM: if (tref_isnumber_str(rc)) { - rc = lj_ir_tonum(J, rc); - rc = emitir(IRTN(IR_NEG), rc, lj_ir_knum_neg(J)); + rc = lj_opt_narrow_unm(J, rc, &ix.tabv); } else { ix.tab = rc; copyTV(J->L, &ix.tabv, &ix.keyv);