aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lj_asm_arm.h13
-rw-r--r--src/lj_asm_x86.h19
-rw-r--r--src/lj_ircall.h1
-rw-r--r--src/lj_iropt.h2
-rw-r--r--src/lj_opt_fold.c24
-rw-r--r--src/lj_opt_narrow.c16
-rw-r--r--src/lj_record.c2
-rw-r--r--src/lj_vm.h1
-rw-r--r--src/lj_vmmath.c14
9 files changed, 76 insertions, 16 deletions
diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h
index 5890b54f..74a3a927 100644
--- a/src/lj_asm_arm.h
+++ b/src/lj_asm_arm.h
@@ -1110,6 +1110,16 @@ static void asm_intmul(ASMState *as, IRIns *ir)
1110 if (ra_hasreg(tmp)) emit_dm(as, ARMI_MOV, tmp, right); 1110 if (ra_hasreg(tmp)) emit_dm(as, ARMI_MOV, tmp, right);
1111} 1111}
1112 1112
1113static void asm_intmod(ASMState *as, IRIns *ir)
1114{
1115 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_vm_modi];
1116 IRRef args[2];
1117 args[0] = ir->op1;
1118 args[1] = ir->op2;
1119 asm_setupresult(as, ir, ci);
1120 asm_gencall(as, ci, args);
1121}
1122
1113static void asm_bitswap(ASMState *as, IRIns *ir) 1123static void asm_bitswap(ASMState *as, IRIns *ir)
1114{ 1124{
1115 Reg dest = ra_dest(as, ir, RSET_GPR); 1125 Reg dest = ra_dest(as, ir, RSET_GPR);
@@ -1652,6 +1662,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
1652 case IR_ADD: case IR_ADDOV: asm_arithop(as, ir, ARMI_ADD); break; 1662 case IR_ADD: case IR_ADDOV: asm_arithop(as, ir, ARMI_ADD); break;
1653 case IR_SUB: case IR_SUBOV: asm_arithop(as, ir, ARMI_SUB); break; 1663 case IR_SUB: case IR_SUBOV: asm_arithop(as, ir, ARMI_SUB); break;
1654 case IR_MUL: case IR_MULOV: asm_intmul(as, ir); break; 1664 case IR_MUL: case IR_MULOV: asm_intmul(as, ir); break;
1665 case IR_MOD: asm_intmod(as, ir); break;
1655 1666
1656 case IR_NEG: asm_intneg(as, ir, ARMI_RSB); break; 1667 case IR_NEG: asm_intneg(as, ir, ARMI_RSB); break;
1657 1668
@@ -1659,7 +1670,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
1659 case IR_MAX: asm_intmin_max(as, ir, CC_LT); break; 1670 case IR_MAX: asm_intmin_max(as, ir, CC_LT); break;
1660 1671
1661 case IR_FPMATH: case IR_ATAN2: case IR_LDEXP: 1672 case IR_FPMATH: case IR_ATAN2: case IR_LDEXP:
1662 case IR_DIV: case IR_MOD: case IR_POW: case IR_ABS: case IR_TOBIT: 1673 case IR_DIV: case IR_POW: case IR_ABS: case IR_TOBIT:
1663 lua_assert(0); /* Unused for LJ_SOFTFP. */ 1674 lua_assert(0); /* Unused for LJ_SOFTFP. */
1664 break; 1675 break;
1665 1676
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
index c89bc521..e5bc4a0e 100644
--- a/src/lj_asm_x86.h
+++ b/src/lj_asm_x86.h
@@ -1651,6 +1651,16 @@ static void asm_arith64(ASMState *as, IRIns *ir, IRCallID id)
1651} 1651}
1652#endif 1652#endif
1653 1653
1654static void asm_intmod(ASMState *as, IRIns *ir)
1655{
1656 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_vm_modi];
1657 IRRef args[2];
1658 args[0] = ir->op1;
1659 args[1] = ir->op2;
1660 asm_setupresult(as, ir, ci);
1661 asm_gencall(as, ci, args);
1662}
1663
1654static int asm_swapops(ASMState *as, IRIns *ir) 1664static int asm_swapops(ASMState *as, IRIns *ir)
1655{ 1665{
1656 IRIns *irl = IR(ir->op1); 1666 IRIns *irl = IR(ir->op1);
@@ -2499,11 +2509,12 @@ static void asm_ir(ASMState *as, IRIns *ir)
2499 break; 2509 break;
2500 case IR_MOD: 2510 case IR_MOD:
2501#if LJ_64 && LJ_HASFFI 2511#if LJ_64 && LJ_HASFFI
2502 asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 : 2512 if (!irt_isint(ir->t))
2503 IRCALL_lj_carith_modu64); 2513 asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 :
2504#else 2514 IRCALL_lj_carith_modu64);
2505 lua_assert(0); 2515 else
2506#endif 2516#endif
2517 asm_intmod(as, ir);
2507 break; 2518 break;
2508 2519
2509 case IR_NEG: 2520 case IR_NEG:
diff --git a/src/lj_ircall.h b/src/lj_ircall.h
index 1cbee91c..3b0a54b6 100644
--- a/src/lj_ircall.h
+++ b/src/lj_ircall.h
@@ -143,6 +143,7 @@ typedef struct CCallInfo {
143 _(lj_gc_barrieruv, 2, FS, NIL, 0) \ 143 _(lj_gc_barrieruv, 2, FS, NIL, 0) \
144 _(lj_mem_newgco, 2, FS, P32, CCI_L) \ 144 _(lj_mem_newgco, 2, FS, P32, CCI_L) \
145 _(lj_math_random_step, 1, FS, NUM, CCI_CASTU64|CCI_NOFPRCLOBBER) \ 145 _(lj_math_random_step, 1, FS, NUM, CCI_CASTU64|CCI_NOFPRCLOBBER) \
146 _(lj_vm_modi, 2, FN, INT, 0) \
146 IRCALLDEF_SOFTFP(_) \ 147 IRCALLDEF_SOFTFP(_) \
147 IRCALLDEF_FPMATH(_) \ 148 IRCALLDEF_FPMATH(_) \
148 IRCALLDEF_FFI(_) \ 149 IRCALLDEF_FFI(_) \
diff --git a/src/lj_iropt.h b/src/lj_iropt.h
index 7ab42b7a..3059fb9e 100644
--- a/src/lj_iropt.h
+++ b/src/lj_iropt.h
@@ -141,7 +141,7 @@ LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_cindex(jit_State *J, TRef key);
141LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc, 141LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
142 TValue *vb, TValue *vc, IROp op); 142 TValue *vb, TValue *vc, IROp op);
143LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc); 143LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc);
144LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc); 144LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc);
145LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc); 145LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc);
146LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase); 146LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase);
147 147
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c
index 0fc73683..2ecac2d9 100644
--- a/src/lj_opt_fold.c
+++ b/src/lj_opt_fold.c
@@ -231,6 +231,7 @@ static int32_t kfold_intop(int32_t k1, int32_t k2, IROp op)
231 case IR_ADD: k1 += k2; break; 231 case IR_ADD: k1 += k2; break;
232 case IR_SUB: k1 -= k2; break; 232 case IR_SUB: k1 -= k2; break;
233 case IR_MUL: k1 *= k2; break; 233 case IR_MUL: k1 *= k2; break;
234 case IR_MOD: k1 = lj_vm_modi(k1, k2); break;
234 case IR_BAND: k1 &= k2; break; 235 case IR_BAND: k1 &= k2; break;
235 case IR_BOR: k1 |= k2; break; 236 case IR_BOR: k1 |= k2; break;
236 case IR_BXOR: k1 ^= k2; break; 237 case IR_BXOR: k1 ^= k2; break;
@@ -249,6 +250,7 @@ static int32_t kfold_intop(int32_t k1, int32_t k2, IROp op)
249LJFOLD(ADD KINT KINT) 250LJFOLD(ADD KINT KINT)
250LJFOLD(SUB KINT KINT) 251LJFOLD(SUB KINT KINT)
251LJFOLD(MUL KINT KINT) 252LJFOLD(MUL KINT KINT)
253LJFOLD(MOD KINT KINT)
252LJFOLD(BAND KINT KINT) 254LJFOLD(BAND KINT KINT)
253LJFOLD(BOR KINT KINT) 255LJFOLD(BOR KINT KINT)
254LJFOLD(BXOR KINT KINT) 256LJFOLD(BXOR KINT KINT)
@@ -1148,7 +1150,6 @@ LJFOLDF(simplify_intmul_k32)
1148 1150
1149LJFOLD(MUL any KINT64) 1151LJFOLD(MUL any KINT64)
1150LJFOLDF(simplify_intmul_k64) 1152LJFOLDF(simplify_intmul_k64)
1151
1152{ 1153{
1153 if (ir_kint64(fright)->u64 == 0) /* i * 0 ==> 0 */ 1154 if (ir_kint64(fright)->u64 == 0) /* i * 0 ==> 0 */
1154 return INT64FOLD(0); 1155 return INT64FOLD(0);
@@ -1160,6 +1161,27 @@ LJFOLDF(simplify_intmul_k64)
1160 return NEXTFOLD; 1161 return NEXTFOLD;
1161} 1162}
1162 1163
1164LJFOLD(MOD any KINT)
1165LJFOLDF(simplify_intmod_k)
1166{
1167 int32_t k = fright->i;
1168 lua_assert(k != 0);
1169 if (k > 0 && (k & (k-1)) == 0) { /* i % (2^k) ==> i & (2^k-1) */
1170 fins->o = IR_BAND;
1171 fins->op2 = lj_ir_kint(J, k-1);
1172 return RETRYFOLD;
1173 }
1174 return NEXTFOLD;
1175}
1176
1177LJFOLD(MOD KINT any)
1178LJFOLDF(simplify_intmod_kleft)
1179{
1180 if (fleft->i == 0)
1181 return INTFOLD(0);
1182 return NEXTFOLD;
1183}
1184
1163LJFOLD(SUB any any) 1185LJFOLD(SUB any any)
1164LJFOLD(SUBOV any any) 1186LJFOLD(SUBOV any any)
1165LJFOLDF(simplify_intsub) 1187LJFOLDF(simplify_intsub)
diff --git a/src/lj_opt_narrow.c b/src/lj_opt_narrow.c
index e7f280ec..40696c02 100644
--- a/src/lj_opt_narrow.c
+++ b/src/lj_opt_narrow.c
@@ -551,16 +551,16 @@ TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc)
551} 551}
552 552
553/* Narrowing of modulo operator. */ 553/* Narrowing of modulo operator. */
554TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc) 554TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc)
555{ 555{
556 TRef tmp; 556 TRef tmp;
557 if ((J->flags & JIT_F_OPT_NARROW) && 557 if (tvisstr(vc) && !lj_str_tonum(strV(vc), vc))
558 tref_isk(rc) && tref_isint(rc)) { /* Optimize x % k. */ 558 lj_trace_err(J, LJ_TRERR_BADTYPE);
559 int32_t k = IR(tref_ref(rc))->i; 559 if ((LJ_DUALNUM || (J->flags & JIT_F_OPT_NARROW)) &&
560 if (k > 0 && (k & (k-1)) == 0) { /* i % 2^k ==> band(i, 2^k-1) */ 560 tref_isinteger(rb) && tref_isinteger(rc) &&
561 if (tref_isinteger(rb)) 561 (tvisint(vc) ? intV(vc) != 0 : !tviszero(vc))) {
562 return emitir(IRTI(IR_BAND), rb, lj_ir_kint(J, k-1)); 562 emitir(IRTGI(IR_NE), rc, lj_ir_kint(J, 0));
563 } 563 return emitir(IRTI(IR_MOD), rb, rc);
564 } 564 }
565 /* b % c ==> b - floor(b/c)*c */ 565 /* b % c ==> b - floor(b/c)*c */
566 rb = lj_ir_tonum(J, rb); 566 rb = lj_ir_tonum(J, rb);
diff --git a/src/lj_record.c b/src/lj_record.c
index 689d7b80..fe79832a 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -1715,7 +1715,7 @@ void lj_record_ins(jit_State *J)
1715 case BC_MODVN: case BC_MODVV: 1715 case BC_MODVN: case BC_MODVV:
1716 recmod: 1716 recmod:
1717 if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) 1717 if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
1718 rc = lj_opt_narrow_mod(J, rb, rc); 1718 rc = lj_opt_narrow_mod(J, rb, rc, rcv);
1719 else 1719 else
1720 rc = rec_mm_arith(J, &ix, MM_mod); 1720 rc = rec_mm_arith(J, &ix, MM_mod);
1721 break; 1721 break;
diff --git a/src/lj_vm.h b/src/lj_vm.h
index 3941dad9..ba624dad 100644
--- a/src/lj_vm.h
+++ b/src/lj_vm.h
@@ -71,6 +71,7 @@ LJ_ASMF double lj_vm_exp2(double);
71#define lj_vm_exp2 exp2 71#define lj_vm_exp2 exp2
72#endif 72#endif
73#endif 73#endif
74LJ_ASMF int32_t LJ_FASTCALL lj_vm_modi(int32_t, int32_t);
74#endif 75#endif
75 76
76/* Continuations for metamethods. */ 77/* Continuations for metamethods. */
diff --git a/src/lj_vmmath.c b/src/lj_vmmath.c
index d357b4e3..970bb5ad 100644
--- a/src/lj_vmmath.c
+++ b/src/lj_vmmath.c
@@ -39,6 +39,20 @@ double lj_vm_exp2(double a)
39} 39}
40#endif 40#endif
41 41
42#if !LJ_TARGET_ARM
43int32_t LJ_FASTCALL lj_vm_modi(int32_t a, int32_t b)
44{
45 uint32_t y, ua, ub;
46 lua_assert(b != 0); /* This must be checked before using this function. */
47 ua = a < 0 ? -(uint32_t)a : (uint32_t)a;
48 ub = b < 0 ? -(uint32_t)b : (uint32_t)b;
49 y = ua % ub;
50 if (y != 0 && (a^b) < 0) y = y - ub;
51 if (((int32_t)y^b) < 0) y = -y;
52 return (int32_t)y;
53}
54#endif
55
42#if !LJ_TARGET_X86ORX64 56#if !LJ_TARGET_X86ORX64
43/* Unsigned x^k. */ 57/* Unsigned x^k. */
44static double lj_vm_powui(double x, uint32_t k) 58static double lj_vm_powui(double x, uint32_t k)