mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-08 07:34:07 +00:00
Add narrowing of modulo operator.
This commit is contained in:
parent
eec28aa9fd
commit
8c5935000d
@ -1110,6 +1110,16 @@ static void asm_intmul(ASMState *as, IRIns *ir)
|
|||||||
if (ra_hasreg(tmp)) emit_dm(as, ARMI_MOV, tmp, right);
|
if (ra_hasreg(tmp)) emit_dm(as, ARMI_MOV, tmp, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void asm_intmod(ASMState *as, IRIns *ir)
|
||||||
|
{
|
||||||
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_vm_modi];
|
||||||
|
IRRef args[2];
|
||||||
|
args[0] = ir->op1;
|
||||||
|
args[1] = ir->op2;
|
||||||
|
asm_setupresult(as, ir, ci);
|
||||||
|
asm_gencall(as, ci, args);
|
||||||
|
}
|
||||||
|
|
||||||
static void asm_bitswap(ASMState *as, IRIns *ir)
|
static void asm_bitswap(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
@ -1652,6 +1662,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
case IR_ADD: case IR_ADDOV: asm_arithop(as, ir, ARMI_ADD); break;
|
case IR_ADD: case IR_ADDOV: asm_arithop(as, ir, ARMI_ADD); break;
|
||||||
case IR_SUB: case IR_SUBOV: asm_arithop(as, ir, ARMI_SUB); break;
|
case IR_SUB: case IR_SUBOV: asm_arithop(as, ir, ARMI_SUB); break;
|
||||||
case IR_MUL: case IR_MULOV: asm_intmul(as, ir); break;
|
case IR_MUL: case IR_MULOV: asm_intmul(as, ir); break;
|
||||||
|
case IR_MOD: asm_intmod(as, ir); break;
|
||||||
|
|
||||||
case IR_NEG: asm_intneg(as, ir, ARMI_RSB); break;
|
case IR_NEG: asm_intneg(as, ir, ARMI_RSB); break;
|
||||||
|
|
||||||
@ -1659,7 +1670,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
case IR_MAX: asm_intmin_max(as, ir, CC_LT); break;
|
case IR_MAX: asm_intmin_max(as, ir, CC_LT); break;
|
||||||
|
|
||||||
case IR_FPMATH: case IR_ATAN2: case IR_LDEXP:
|
case IR_FPMATH: case IR_ATAN2: case IR_LDEXP:
|
||||||
case IR_DIV: case IR_MOD: case IR_POW: case IR_ABS: case IR_TOBIT:
|
case IR_DIV: case IR_POW: case IR_ABS: case IR_TOBIT:
|
||||||
lua_assert(0); /* Unused for LJ_SOFTFP. */
|
lua_assert(0); /* Unused for LJ_SOFTFP. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1651,6 +1651,16 @@ static void asm_arith64(ASMState *as, IRIns *ir, IRCallID id)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void asm_intmod(ASMState *as, IRIns *ir)
|
||||||
|
{
|
||||||
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_vm_modi];
|
||||||
|
IRRef args[2];
|
||||||
|
args[0] = ir->op1;
|
||||||
|
args[1] = ir->op2;
|
||||||
|
asm_setupresult(as, ir, ci);
|
||||||
|
asm_gencall(as, ci, args);
|
||||||
|
}
|
||||||
|
|
||||||
static int asm_swapops(ASMState *as, IRIns *ir)
|
static int asm_swapops(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
IRIns *irl = IR(ir->op1);
|
IRIns *irl = IR(ir->op1);
|
||||||
@ -2499,11 +2509,12 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
break;
|
break;
|
||||||
case IR_MOD:
|
case IR_MOD:
|
||||||
#if LJ_64 && LJ_HASFFI
|
#if LJ_64 && LJ_HASFFI
|
||||||
|
if (!irt_isint(ir->t))
|
||||||
asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 :
|
asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 :
|
||||||
IRCALL_lj_carith_modu64);
|
IRCALL_lj_carith_modu64);
|
||||||
#else
|
else
|
||||||
lua_assert(0);
|
|
||||||
#endif
|
#endif
|
||||||
|
asm_intmod(as, ir);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IR_NEG:
|
case IR_NEG:
|
||||||
|
@ -143,6 +143,7 @@ typedef struct CCallInfo {
|
|||||||
_(lj_gc_barrieruv, 2, FS, NIL, 0) \
|
_(lj_gc_barrieruv, 2, FS, NIL, 0) \
|
||||||
_(lj_mem_newgco, 2, FS, P32, CCI_L) \
|
_(lj_mem_newgco, 2, FS, P32, CCI_L) \
|
||||||
_(lj_math_random_step, 1, FS, NUM, CCI_CASTU64|CCI_NOFPRCLOBBER) \
|
_(lj_math_random_step, 1, FS, NUM, CCI_CASTU64|CCI_NOFPRCLOBBER) \
|
||||||
|
_(lj_vm_modi, 2, FN, INT, 0) \
|
||||||
IRCALLDEF_SOFTFP(_) \
|
IRCALLDEF_SOFTFP(_) \
|
||||||
IRCALLDEF_FPMATH(_) \
|
IRCALLDEF_FPMATH(_) \
|
||||||
IRCALLDEF_FFI(_) \
|
IRCALLDEF_FFI(_) \
|
||||||
|
@ -141,7 +141,7 @@ LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_cindex(jit_State *J, TRef key);
|
|||||||
LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
|
LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
|
||||||
TValue *vb, TValue *vc, IROp op);
|
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_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_mod(jit_State *J, TRef rb, TRef rc, TValue *vc);
|
||||||
LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc);
|
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);
|
LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase);
|
||||||
|
|
||||||
|
@ -231,6 +231,7 @@ static int32_t kfold_intop(int32_t k1, int32_t k2, IROp op)
|
|||||||
case IR_ADD: k1 += k2; break;
|
case IR_ADD: k1 += k2; break;
|
||||||
case IR_SUB: k1 -= k2; break;
|
case IR_SUB: k1 -= k2; break;
|
||||||
case IR_MUL: k1 *= k2; break;
|
case IR_MUL: k1 *= k2; break;
|
||||||
|
case IR_MOD: k1 = lj_vm_modi(k1, k2); break;
|
||||||
case IR_BAND: k1 &= k2; break;
|
case IR_BAND: k1 &= k2; break;
|
||||||
case IR_BOR: k1 |= k2; break;
|
case IR_BOR: k1 |= k2; break;
|
||||||
case IR_BXOR: k1 ^= k2; break;
|
case IR_BXOR: k1 ^= k2; break;
|
||||||
@ -249,6 +250,7 @@ static int32_t kfold_intop(int32_t k1, int32_t k2, IROp op)
|
|||||||
LJFOLD(ADD KINT KINT)
|
LJFOLD(ADD KINT KINT)
|
||||||
LJFOLD(SUB KINT KINT)
|
LJFOLD(SUB KINT KINT)
|
||||||
LJFOLD(MUL KINT KINT)
|
LJFOLD(MUL KINT KINT)
|
||||||
|
LJFOLD(MOD KINT KINT)
|
||||||
LJFOLD(BAND KINT KINT)
|
LJFOLD(BAND KINT KINT)
|
||||||
LJFOLD(BOR KINT KINT)
|
LJFOLD(BOR KINT KINT)
|
||||||
LJFOLD(BXOR KINT KINT)
|
LJFOLD(BXOR KINT KINT)
|
||||||
@ -1148,7 +1150,6 @@ LJFOLDF(simplify_intmul_k32)
|
|||||||
|
|
||||||
LJFOLD(MUL any KINT64)
|
LJFOLD(MUL any KINT64)
|
||||||
LJFOLDF(simplify_intmul_k64)
|
LJFOLDF(simplify_intmul_k64)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (ir_kint64(fright)->u64 == 0) /* i * 0 ==> 0 */
|
if (ir_kint64(fright)->u64 == 0) /* i * 0 ==> 0 */
|
||||||
return INT64FOLD(0);
|
return INT64FOLD(0);
|
||||||
@ -1160,6 +1161,27 @@ LJFOLDF(simplify_intmul_k64)
|
|||||||
return NEXTFOLD;
|
return NEXTFOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LJFOLD(MOD any KINT)
|
||||||
|
LJFOLDF(simplify_intmod_k)
|
||||||
|
{
|
||||||
|
int32_t k = fright->i;
|
||||||
|
lua_assert(k != 0);
|
||||||
|
if (k > 0 && (k & (k-1)) == 0) { /* i % (2^k) ==> i & (2^k-1) */
|
||||||
|
fins->o = IR_BAND;
|
||||||
|
fins->op2 = lj_ir_kint(J, k-1);
|
||||||
|
return RETRYFOLD;
|
||||||
|
}
|
||||||
|
return NEXTFOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJFOLD(MOD KINT any)
|
||||||
|
LJFOLDF(simplify_intmod_kleft)
|
||||||
|
{
|
||||||
|
if (fleft->i == 0)
|
||||||
|
return INTFOLD(0);
|
||||||
|
return NEXTFOLD;
|
||||||
|
}
|
||||||
|
|
||||||
LJFOLD(SUB any any)
|
LJFOLD(SUB any any)
|
||||||
LJFOLD(SUBOV any any)
|
LJFOLD(SUBOV any any)
|
||||||
LJFOLDF(simplify_intsub)
|
LJFOLDF(simplify_intsub)
|
||||||
|
@ -551,16 +551,16 @@ TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Narrowing of modulo operator. */
|
/* Narrowing of modulo operator. */
|
||||||
TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc)
|
TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc)
|
||||||
{
|
{
|
||||||
TRef tmp;
|
TRef tmp;
|
||||||
if ((J->flags & JIT_F_OPT_NARROW) &&
|
if (tvisstr(vc) && !lj_str_tonum(strV(vc), vc))
|
||||||
tref_isk(rc) && tref_isint(rc)) { /* Optimize x % k. */
|
lj_trace_err(J, LJ_TRERR_BADTYPE);
|
||||||
int32_t k = IR(tref_ref(rc))->i;
|
if ((LJ_DUALNUM || (J->flags & JIT_F_OPT_NARROW)) &&
|
||||||
if (k > 0 && (k & (k-1)) == 0) { /* i % 2^k ==> band(i, 2^k-1) */
|
tref_isinteger(rb) && tref_isinteger(rc) &&
|
||||||
if (tref_isinteger(rb))
|
(tvisint(vc) ? intV(vc) != 0 : !tviszero(vc))) {
|
||||||
return emitir(IRTI(IR_BAND), rb, lj_ir_kint(J, k-1));
|
emitir(IRTGI(IR_NE), rc, lj_ir_kint(J, 0));
|
||||||
}
|
return emitir(IRTI(IR_MOD), rb, rc);
|
||||||
}
|
}
|
||||||
/* b % c ==> b - floor(b/c)*c */
|
/* b % c ==> b - floor(b/c)*c */
|
||||||
rb = lj_ir_tonum(J, rb);
|
rb = lj_ir_tonum(J, rb);
|
||||||
|
@ -1715,7 +1715,7 @@ void lj_record_ins(jit_State *J)
|
|||||||
case BC_MODVN: case BC_MODVV:
|
case BC_MODVN: case BC_MODVV:
|
||||||
recmod:
|
recmod:
|
||||||
if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
|
if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
|
||||||
rc = lj_opt_narrow_mod(J, rb, rc);
|
rc = lj_opt_narrow_mod(J, rb, rc, rcv);
|
||||||
else
|
else
|
||||||
rc = rec_mm_arith(J, &ix, MM_mod);
|
rc = rec_mm_arith(J, &ix, MM_mod);
|
||||||
break;
|
break;
|
||||||
|
@ -71,6 +71,7 @@ LJ_ASMF double lj_vm_exp2(double);
|
|||||||
#define lj_vm_exp2 exp2
|
#define lj_vm_exp2 exp2
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
LJ_ASMF int32_t LJ_FASTCALL lj_vm_modi(int32_t, int32_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Continuations for metamethods. */
|
/* Continuations for metamethods. */
|
||||||
|
@ -39,6 +39,20 @@ double lj_vm_exp2(double a)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !LJ_TARGET_ARM
|
||||||
|
int32_t LJ_FASTCALL lj_vm_modi(int32_t a, int32_t b)
|
||||||
|
{
|
||||||
|
uint32_t y, ua, ub;
|
||||||
|
lua_assert(b != 0); /* This must be checked before using this function. */
|
||||||
|
ua = a < 0 ? -(uint32_t)a : (uint32_t)a;
|
||||||
|
ub = b < 0 ? -(uint32_t)b : (uint32_t)b;
|
||||||
|
y = ua % ub;
|
||||||
|
if (y != 0 && (a^b) < 0) y = y - ub;
|
||||||
|
if (((int32_t)y^b) < 0) y = -y;
|
||||||
|
return (int32_t)y;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !LJ_TARGET_X86ORX64
|
#if !LJ_TARGET_X86ORX64
|
||||||
/* Unsigned x^k. */
|
/* Unsigned x^k. */
|
||||||
static double lj_vm_powui(double x, uint32_t k)
|
static double lj_vm_powui(double x, uint32_t k)
|
||||||
|
Loading…
Reference in New Issue
Block a user