From: Nikita Popov Date: Sun, 17 Jul 2016 20:47:49 +0000 (+0200) Subject: Fix optimization of $i = $i++ X-Git-Tag: php-7.1.0beta1~40 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=42260325a47480bc97f7dceb2ac5d8e8d7799928;p=php Fix optimization of $i = $i++ --- diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index a64619bfe8..a99d50fc41 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -343,7 +343,8 @@ static inline zend_bool can_elide_return_type_check( return 1; } -static zend_bool opline_supports_assign_contraction(zend_ssa *ssa, zend_op *opline, int src_var) { +static zend_bool opline_supports_assign_contraction( + zend_ssa *ssa, zend_op *opline, int src_var, uint32_t cv_var) { if (opline->opcode == ZEND_NEW) { /* see Zend/tests/generators/aborted_yield_during_new.phpt */ return 0; @@ -358,6 +359,12 @@ static zend_bool opline_supports_assign_contraction(zend_ssa *ssa, zend_op *opli return !((type & MAY_BE_ANY) & ~simple); } + if (opline->opcode == ZEND_POST_INC || opline->opcode == ZEND_POST_DEC) { + /* POST_INC/DEC write the result variable before performing the inc/dec. For $i = $i++ + * eliding the temporary variable would thus yield an incorrect result. */ + return opline->op1_type != IS_CV || opline->op1.var != cv_var; + } + return 1; } @@ -476,7 +483,8 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx && !ssa->vars[src_var].phi_use_chain && !ssa->vars[src_var].sym_use_chain && opline_supports_assign_contraction( - ssa, &op_array->opcodes[ssa->vars[src_var].definition], src_var) + ssa, &op_array->opcodes[ssa->vars[src_var].definition], + src_var, opline->op1.var) ) { int op_2 = ssa->vars[src_var].definition; diff --git a/ext/opcache/tests/ssa_bug_006.phpt b/ext/opcache/tests/ssa_bug_006.phpt new file mode 100644 index 0000000000..624c1e0047 --- /dev/null +++ b/ext/opcache/tests/ssa_bug_006.phpt @@ -0,0 +1,20 @@ +--TEST-- +Incorrect optimization of $i = $i++ +--FILE-- + +--EXPECT-- +int(1) +int(1)