]> granicus.if.org Git - php/commitdiff
Add another DFA optimization pattern (ASSIGN -> QM_ASSING)
authorDmitry Stogov <dmitry@zend.com>
Thu, 24 Dec 2015 08:06:02 +0000 (11:06 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 24 Dec 2015 08:06:02 +0000 (11:06 +0300)
ext/opcache/Optimizer/dfa_pass.c

index 0e7a9329c74e9c781f0ddb45d1721ee372392dd2..ac7a193675ab616d30b9a18a9681ea79b5f0d030 100644 (file)
@@ -131,57 +131,98 @@ void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
        //TODO: Add optimization patterns ???
        if (ssa.var_info) {
                int i;
-               // 1: #1.T  = OP_Y                                   |  #3.CV = OP_Y
-               // 2: ASSIGN #2.CV [undef,null,bool] -> #3.cv, #1.T  |  NOP
+               int remove_nops = 0;
+
+               // 1: #1.T  = OP_Y                                |  #3.CV = OP_Y
+               // 2: ASSIGN #2.CV [undef,scalar] -> #3.CV, #1.T  |  NOP
+               // --
+               // 2: ASSIGN #2.CV [undef,scalar] -> #3.CV, C     |  3.CV = QM_ASSIGN C
+               // --
+               // 2: ASSIGN #2.CV [undef,scalar] -> #3.CV, #1.CV |  3.CV = QM_ASSIGN #1.CV
+
                for (i = 0; i < ssa.vars_count; i++) {
                        int op2 = ssa.vars[i].definition;
 
                        if (op2 >= 0
                         && op_array->opcodes[op2].opcode == ZEND_ASSIGN
                         && op_array->opcodes[op2].op1_type == IS_CV
-                        && (op_array->opcodes[op2].op2_type & (IS_TMP_VAR|IS_VAR))
                         && !RETURN_VALUE_USED(&op_array->opcodes[op2])
                        ) {
-
-                               int var1 = ssa.ops[op2].op2_use;
                                int var2 = ssa.ops[op2].op1_use;
 
-                               if (var1 >= 0
-                                && var2 >= 0
+                               if (var2 >= 0
                                 && !(ssa.var_info[var2].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))
-                                && !(ssa.var_info[var1].type & MAY_BE_REF)
-                                && ssa.vars[var1].definition >= 0
-                                && ssa.ops[ssa.vars[var1].definition].result_def == var1
-                                && ssa.ops[ssa.vars[var1].definition].result_use < 0
-                                && ssa.vars[var1].use_chain == op2
-                                && ssa.ops[op2].op2_use_chain < 0
-                                && !ssa.vars[var1].phi_use_chain
-                                && !ssa.vars[var1].sym_use_chain
                                ) {
-                                       int op1 = ssa.vars[var1].definition;
-                                       int var3 = i;
-
-                                       if (zend_ssa_unlink_use_chain(&ssa, op2, var2)) {
-                                               /* Reconstruct SSA */
-                                               ssa.vars[var3].definition = op1;
-                                               ssa.ops[op1].result_def = var3;
-
-                                               ssa.vars[var1].definition = -1;
-                                               ssa.vars[var1].use_chain = -1;
-
-                                               ssa.ops[op2].op1_use = -1;
-                                               ssa.ops[op2].op2_use = -1;
-                                               ssa.ops[op2].op1_def = -1;
-                                               ssa.ops[op2].op1_use_chain = -1;
-
-                                               /* Update opcodes */
-                                               op_array->opcodes[op1].result_type = op_array->opcodes[op2].op1_type;
-                                               op_array->opcodes[op1].result.var = op_array->opcodes[op2].op1.var;
-                                               MAKE_NOP(&op_array->opcodes[op2]);
+
+                                       if (op_array->opcodes[op2].op2_type & (IS_TMP_VAR|IS_VAR)) {
+                                               int var1 = ssa.ops[op2].op2_use;
+
+                                               if (var1 >= 0
+                                                && !(ssa.var_info[var1].type & MAY_BE_REF)
+                                                && ssa.vars[var1].definition >= 0
+                                                && ssa.ops[ssa.vars[var1].definition].result_def == var1
+                                                && ssa.ops[ssa.vars[var1].definition].result_use < 0
+                                                && ssa.vars[var1].use_chain == op2
+                                                && ssa.ops[op2].op2_use_chain < 0
+                                                && !ssa.vars[var1].phi_use_chain
+                                                && !ssa.vars[var1].sym_use_chain
+                                               ) {
+                                                       int op1 = ssa.vars[var1].definition;
+                                                       int var3 = i;
+
+                                                       if (zend_ssa_unlink_use_chain(&ssa, op2, var2)) {
+                                                               /* Reconstruct SSA */
+                                                               ssa.vars[var3].definition = op1;
+                                                               ssa.ops[op1].result_def = var3;
+
+                                                               ssa.vars[var1].definition = -1;
+                                                               ssa.vars[var1].use_chain = -1;
+
+                                                               ssa.ops[op2].op1_use = -1;
+                                                               ssa.ops[op2].op2_use = -1;
+                                                               ssa.ops[op2].op1_def = -1;
+                                                               ssa.ops[op2].op1_use_chain = -1;
+
+                                                               /* Update opcodes */
+                                                               op_array->opcodes[op1].result_type = op_array->opcodes[op2].op1_type;
+                                                               op_array->opcodes[op1].result.var = op_array->opcodes[op2].op1.var;
+                                                               MAKE_NOP(&op_array->opcodes[op2]);
+                                                               remove_nops = 1;
+                                                       }
+                                               }
+                                       } else if (op_array->opcodes[op2].op2_type == IS_CONST
+                                        || (op_array->opcodes[op2].op2_type == IS_CV
+                                            && ssa.ops[op2].op2_use >= 0
+                                            && ssa.ops[op2].op2_def < 0
+                                            && !(ssa.var_info[ssa.ops[op2].op2_use].type & MAY_BE_REF))
+                                       ) {
+                                               int var3 = i;
+
+                                               if (zend_ssa_unlink_use_chain(&ssa, op2, var2)) {
+                                                       /* Reconstruct SSA */
+                                                       ssa.ops[op2].result_def = var3;
+                                                       ssa.ops[op2].op1_def = -1;
+                                                       ssa.ops[op2].op1_use = ssa.ops[op2].op2_use;
+                                                       ssa.ops[op2].op1_use_chain = ssa.ops[op2].op2_use_chain;
+                                                       ssa.ops[op2].op2_use = -1;
+                                                       ssa.ops[op2].op2_use_chain = -1;
+
+                                                       /* Update opcode */
+                                                       op_array->opcodes[op2].result_type = op_array->opcodes[op2].op1_type;
+                                                       op_array->opcodes[op2].result.var = op_array->opcodes[op2].op1.var;
+                                                       op_array->opcodes[op2].op1_type = op_array->opcodes[op2].op2_type;
+                                                       op_array->opcodes[op2].op1.var = op_array->opcodes[op2].op2.var;
+                                                       op_array->opcodes[op2].op2_type = IS_UNUSED;
+                                                       op_array->opcodes[op2].op2.var = 0;
+                                                       op_array->opcodes[op2].opcode = ZEND_QM_ASSIGN;
+                                               }
                                        }
                                }
                        }
                }
+               if (remove_nops) {
+                       // TODO: remove nop???
+               }
        }