|
@@ -140,6 +140,7 @@ static IRRef split_call_l(jit_State *J, IRRef1 *hisubst, IRIns *oir,
|
|
|
ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id);
|
|
|
return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp);
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
/* Emit a CALLN with one split 64 bit argument and a 32 bit argument. */
|
|
|
static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir,
|
|
@@ -156,7 +157,6 @@ static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir,
|
|
|
ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id);
|
|
|
return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp);
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
/* Emit a CALLN with two split 64 bit arguments. */
|
|
|
static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir,
|
|
@@ -196,6 +196,118 @@ static IRRef split_ptr(jit_State *J, IRIns *oir, IRRef ref)
|
|
|
return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs));
|
|
|
}
|
|
|
|
|
|
+#if LJ_HASFFI
|
|
|
+static IRRef split_bitshift(jit_State *J, IRRef1 *hisubst,
|
|
|
+ IRIns *oir, IRIns *nir, IRIns *ir)
|
|
|
+{
|
|
|
+ IROp op = ir->o;
|
|
|
+ IRRef kref = nir->op2;
|
|
|
+ if (irref_isk(kref)) { /* Optimize constant shifts. */
|
|
|
+ int32_t k = (IR(kref)->i & 63);
|
|
|
+ IRRef lo = nir->op1, hi = hisubst[ir->op1];
|
|
|
+ if (op == IR_BROL || op == IR_BROR) {
|
|
|
+ if (op == IR_BROR) k = (-k & 63);
|
|
|
+ if (k >= 32) { IRRef t = lo; lo = hi; hi = t; k -= 32; }
|
|
|
+ if (k == 0) {
|
|
|
+ passthrough:
|
|
|
+ J->cur.nins--;
|
|
|
+ ir->prev = lo;
|
|
|
+ return hi;
|
|
|
+ } else {
|
|
|
+ TRef k1, k2;
|
|
|
+ IRRef t1, t2, t3, t4;
|
|
|
+ J->cur.nins--;
|
|
|
+ k1 = lj_ir_kint(J, k);
|
|
|
+ k2 = lj_ir_kint(J, (-k & 31));
|
|
|
+ t1 = split_emit(J, IRTI(IR_BSHL), lo, k1);
|
|
|
+ t2 = split_emit(J, IRTI(IR_BSHL), hi, k1);
|
|
|
+ t3 = split_emit(J, IRTI(IR_BSHR), lo, k2);
|
|
|
+ t4 = split_emit(J, IRTI(IR_BSHR), hi, k2);
|
|
|
+ ir->prev = split_emit(J, IRTI(IR_BOR), t1, t4);
|
|
|
+ return split_emit(J, IRTI(IR_BOR), t2, t3);
|
|
|
+ }
|
|
|
+ } else if (k == 0) {
|
|
|
+ goto passthrough;
|
|
|
+ } else if (k < 32) {
|
|
|
+ if (op == IR_BSHL) {
|
|
|
+ IRRef t1 = split_emit(J, IRTI(IR_BSHL), hi, kref);
|
|
|
+ IRRef t2 = split_emit(J, IRTI(IR_BSHR), lo, lj_ir_kint(J, (-k&31)));
|
|
|
+ return split_emit(J, IRTI(IR_BOR), t1, t2);
|
|
|
+ } else {
|
|
|
+ IRRef t1 = ir->prev, t2;
|
|
|
+ lua_assert(op == IR_BSHR || op == IR_BSAR);
|
|
|
+ nir->o = IR_BSHR;
|
|
|
+ t2 = split_emit(J, IRTI(IR_BSHL), hi, lj_ir_kint(J, (-k&31)));
|
|
|
+ ir->prev = split_emit(J, IRTI(IR_BOR), t1, t2);
|
|
|
+ return split_emit(J, IRTI(op), hi, kref);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (op == IR_BSHL) {
|
|
|
+ if (k == 32)
|
|
|
+ J->cur.nins--;
|
|
|
+ else
|
|
|
+ lo = ir->prev;
|
|
|
+ ir->prev = lj_ir_kint(J, 0);
|
|
|
+ return lo;
|
|
|
+ } else {
|
|
|
+ lua_assert(op == IR_BSHR || op == IR_BSAR);
|
|
|
+ if (k == 32) {
|
|
|
+ J->cur.nins--;
|
|
|
+ ir->prev = hi;
|
|
|
+ } else {
|
|
|
+ nir->op1 = hi;
|
|
|
+ }
|
|
|
+ if (op == IR_BSHR)
|
|
|
+ return lj_ir_kint(J, 0);
|
|
|
+ else
|
|
|
+ return split_emit(J, IRTI(IR_BSAR), hi, lj_ir_kint(J, 31));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return split_call_li(J, hisubst, oir, ir,
|
|
|
+ op - IR_BSHL + IRCALL_lj_carith_shl64);
|
|
|
+}
|
|
|
+
|
|
|
+static IRRef split_bitop(jit_State *J, IRRef1 *hisubst,
|
|
|
+ IRIns *nir, IRIns *ir)
|
|
|
+{
|
|
|
+ IROp op = ir->o;
|
|
|
+ IRRef hi, kref = nir->op2;
|
|
|
+ if (irref_isk(kref)) { /* Optimize bit operations with lo constant. */
|
|
|
+ int32_t k = IR(kref)->i;
|
|
|
+ if (k == 0 || k == -1) {
|
|
|
+ if (op == IR_BAND) k = ~k;
|
|
|
+ if (k == 0) {
|
|
|
+ J->cur.nins--;
|
|
|
+ ir->prev = nir->op1;
|
|
|
+ } else if (op == IR_BXOR) {
|
|
|
+ nir->o = IR_BNOT;
|
|
|
+ nir->op2 = 0;
|
|
|
+ } else {
|
|
|
+ J->cur.nins--;
|
|
|
+ ir->prev = kref;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ hi = hisubst[ir->op1];
|
|
|
+ kref = hisubst[ir->op2];
|
|
|
+ if (irref_isk(kref)) { /* Optimize bit operations with hi constant. */
|
|
|
+ int32_t k = IR(kref)->i;
|
|
|
+ if (k == 0 || k == -1) {
|
|
|
+ if (op == IR_BAND) k = ~k;
|
|
|
+ if (k == 0) {
|
|
|
+ return hi;
|
|
|
+ } else if (op == IR_BXOR) {
|
|
|
+ return split_emit(J, IRTI(IR_BNOT), hi, 0);
|
|
|
+ } else {
|
|
|
+ return kref;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return split_emit(J, IRTI(op), hi, kref);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/* Transform the old IR to the new IR. */
|
|
|
static void split_ir(jit_State *J)
|
|
|
{
|
|
@@ -417,6 +529,19 @@ static void split_ir(jit_State *J)
|
|
|
irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 :
|
|
|
IRCALL_lj_carith_powu64);
|
|
|
break;
|
|
|
+ case IR_BNOT:
|
|
|
+ hi = split_emit(J, IRTI(IR_BNOT), hiref, 0);
|
|
|
+ break;
|
|
|
+ case IR_BSWAP:
|
|
|
+ ir->prev = split_emit(J, IRTI(IR_BSWAP), hiref, 0);
|
|
|
+ hi = nref;
|
|
|
+ break;
|
|
|
+ case IR_BAND: case IR_BOR: case IR_BXOR:
|
|
|
+ hi = split_bitop(J, hisubst, nir, ir);
|
|
|
+ break;
|
|
|
+ case IR_BSHL: case IR_BSHR: case IR_BSAR: case IR_BROL: case IR_BROR:
|
|
|
+ hi = split_bitshift(J, hisubst, oir, nir, ir);
|
|
|
+ break;
|
|
|
case IR_FLOAD:
|
|
|
lua_assert(ir->op2 == IRFL_CDATA_INT64);
|
|
|
hi = split_emit(J, IRTI(IR_FLOAD), nir->op1, IRFL_CDATA_INT64_4);
|