Add narrowing of modulo operator.

This commit is contained in:
Mike Pall 2011-06-03 18:48:02 +02:00
parent eec28aa9fd
commit 8c5935000d
9 changed files with 76 additions and 16 deletions

View File

@ -1110,6 +1110,16 @@ static void asm_intmul(ASMState *as, IRIns *ir)
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)
{
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_SUB: case IR_SUBOV: asm_arithop(as, ir, ARMI_SUB); 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;
@ -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_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. */
break;

View File

@ -1651,6 +1651,16 @@ static void asm_arith64(ASMState *as, IRIns *ir, IRCallID id)
}
#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)
{
IRIns *irl = IR(ir->op1);
@ -2499,11 +2509,12 @@ static void asm_ir(ASMState *as, IRIns *ir)
break;
case IR_MOD:
#if LJ_64 && LJ_HASFFI
asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 :
IRCALL_lj_carith_modu64);
#else
lua_assert(0);
if (!irt_isint(ir->t))
asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 :
IRCALL_lj_carith_modu64);
else
#endif
asm_intmod(as, ir);
break;
case IR_NEG:

View File

@ -143,6 +143,7 @@ typedef struct CCallInfo {
_(lj_gc_barrieruv, 2, FS, NIL, 0) \
_(lj_mem_newgco, 2, FS, P32, CCI_L) \
_(lj_math_random_step, 1, FS, NUM, CCI_CASTU64|CCI_NOFPRCLOBBER) \
_(lj_vm_modi, 2, FN, INT, 0) \
IRCALLDEF_SOFTFP(_) \
IRCALLDEF_FPMATH(_) \
IRCALLDEF_FFI(_) \

View File

@ -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,
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_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 IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase);

View File

@ -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_SUB: 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_BOR: 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(SUB KINT KINT)
LJFOLD(MUL KINT KINT)
LJFOLD(MOD KINT KINT)
LJFOLD(BAND KINT KINT)
LJFOLD(BOR KINT KINT)
LJFOLD(BXOR KINT KINT)
@ -1148,7 +1150,6 @@ LJFOLDF(simplify_intmul_k32)
LJFOLD(MUL any KINT64)
LJFOLDF(simplify_intmul_k64)
{
if (ir_kint64(fright)->u64 == 0) /* i * 0 ==> 0 */
return INT64FOLD(0);
@ -1160,6 +1161,27 @@ LJFOLDF(simplify_intmul_k64)
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(SUBOV any any)
LJFOLDF(simplify_intsub)

View File

@ -551,16 +551,16 @@ TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc)
}
/* 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;
if ((J->flags & JIT_F_OPT_NARROW) &&
tref_isk(rc) && tref_isint(rc)) { /* Optimize x % k. */
int32_t k = IR(tref_ref(rc))->i;
if (k > 0 && (k & (k-1)) == 0) { /* i % 2^k ==> band(i, 2^k-1) */
if (tref_isinteger(rb))
return emitir(IRTI(IR_BAND), rb, lj_ir_kint(J, k-1));
}
if (tvisstr(vc) && !lj_str_tonum(strV(vc), vc))
lj_trace_err(J, LJ_TRERR_BADTYPE);
if ((LJ_DUALNUM || (J->flags & JIT_F_OPT_NARROW)) &&
tref_isinteger(rb) && tref_isinteger(rc) &&
(tvisint(vc) ? intV(vc) != 0 : !tviszero(vc))) {
emitir(IRTGI(IR_NE), rc, lj_ir_kint(J, 0));
return emitir(IRTI(IR_MOD), rb, rc);
}
/* b % c ==> b - floor(b/c)*c */
rb = lj_ir_tonum(J, rb);

View File

@ -1715,7 +1715,7 @@ void lj_record_ins(jit_State *J)
case BC_MODVN: case BC_MODVV:
recmod:
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
rc = rec_mm_arith(J, &ix, MM_mod);
break;

View File

@ -71,6 +71,7 @@ LJ_ASMF double lj_vm_exp2(double);
#define lj_vm_exp2 exp2
#endif
#endif
LJ_ASMF int32_t LJ_FASTCALL lj_vm_modi(int32_t, int32_t);
#endif
/* Continuations for metamethods. */

View File

@ -39,6 +39,20 @@ double lj_vm_exp2(double a)
}
#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
/* Unsigned x^k. */
static double lj_vm_powui(double x, uint32_t k)