diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/opcache/Optimizer/dfa_pass.c | 20 | ||||
-rw-r--r-- | ext/opcache/tests/opt/sccp_in_array.phpt | 14 |
2 files changed, 24 insertions, 10 deletions
diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index 765b023f07..92a7470b9e 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -474,16 +474,16 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa) int var = ssa_op->result_def; int use = ssa->vars[var].use_chain; - if (ssa->vars[var].phi_use_chain == NULL) { - if (ssa->ops[use].op1_use == var - && ssa->ops[use].op1_use_chain == -1) { - call_info->caller_call_opline->result_type = IS_TMP_VAR; - op_array->opcodes[use].op1_type = IS_TMP_VAR; - } else if (ssa->ops[use].op2_use == var - && ssa->ops[use].op2_use_chain == -1) { - call_info->caller_call_opline->result_type = IS_TMP_VAR; - op_array->opcodes[use].op2_type = IS_TMP_VAR; - } + /* If the result is used only in a JMPZ/JMPNZ, replace result type with + * IS_TMP_VAR, which will enable use of smart branches. Don't do this + * in other cases, as not all opcodes support both VAR and TMP. */ + if (ssa->vars[var].phi_use_chain == NULL + && ssa->ops[use].op1_use == var + && ssa->ops[use].op1_use_chain == -1 + && (op_array->opcodes[use].opcode == ZEND_JMPZ + || op_array->opcodes[use].opcode == ZEND_JMPNZ)) { + call_info->caller_call_opline->result_type = IS_TMP_VAR; + op_array->opcodes[use].op1_type = IS_TMP_VAR; } } } diff --git a/ext/opcache/tests/opt/sccp_in_array.phpt b/ext/opcache/tests/opt/sccp_in_array.phpt new file mode 100644 index 0000000000..e7716b8ad8 --- /dev/null +++ b/ext/opcache/tests/opt/sccp_in_array.phpt @@ -0,0 +1,14 @@ +--TEST-- +Don't replace IN_ARRAY result type if the using opcode doesn't support it +--FILE-- +<?php + +function test($v) { + $ary = ['x', 'y']; + var_dump(in_array($v, $ary)); +} +test('x'); + +?> +--EXPECT-- +bool(true) |