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) {
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)
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))