]> granicus.if.org Git - php/commitdiff
Added simple DFA optimisation pattern (just to prove the concept)
authorDmitry Stogov <dmitry@zend.com>
Wed, 16 Dec 2015 10:14:31 +0000 (13:14 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 16 Dec 2015 10:14:31 +0000 (13:14 +0300)
ext/opcache/Optimizer/dfa_pass.c
ext/opcache/Optimizer/zend_ssa.c
ext/opcache/Optimizer/zend_ssa.h

index f4ec641c40f3ccde9419ad5b6aa5f1e8e5c4b713..0e7a9329c74e9c781f0ddb45d1721ee372392dd2 100644 (file)
@@ -128,7 +128,62 @@ void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "before dfa pass", &ssa);
        }
 
-       //TODO: Add optimization???
+       //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
+               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
+                                && !(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 (ctx->debug_level & ZEND_DUMP_AFTER_DFA_PASS) {
                zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "after dfa pass", &ssa);
index 24b2eb1ed52b396358824daca1ef146e48cb2667..86e7e2d6ff6948f1fbd9f5afb451c44c6f03cf03 100644 (file)
@@ -994,6 +994,46 @@ int zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_
 }
 /* }}} */
 
+int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var)
+{
+       if (ssa->vars[var].use_chain == op) {
+               ssa->vars[var].use_chain = zend_ssa_next_use(ssa->ops, var, op);
+               return 1;
+       } else {
+               int use = ssa->vars[var].use_chain;
+
+               while (use >= 0) {
+                       if (ssa->ops[use].result_use == var) {
+                               if (ssa->ops[use].res_use_chain == op) {
+                                       ssa->ops[use].res_use_chain = zend_ssa_next_use(ssa->ops, var, op);
+                                       return 1;
+                               } else {
+                                       use = ssa->ops[use].res_use_chain;
+                               }
+                       } else if (ssa->ops[use].op1_use == var) {
+                               if (ssa->ops[use].op1_use_chain == op) {
+                                       ssa->ops[use].op1_use_chain = zend_ssa_next_use(ssa->ops, var, op);
+                                       return 1;
+                               } else {
+                                       use = ssa->ops[use].op1_use_chain;
+                               }
+                       } else if (ssa->ops[use].op2_use == var) {
+                               if (ssa->ops[use].op2_use_chain == op) {
+                                       ssa->ops[use].op2_use_chain = zend_ssa_next_use(ssa->ops, var, op);
+                                       return 1;
+                               } else {
+                                       use = ssa->ops[use].op2_use_chain;
+                               }
+                       } else {
+                               break;
+                       }
+               }
+               /* something wrong */
+               ZEND_ASSERT(0);
+               return 0;
+       }
+}
+
 /*
  * Local variables:
  * tab-width: 4
index dc0c1b3ababa68e0fc997434a3b69ddcc59251d5..bc6c22e31570861ff08df7cb907b924b5a064c34 100644 (file)
@@ -117,6 +117,7 @@ BEGIN_EXTERN_C()
 
 int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, uint32_t *func_flags);
 int zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_array, zend_ssa *ssa);
+int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var);
 
 END_EXTERN_C()