diff options
author | Mike Pall <mike> | 2011-06-03 18:48:02 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-06-03 18:48:02 +0200 |
commit | 8c5935000d2b9bccd6c563b45c6a893f28986ca5 (patch) | |
tree | 2f530cf0b703350e355f1931679a7ed68503867e | |
parent | eec28aa9fdf5f733a4f7d2628fc060eac66ab713 (diff) | |
download | luajit-8c5935000d2b9bccd6c563b45c6a893f28986ca5.tar.gz luajit-8c5935000d2b9bccd6c563b45c6a893f28986ca5.tar.bz2 luajit-8c5935000d2b9bccd6c563b45c6a893f28986ca5.zip |
Add narrowing of modulo operator.
-rw-r--r-- | src/lj_asm_arm.h | 13 | ||||
-rw-r--r-- | src/lj_asm_x86.h | 19 | ||||
-rw-r--r-- | src/lj_ircall.h | 1 | ||||
-rw-r--r-- | src/lj_iropt.h | 2 | ||||
-rw-r--r-- | src/lj_opt_fold.c | 24 | ||||
-rw-r--r-- | src/lj_opt_narrow.c | 16 | ||||
-rw-r--r-- | src/lj_record.c | 2 | ||||
-rw-r--r-- | src/lj_vm.h | 1 | ||||
-rw-r--r-- | src/lj_vmmath.c | 14 |
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 | ||
1113 | static 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 | |||
1113 | static void asm_bitswap(ASMState *as, IRIns *ir) | 1123 | static 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 | ||
1654 | static 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 | |||
1654 | static int asm_swapops(ASMState *as, IRIns *ir) | 1664 | static 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); | |||
141 | LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc, | 141 | LJ_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); |
143 | LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc); | 143 | LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc); |
144 | LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc); | 144 | LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc); |
145 | LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc); | 145 | LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc); |
146 | LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase); | 146 | LJ_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) | |||
249 | LJFOLD(ADD KINT KINT) | 250 | LJFOLD(ADD KINT KINT) |
250 | LJFOLD(SUB KINT KINT) | 251 | LJFOLD(SUB KINT KINT) |
251 | LJFOLD(MUL KINT KINT) | 252 | LJFOLD(MUL KINT KINT) |
253 | LJFOLD(MOD KINT KINT) | ||
252 | LJFOLD(BAND KINT KINT) | 254 | LJFOLD(BAND KINT KINT) |
253 | LJFOLD(BOR KINT KINT) | 255 | LJFOLD(BOR KINT KINT) |
254 | LJFOLD(BXOR KINT KINT) | 256 | LJFOLD(BXOR KINT KINT) |
@@ -1148,7 +1150,6 @@ LJFOLDF(simplify_intmul_k32) | |||
1148 | 1150 | ||
1149 | LJFOLD(MUL any KINT64) | 1151 | LJFOLD(MUL any KINT64) |
1150 | LJFOLDF(simplify_intmul_k64) | 1152 | LJFOLDF(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 | ||
1164 | LJFOLD(MOD any KINT) | ||
1165 | LJFOLDF(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 | |||
1177 | LJFOLD(MOD KINT any) | ||
1178 | LJFOLDF(simplify_intmod_kleft) | ||
1179 | { | ||
1180 | if (fleft->i == 0) | ||
1181 | return INTFOLD(0); | ||
1182 | return NEXTFOLD; | ||
1183 | } | ||
1184 | |||
1163 | LJFOLD(SUB any any) | 1185 | LJFOLD(SUB any any) |
1164 | LJFOLD(SUBOV any any) | 1186 | LJFOLD(SUBOV any any) |
1165 | LJFOLDF(simplify_intsub) | 1187 | LJFOLDF(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. */ |
554 | TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc) | 554 | TRef 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 |
74 | LJ_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 | ||
43 | int32_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. */ |
44 | static double lj_vm_powui(double x, uint32_t k) | 58 | static double lj_vm_powui(double x, uint32_t k) |