diff --git a/ext/opcache/jit/ir/ir_ra.c b/ext/opcache/jit/ir/ir_ra.c index 06d3a9e2316..8cca8d08be1 100644 --- a/ext/opcache/jit/ir/ir_ra.c +++ b/ext/opcache/jit/ir/ir_ra.c @@ -3699,7 +3699,7 @@ static bool needs_spill_load(ir_ctx *ctx, ir_live_interval *ival, ir_use_pos *us return use_pos->next && use_pos->next->op_num != 0; } -static void ir_set_fused_reg(ir_ctx *ctx, ir_ref root, ir_ref ref, uint8_t op_num, int8_t reg) +static void ir_set_fused_reg(ir_ctx *ctx, ir_ref root, ir_ref ref_and_op, int8_t reg) { char key[10]; @@ -3709,9 +3709,8 @@ static void ir_set_fused_reg(ir_ctx *ctx, ir_ref root, ir_ref ref, uint8_t op_nu ir_strtab_init(ctx->fused_regs, 8, 128); } memcpy(key, &root, sizeof(ir_ref)); - memcpy(key + 4, &ref, sizeof(ir_ref)); - memcpy(key + 8, &op_num, sizeof(uint8_t)); - ir_strtab_lookup(ctx->fused_regs, key, 9, 0x10000000 | reg); + memcpy(key + 4, &ref_and_op, sizeof(ir_ref)); + ir_strtab_lookup(ctx->fused_regs, key, 8, 0x10000000 | reg); } static void assign_regs(ir_ctx *ctx) @@ -3853,7 +3852,7 @@ static void assign_regs(ir_ctx *ctx) if (reg != old_reg) { IR_ASSERT(ctx->rules[-use_pos->hint_ref] & IR_FUSED); ctx->rules[-use_pos->hint_ref] |= IR_FUSED_REG; - ir_set_fused_reg(ctx, ref, -use_pos->hint_ref, use_pos->op_num, reg); + ir_set_fused_reg(ctx, ref, -use_pos->hint_ref * sizeof(ir_ref) + use_pos->op_num, reg); use_pos = use_pos->next; continue; } @@ -3872,7 +3871,7 @@ static void assign_regs(ir_ctx *ctx) if (reg != old_reg) { IR_ASSERT(ctx->rules[-use_pos->hint_ref] & IR_FUSED); ctx->rules[-use_pos->hint_ref] |= IR_FUSED_REG; - ir_set_fused_reg(ctx, ref, -use_pos->hint_ref, use_pos->op_num, reg); + ir_set_fused_reg(ctx, ref, -use_pos->hint_ref * sizeof(ir_ref) + use_pos->op_num, reg); use_pos = use_pos->next; continue; } diff --git a/ext/opcache/jit/ir/ir_x86.dasc b/ext/opcache/jit/ir/ir_x86.dasc index 80a76a549a6..dd34e023ba8 100644 --- a/ext/opcache/jit/ir/ir_x86.dasc +++ b/ext/opcache/jit/ir/ir_x86.dasc @@ -1546,6 +1546,19 @@ static void ir_match_fuse_load_cmp_int(ir_ctx *ctx, ir_insn *insn, ir_ref root) } } +static void ir_match_fuse_load_test_int(ir_ctx *ctx, ir_insn *insn, ir_ref root) +{ + if (IR_IS_CONST_REF(insn->op2)) { + if (!IR_IS_SYM_CONST(ctx->ir_base[insn->op2].op) + && (ir_type_size[insn->type] != 8 || IR_IS_32BIT(ctx->ir_base[insn->op2].type, ctx->ir_base[insn->op2].val))) { + ir_match_fuse_load(ctx, insn->op1, root); + } + } else if (!ir_match_try_fuse_load(ctx, insn->op2, root) + && ir_match_try_fuse_load(ctx, insn->op1, root)) { + ir_swap_ops(insn); + } +} + static void ir_match_fuse_load_cmp_fp(ir_ctx *ctx, ir_insn *insn, ir_ref root) { if (insn->op != IR_EQ && insn->op != IR_NE) { @@ -1621,7 +1634,7 @@ static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref) if (op1_insn->op == IR_AND && ctx->use_lists[insn->op1].count == 1) { /* v = AND(_, _); CMP(v, 0) => SKIP_TEST; TEST */ - ir_match_fuse_load_cmp_int(ctx, op1_insn, ref); + ir_match_fuse_load_test_int(ctx, op1_insn, ref); ctx->rules[insn->op1] = IR_FUSED | IR_TEST_INT; return IR_TESTCC_INT; } else if ((op1_insn->op == IR_OR || op1_insn->op == IR_AND || op1_insn->op == IR_XOR) || @@ -2242,7 +2255,7 @@ store_int: if (op1_insn->op == IR_AND && ctx->use_lists[op2_insn->op1].count == 1) { /* v = AND(_, _); c = CMP(v, 0) ... IF(c) => SKIP_TEST; SKIP ... TEST_AND_BRANCH */ - ir_match_fuse_load_cmp_int(ctx, op1_insn, ref); + ir_match_fuse_load_test_int(ctx, op1_insn, ref); ctx->rules[op2_insn->op1] = IR_FUSED | IR_TEST_INT; ctx->rules[insn->op2] = IR_FUSED | IR_SIMPLE | IR_NOP; return IR_TEST_AND_BRANCH_INT; @@ -2273,7 +2286,7 @@ store_int: } } else if (op2_insn->op == IR_AND) { /* c = AND(_, _) ... IF(c) => SKIP_TEST ... TEST_AND_BRANCH */ - ir_match_fuse_load_cmp_int(ctx, op2_insn, ref); + ir_match_fuse_load_test_int(ctx, op2_insn, ref); ctx->rules[insn->op2] = IR_FUSED | IR_TEST_INT; return IR_TEST_AND_BRANCH_INT; } else if (op2_insn->op == IR_OVERFLOW) { @@ -2443,7 +2456,7 @@ store_int: } } else if (op2_insn->op == IR_AND) { // TODO: OR, XOR. etc /* c = AND(_, _) ... GUARD(c) => SKIP_TEST ... GUARD_TEST */ - ir_match_fuse_load_cmp_int(ctx, op2_insn, ref); + ir_match_fuse_load_test_int(ctx, op2_insn, ref); ctx->rules[insn->op2] = IR_FUSED | IR_TEST_INT; return IR_GUARD_TEST_INT; } else if (op2_insn->op == IR_OVERFLOW) {