mirror of
https://github.com/php/php-src.git
synced 2026-04-26 01:18:19 +02:00
Merge branch 'PHP-8.0'
* PHP-8.0: Optimize out result value of ASSIGN, ASSIGN_OP and INC/DEC opcodes, if possible.
This commit is contained in:
@@ -985,6 +985,77 @@ optimize_nop:
|
||||
return removed_ops;
|
||||
}
|
||||
|
||||
static int zend_dfa_try_to_replace_result(zend_op_array *op_array, zend_ssa *ssa, int def, int cv_var)
|
||||
{
|
||||
int result_var = ssa->ops[def].result_def;
|
||||
int cv = EX_NUM_TO_VAR(ssa->vars[cv_var].var);
|
||||
|
||||
if (result_var >= 0
|
||||
&& !(ssa->var_info[cv_var].type & MAY_BE_REF)
|
||||
&& ssa->vars[cv_var].alias == NO_ALIAS
|
||||
&& ssa->vars[result_var].phi_use_chain == NULL
|
||||
&& ssa->vars[result_var].sym_use_chain == NULL) {
|
||||
int use = ssa->vars[result_var].use_chain;
|
||||
|
||||
if (use >= 0
|
||||
&& zend_ssa_next_use(ssa->ops, result_var, use) < 0
|
||||
&& op_array->opcodes[use].opcode != ZEND_FREE
|
||||
&& op_array->opcodes[use].opcode != ZEND_SEND_VAL
|
||||
&& op_array->opcodes[use].opcode != ZEND_SEND_VAL_EX
|
||||
&& op_array->opcodes[use].opcode != ZEND_VERIFY_RETURN_TYPE) {
|
||||
if (use > def) {
|
||||
int i = use;
|
||||
const zend_op *opline = &op_array->opcodes[use];
|
||||
|
||||
while (i > def) {
|
||||
if ((opline->op1_type == IS_CV && opline->op1.var == cv)
|
||||
|| (opline->op2_type == IS_CV && opline->op2.var == cv)
|
||||
|| (opline->result_type == IS_CV && opline->result.var == cv)) {
|
||||
return 0;
|
||||
}
|
||||
opline--;
|
||||
i--;
|
||||
}
|
||||
|
||||
/* Update opcodes and reconstruct SSA */
|
||||
ssa->vars[result_var].definition = -1;
|
||||
ssa->vars[result_var].use_chain = -1;
|
||||
ssa->ops[def].result_def = -1;
|
||||
|
||||
op_array->opcodes[def].result_type = IS_UNUSED;
|
||||
op_array->opcodes[def].result.var = 0;
|
||||
|
||||
if (ssa->ops[use].op1_use == result_var) {
|
||||
ssa->ops[use].op1_use = cv_var;
|
||||
ssa->ops[use].op1_use_chain = ssa->vars[cv_var].use_chain;
|
||||
ssa->vars[cv_var].use_chain = use;
|
||||
|
||||
op_array->opcodes[use].op1_type = IS_CV;
|
||||
op_array->opcodes[use].op1.var = cv;
|
||||
} else if (ssa->ops[use].op2_use == result_var) {
|
||||
ssa->ops[use].op2_use = cv_var;
|
||||
ssa->ops[use].op2_use_chain = ssa->vars[cv_var].use_chain;
|
||||
ssa->vars[cv_var].use_chain = use;
|
||||
|
||||
op_array->opcodes[use].op2_type = IS_CV;
|
||||
op_array->opcodes[use].op2.var = cv;
|
||||
} else if (ssa->ops[use].result_use == result_var) {
|
||||
ssa->ops[use].result_use = cv_var;
|
||||
ssa->ops[use].res_use_chain = ssa->vars[cv_var].use_chain;
|
||||
ssa->vars[cv_var].use_chain = use;
|
||||
|
||||
op_array->opcodes[use].result_type = IS_CV;
|
||||
op_array->opcodes[use].result.var = cv;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa, zend_call_info **call_map)
|
||||
{
|
||||
if (ctx->debug_level & ZEND_DUMP_BEFORE_DFA_PASS) {
|
||||
@@ -1303,6 +1374,44 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ssa->ops[op_1].op1_def == v
|
||||
&& RETURN_VALUE_USED(opline)) {
|
||||
if (opline->opcode == ZEND_ASSIGN
|
||||
|| opline->opcode == ZEND_ASSIGN_OP
|
||||
|| opline->opcode == ZEND_PRE_INC
|
||||
|| opline->opcode == ZEND_PRE_DEC) {
|
||||
zend_dfa_try_to_replace_result(op_array, ssa, op_1, v);
|
||||
} else if (opline->opcode == ZEND_POST_INC) {
|
||||
int result_var = ssa->ops[op_1].result_def;
|
||||
|
||||
if (result_var >= 0
|
||||
&& (ssa->var_info[result_var].type & ((MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_DOUBLE))) == 0) {
|
||||
int use = ssa->vars[result_var].use_chain;
|
||||
|
||||
if (op_array->opcodes[use].opcode == ZEND_IS_SMALLER
|
||||
&& ssa->ops[use].op1_use == result_var
|
||||
&& zend_dfa_try_to_replace_result(op_array, ssa, op_1, v)) {
|
||||
opline->opcode = ZEND_PRE_INC;
|
||||
op_array->opcodes[use].opcode = ZEND_IS_SMALLER_OR_EQUAL;
|
||||
}
|
||||
}
|
||||
} else if (opline->opcode == ZEND_POST_DEC) {
|
||||
int result_var = ssa->ops[op_1].result_def;
|
||||
|
||||
if (result_var >= 0
|
||||
&& (ssa->var_info[result_var].type & ((MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_DOUBLE))) == 0) {
|
||||
int use = ssa->vars[result_var].use_chain;
|
||||
|
||||
if (op_array->opcodes[use].opcode == ZEND_IS_SMALLER
|
||||
&& ssa->ops[use].op2_use == result_var
|
||||
&& zend_dfa_try_to_replace_result(op_array, ssa, op_1, v)) {
|
||||
opline->opcode = ZEND_PRE_DEC;
|
||||
op_array->opcodes[use].opcode = ZEND_IS_SMALLER_OR_EQUAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opline->opcode == ZEND_ASSIGN
|
||||
&& ssa->ops[op_1].op1_def == v
|
||||
&& !RETURN_VALUE_USED(opline)
|
||||
@@ -1312,7 +1421,6 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
|
||||
if (orig_var >= 0
|
||||
&& !(ssa->var_info[orig_var].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))
|
||||
) {
|
||||
|
||||
int src_var = ssa->ops[op_1].op2_use;
|
||||
|
||||
if ((opline->op2_type & (IS_TMP_VAR|IS_VAR))
|
||||
|
||||
Reference in New Issue
Block a user