From: Dmitry Stogov Date: Thu, 24 Dec 2015 08:06:02 +0000 (+0300) Subject: Add another DFA optimization pattern (ASSIGN -> QM_ASSING) X-Git-Tag: php-7.1.0alpha1~617^2~147 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3d88a64e0ce3bc9ddb7a566f98b1bed2ba0ae4fd;p=php Add another DFA optimization pattern (ASSIGN -> QM_ASSING) --- diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index 0e7a9329c7..ac7a193675 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -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??? + } }