1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

JIT: Implement CPU register usage for ASSIGN_DIM (#14224)

This commit is contained in:
Dmitry Stogov
2024-05-14 12:10:28 +03:00
committed by GitHub
parent c90c4fe553
commit bf7d4d7eb2
4 changed files with 81 additions and 27 deletions

View File

@@ -1702,7 +1702,12 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
break;
}
if (!zend_jit_assign_dim(&ctx, opline,
OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), OP1_DATA_INFO(), IS_UNKNOWN,
OP1_INFO(), OP1_REG_ADDR(),
OP2_INFO(), (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
OP1_DATA_INFO(), OP1_DATA_REG_ADDR(),
(ctx.ra && (ssa_op+1)->op1_def >= 0) ? OP1_DATA_DEF_REG_ADDR() : 0,
(opline->result_type != IS_UNUSED) ? RES_REG_ADDR() : 0,
IS_UNKNOWN,
zend_may_throw(opline, ssa_op, op_array, ssa))) {
goto jit_failure;
}
@@ -2008,7 +2013,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
/* For EX variant write into the result of EX opcode. */
if ((opline+1)->opcode == ZEND_JMPZ_EX
|| (opline+1)->opcode == ZEND_JMPNZ_EX) {
res_addr = OP_REG_ADDR(opline + 1, result_type, result, result_def);
res_addr = OP_REG_ADDR(opline + 1, ssa_op + 1, result_type, result, result_def);
}
} else {
smart_branch_opcode = 0;
@@ -2044,7 +2049,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
/* For EX variant write into the result of EX opcode. */
if ((opline+1)->opcode == ZEND_JMPZ_EX
|| (opline+1)->opcode == ZEND_JMPNZ_EX) {
res_addr = OP_REG_ADDR(opline + 1, result_type, result, result_def);
res_addr = OP_REG_ADDR(opline + 1, ssa_op + 1, result_type, result, result_def);
}
} else {
smart_branch_opcode = 0;

View File

@@ -77,9 +77,9 @@ typedef uintptr_t zend_jit_addr;
ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline)->op.var))
#endif
#define OP_REG_ADDR(opline, type, op, _ssa_op) \
((ctx.ra && ssa_op->_ssa_op >= 0 && ctx.ra[ssa_op->_ssa_op].ref) ? \
ZEND_ADDR_REG(ssa_op->_ssa_op) : \
#define OP_REG_ADDR(opline, ssa_op, type, op, _ssa_op) \
((ctx.ra && (ssa_op)->_ssa_op >= 0 && ctx.ra[(ssa_op)->_ssa_op].ref) ? \
ZEND_ADDR_REG((ssa_op)->_ssa_op) : \
OP_ADDR(opline, type, op))
#define OP1_ADDR() \
@@ -92,22 +92,22 @@ typedef uintptr_t zend_jit_addr;
OP_ADDR(opline + 1, op1_type, op1)
#define OP1_REG_ADDR() \
OP_REG_ADDR(opline, op1_type, op1, op1_use)
OP_REG_ADDR(opline, ssa_op, op1_type, op1, op1_use)
#define OP2_REG_ADDR() \
OP_REG_ADDR(opline, op2_type, op2, op2_use)
OP_REG_ADDR(opline, ssa_op, op2_type, op2, op2_use)
#define RES_REG_ADDR() \
OP_REG_ADDR(opline, result_type, result, result_def)
OP_REG_ADDR(opline, ssa_op, result_type, result, result_def)
#define OP1_DATA_REG_ADDR() \
OP_REG_ADDR(opline + 1, op1_type, op1, op1_use)
OP_REG_ADDR(opline + 1, ssa_op + 1, op1_type, op1, op1_use)
#define OP1_DEF_REG_ADDR() \
OP_REG_ADDR(opline, op1_type, op1, op1_def)
OP_REG_ADDR(opline, ssa_op, op1_type, op1, op1_def)
#define OP2_DEF_REG_ADDR() \
OP_REG_ADDR(opline, op2_type, op2, op2_def)
OP_REG_ADDR(opline, ssa_op, op2_type, op2, op2_def)
#define RES_USE_REG_ADDR() \
OP_REG_ADDR(opline, result_type, result, result_use)
OP_REG_ADDR(opline, ssa_op, result_type, result, result_use)
#define OP1_DATA_DEF_REG_ADDR() \
OP_REG_ADDR(opline + 1, op1_type, op1, op1_def)
OP_REG_ADDR(opline + 1, ssa_op + 1, op1_type, op1, op1_def)
static zend_always_inline bool zend_jit_same_addr(zend_jit_addr addr1, zend_jit_addr addr2)
{

View File

@@ -6232,8 +6232,14 @@ static int zend_jit_assign_to_variable(zend_jit_ctx *jit,
ir_IF_TRUE_cold(if_typed);
jit_SET_EX_OPLINE(jit, opline);
if (Z_MODE(val_addr) == IS_REG) {
ZEND_ASSERT(opline->opcode == ZEND_ASSIGN);
zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
zend_jit_addr real_addr;
if (opline->opcode == ZEND_ASSIGN_DIM) {
real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
} else {
ZEND_ASSERT(opline->opcode == ZEND_ASSIGN);
real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
}
if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
return 0;
}
@@ -12788,18 +12794,29 @@ static int zend_jit_isset_isempty_dim(zend_jit_ctx *jit,
return 1;
}
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)
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,
zend_jit_addr op2_addr,
uint32_t val_info,
zend_jit_addr op3_addr,
zend_jit_addr op3_def_addr,
zend_jit_addr res_addr,
uint8_t dim_type,
int may_throw)
{
zend_jit_addr op2_addr, op3_addr, res_addr;
ir_ref if_type = IR_UNUSED;
ir_ref end_inputs = IR_UNUSED, ht_ref;
op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0;
op3_addr = OP1_DATA_ADDR();
if (opline->result_type == IS_UNUSED) {
res_addr = 0;
} else {
res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
if (op3_addr != op3_def_addr && op3_def_addr) {
if (!zend_jit_update_regs(jit, (opline+1)->op1.var, op3_addr, op3_def_addr, val_info)) {
return 0;
}
if (Z_MODE(op3_def_addr) == IS_REG && Z_MODE(op3_addr) != IS_REG) {
op3_addr = op3_def_addr;
}
}
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_
ir_refs_init(found_values, 8);
if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_VAR_W, op1_info,
op2_info, OP2_ADDR(), dim_type, NULL, NULL, NULL,
op2_info, op2_addr, dim_type, NULL, NULL, NULL,
0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) {
return 0;
}
@@ -12870,7 +12887,9 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_
var_addr = ZEND_ADDR_REF_ZVAL(ref);
// JIT: value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE);
if (opline->op1_type == IS_VAR) {
if (opline->op1_type == IS_VAR
&& Z_MODE(op3_addr) != IS_REG
&& (res_addr == 0 || Z_MODE(res_addr) != IS_REG)) {
ZEND_ASSERT(opline->result_type == IS_UNUSED);
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)) {
return 0;
@@ -16552,6 +16571,31 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa
return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
(((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
case ZEND_ASSIGN_DIM:
op1_info = OP1_INFO();
op2_info = OP2_INFO();
if (trace) {
if (opline->op1_type == IS_CV) {
if ((opline+1)->op1_type == IS_CV
&& (opline+1)->op1.var == opline->op1.var) {
/* skip $a[x] = $a; */
return 0;
}
} else if (opline->op1_type == IS_VAR) {
if (trace->op1_type == IS_UNKNOWN
|| !(trace->op1_type & IS_TRACE_INDIRECT)
|| opline->result_type != IS_UNUSED) {
return 0;
}
}
if (trace->op1_type != IS_UNKNOWN
&& (trace->op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)) == IS_ARRAY) {
op1_info &= ~((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_ARRAY);
}
}
return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
(((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
}
return 0;
}

View File

@@ -4934,7 +4934,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
op1_data_info = OP1_DATA_INFO();
CHECK_OP1_DATA_TRACE_TYPE();
if (!zend_jit_assign_dim(&ctx, opline,
op1_info, op1_addr, op2_info, op1_data_info, val_type,
op1_info, op1_addr,
op2_info, (opline->op2_type != IS_UNUSED) ? OP2_REG_ADDR() : 0,
op1_data_info, OP1_DATA_REG_ADDR(),
(ctx.ra && (ssa_op+1)->op1_def >= 0) ? OP1_DATA_DEF_REG_ADDR() : 0,
(opline->result_type != IS_UNUSED) ? RES_REG_ADDR() : 0,
val_type,
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
goto jit_failure;
}