Skip to content

Commit bf7d4d7

Browse files
authored
JIT: Implement CPU register usage for ASSIGN_DIM (#14224)
1 parent c90c4fe commit bf7d4d7

File tree

4 files changed

+81
-27
lines changed

4 files changed

+81
-27
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,7 +1702,12 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
17021702
break;
17031703
}
17041704
if (!zend_jit_assign_dim(&ctx, opline,
1705-
OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), OP1_DATA_INFO(), IS_UNKNOWN,
1705+
OP1_INFO(), OP1_REG_ADDR(),
1706+
OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
1707+
OP1_DATA_INFO(), OP1_DATA_REG_ADDR(),
1708+
(ctx.ra && (ssa_op+1)->op1_def >= 0) ? OP1_DATA_DEF_REG_ADDR() : 0,
1709+
(opline->result_type != IS_UNUSED) ? RES_REG_ADDR() : 0,
1710+
IS_UNKNOWN,
17061711
zend_may_throw(opline, ssa_op, op_array, ssa))) {
17071712
goto jit_failure;
17081713
}
@@ -2008,7 +2013,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
20082013
/* For EX variant write into the result of EX opcode. */
20092014
if ((opline+1)->opcode == ZEND_JMPZ_EX
20102015
|| (opline+1)->opcode == ZEND_JMPNZ_EX) {
2011-
res_addr = OP_REG_ADDR(opline + 1, result_type, result, result_def);
2016+
res_addr = OP_REG_ADDR(opline + 1, ssa_op + 1, result_type, result, result_def);
20122017
}
20132018
} else {
20142019
smart_branch_opcode = 0;
@@ -2044,7 +2049,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
20442049
/* For EX variant write into the result of EX opcode. */
20452050
if ((opline+1)->opcode == ZEND_JMPZ_EX
20462051
|| (opline+1)->opcode == ZEND_JMPNZ_EX) {
2047-
res_addr = OP_REG_ADDR(opline + 1, result_type, result, result_def);
2052+
res_addr = OP_REG_ADDR(opline + 1, ssa_op + 1, result_type, result, result_def);
20482053
}
20492054
} else {
20502055
smart_branch_opcode = 0;

ext/opcache/jit/zend_jit_internal.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ typedef uintptr_t zend_jit_addr;
7777
ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline)->op.var))
7878
#endif
7979

