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); 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;

View File

@ -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:

View File

@ -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(_) \

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, 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);

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_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)

View File

@ -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);

View File

@ -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;

View File

@ -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. */

View File

@ -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)