Skip to content

Commit 0bf80cf

Browse files
committed
Optimize OR(X, PWR2) => BTS to avoid loading imm64 value in register
1 parent d31339f commit 0bf80cf

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

ext/opcache/jit/ir/ir_x86.dasc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,7 @@ const char *ir_reg_name(int8_t reg, ir_type type)
10641064
_(SSE_CEIL) \
10651065
_(SSE_TRUNC) \
10661066
_(SSE_NEARBYINT) \
1067+
_(OR_PWR2) \
10671068

10681069
#define IR_RULE_ENUM(name) IR_ ## name,
10691070

@@ -1395,6 +1396,7 @@ op2_const:
13951396
case IR_DIV_PWR2:
13961397
case IR_OP_INT:
13971398
case IR_OP_FP:
1399+
case IR_OR_PWR2:
13981400
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
13991401
break;
14001402
case IR_MOD_PWR2:
@@ -2262,6 +2264,9 @@ binop_fp:
22622264
// return IR_COPY_INT;
22632265
} else if (op2_insn->val.i64 == -1) {
22642266
// -1
2267+
} else if (IR_IS_POWER_OF_TWO(op2_insn->val.u64) && op2_insn->val.u64 > (1ULL<<30)) {
2268+
/* OR(X, PWR2) => BTS */
2269+
return IR_OR_PWR2;
22652270
}
22662271
}
22672272
goto binop_int;
@@ -4280,6 +4285,26 @@ static void ir_emit_mul_div_mod_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn)
42804285
uint32_t shift = IR_LOG2(ctx->ir_base[insn->op2].val.u64);
42814286

42824287
| ASM_REG_IMM_OP shr, type, def_reg, shift
4288+
} else if (insn->op == IR_OR) {
4289+
uint32_t shift = IR_LOG2(ctx->ir_base[insn->op2].val.u64);
4290+
4291+
/* bts doesn't support r/m8 first operand */
4292+
switch (ir_type_size[type]) {
4293+
default:
4294+
IR_ASSERT(0);
4295+
case 1:
4296+
case 2:
4297+
| bts Rw(def_reg), (shift & 0xffff)
4298+
break;
4299+
case 4:
4300+
| bts Rd(def_reg), shift
4301+
break;
4302+
|.if X64
4303+
|| case 8:
4304+
| bts Rq(def_reg), shift
4305+
|| break;
4306+
|.endif
4307+
}
42834308
} else {
42844309
IR_ASSERT(insn->op == IR_MOD);
42854310
uint64_t mask = ctx->ir_base[insn->op2].val.u64 - 1;
@@ -10608,6 +10633,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
1060810633
case IR_MUL_PWR2:
1060910634
case IR_DIV_PWR2:
1061010635
case IR_MOD_PWR2:
10636+
case IR_OR_PWR2:
1061110637
ir_emit_mul_div_mod_pwr2(ctx, i, insn);
1061210638
break;
1061310639
case IR_SDIV_PWR2:

0 commit comments

Comments
 (0)