80-
#define OP_REG_ADDR(opline, type, op, _ssa_op) \
81-
((ctx.ra && ssa_op->_ssa_op >= 0 && ctx.ra[ssa_op->_ssa_op].ref) ? \
82-
ZEND_ADDR_REG(ssa_op->_ssa_op) : \
80+
#define OP_REG_ADDR(opline, ssa_op, type, op, _ssa_op) \
81+
((ctx.ra && (ssa_op)->_ssa_op >= 0 && ctx.ra[(ssa_op)->_ssa_op].ref) ? \
82+
ZEND_ADDR_REG((ssa_op)->_ssa_op) : \
8383
OP_ADDR(opline, type, op))
8484

8585
#define OP1_ADDR() \
@@ -92,22 +92,22 @@ typedef uintptr_t zend_jit_addr;
9292
OP_ADDR(opline + 1, op1_type, op1)
9393

9494
#define OP1_REG_ADDR() \
95-
OP_REG_ADDR(opline, op1_type, op1, op1_use)
95+
OP_REG_ADDR(opline, ssa_op, op1_type, op1, op1_use)
9696
#define OP2_REG_ADDR() \
97-
OP_REG_ADDR(opline, op2_type, op2, op2_use)
97+
OP_REG_ADDR(opline, ssa_op, op2_type, op2, op2_use)
9898
#define RES_REG_ADDR() \
99-
OP_REG_ADDR(opline, result_type, result, result_def)
99+
OP_REG_ADDR(opline, ssa_op, result_type, result, result_def)
100100
#define OP1_DATA_REG_ADDR() \
101-
OP_REG_ADDR(opline + 1, op1_type, op1, op1_use)
101+
OP_REG_ADDR(opline + 1, ssa_op + 1, op1_type, op1, op1_use)
102102

103103
#define OP1_DEF_REG_ADDR() \
104-
OP_REG_ADDR(opline, op1_type, op1, op1_def)
104+
OP_REG_ADDR(opline, ssa_op, op1_type, op1, op1_def)
105105
#define OP2_DEF_REG_ADDR() \
106-
OP_REG_ADDR(opline, op2_type, op2, op2_def)
106+
OP_REG_ADDR(opline, ssa_op, op2_type, op2, op2_def)
107107
#define RES_USE_REG_ADDR() \
108-
OP_REG_ADDR(opline, result_type, result, result_use)
108+
OP_REG_ADDR(opline, ssa_op, result_type, result, result_use)
109109
#define OP1_DATA_DEF_REG_ADDR() \
110-
OP_REG_ADDR(opline + 1, op1_type, op1, op1_def)
110+
OP_REG_ADDR(opline + 1, ssa_op + 1, op1_type, op1, op1_def)
111111

112112
static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_addr addr2)
113113
{

ext/opcache/jit/zend_jit_ir.c

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6232,8 +6232,14 @@ static int zend_jit_assign_to_variable(zend_jit_ctx *jit,
62326232
ir_IF_TRUE_cold(if_typed);
62336233
jit_SET_EX_OPLINE(jit, opline);
62346234
if (Z_MODE(val_addr) == IS_REG) {
6235-
ZEND_ASSERT(opline->opcode == ZEND_ASSIGN);
6236-
zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
6235+
zend_jit_addr real_addr;
6236+
6237+
if (opline->opcode == ZEND_ASSIGN_DIM) {
6238+
real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
6239+
} else {
6240+
ZEND_ASSERT(opline->opcode == ZEND_ASSIGN);
6241+
real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
6242+
}
62376243
if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
62386244
return 0;
62396245
}
@@ -12788,18 +12794,29 @@ static int zend_jit_isset_isempty_dim(zend_jit_ctx *jit,
1278812794
return 1;
1278912795
}
1279012796

12791-
static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, uint32_t op2_info, uint32_t val_info, uint8_t dim_type, int may_throw)
12797+
static int zend_jit_assign_dim(zend_jit_ctx *jit,
12798+
const zend_op *opline,
12799+
uint32_t op1_info,
12800+
zend_jit_addr op1_addr,
12801+
uint32_t op2_info,
12802+
zend_jit_addr op2_addr,
12803+
uint32_t val_info,
12804+
zend_jit_addr op3_addr,
12805+
zend_jit_addr op3_def_addr,
12806+
zend_jit_addr res_addr,
12807+
uint8_t dim_type,
12808+
int may_throw)
1279212809
{
12793-
zend_jit_addr op2_addr, op3_addr, res_addr;
1279412810
ir_ref if_type = IR_UNUSED;
1279512811
ir_ref end_inputs = IR_UNUSED, ht_ref;
1279612812

12797-
op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0;
12798-
op3_addr = OP1_DATA_ADDR();
12799-
if (opline->result_type == IS_UNUSED) {
12800-
res_addr = 0;
12801-
} else {
12802-
res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
12813+
if (op3_addr != op3_def_addr && op3_def_addr) {
12814+
if (!zend_jit_update_regs(jit, (opline+1)->op1.var, op3_addr, op3_def_addr, val_info)) {
12815+
return 0;
12816+
}
12817+
if (Z_MODE(op3_def_addr) == IS_REG && Z_MODE(op3_addr) != IS_REG) {
12818+
op3_addr = op3_def_addr;
12819+
}
1280312820
}
1280412821

1280512822
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && (val_info & MAY_BE_UNDEF)) {
@@ -12852,7 +12869,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_
1285212869
ir_refs_init(found_values, 8);
1285312870

1285412871
if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_VAR_W, op1_info,
12855-
op2_info, OP2_ADDR(), dim_type, NULL, NULL, NULL,
12872+
op2_info, op2_addr, dim_type, NULL, NULL, NULL,
1285612873
0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) {
1285712874
return 0;
1285812875
}
@@ -12870,7 +12887,9 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_
1287012887
var_addr = ZEND_ADDR_REF_ZVAL(ref);
1287112888

1287212889
// JIT: value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE);
12873-
if (opline->op1_type == IS_VAR) {
12890+
if (opline->op1_type == IS_VAR
12891+
&& Z_MODE(op3_addr) != IS_REG
12892+
&& (res_addr == 0 || Z_MODE(res_addr) != IS_REG)) {
1287412893
ZEND_ASSERT(opline->result_type == IS_UNUSED);
1287512894
if (!zend_jit_assign_to_variable_call(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0)) {
1287612895
return 0;
@@ -16552,6 +16571,31 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa
1655216571
return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
1655316572
(((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
1655416573
((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
16574+
case ZEND_ASSIGN_DIM:
16575+
op1_info = OP1_INFO();
16576+
op2_info = OP2_INFO();
16577+
if (trace) {
16578+
if (opline->op1_type == IS_CV) {
16579+
if ((opline+1)->op1_type == IS_CV
16580+
&& (opline+1)->op1.var == opline->op1.var) {
16581+
/* skip $a[x] = $a; */
16582+
return 0;
16583+
}
16584+
} else if (opline->op1_type == IS_VAR) {
16585+
if (trace->op1_type == IS_UNKNOWN
16586+
|| !(trace->op1_type & IS_TRACE_INDIRECT)
16587+
|| opline->result_type != IS_UNUSED) {
16588+
return 0;
16589+
}
16590+
}
16591+
if (trace->op1_type != IS_UNKNOWN
16592+
&& (trace->op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)) == IS_ARRAY) {
16593+
op1_info &= ~((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_ARRAY);
16594+
}
16595+
}
16596+
return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
16597+
(((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
16598+
((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
1655516599
}
1655616600
return 0;
1655716601
}

ext/opcache/jit/zend_jit_trace.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4934,7 +4934,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
49344934
op1_data_info = OP1_DATA_INFO();
49354935
CHECK_OP1_DATA_TRACE_TYPE();
49364936
if (!zend_jit_assign_dim(&ctx, opline,
4937-
op1_info, op1_addr, op2_info, op1_data_info, val_type,
4937+
op1_info, op1_addr,
4938+
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
4939+
op1_data_info, OP1_DATA_REG_ADDR(),
4940+
(ctx.ra && (ssa_op+1)->op1_def >= 0) ? OP1_DATA_DEF_REG_ADDR() : 0,
4941+
(opline->result_type != IS_UNUSED) ? RES_REG_ADDR() : 0,
4942+
val_type,
49384943
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
49394944
goto jit_failure;
49404945
}

0 commit comments

Comments
 (0)