summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-02-22 12:44:36 +0100
committerNikita Popov <nikita.ppv@gmail.com>2019-02-22 12:44:36 +0100
commitea115a617fea566bda787ad77ae9f9d0396da203 (patch)
tree50daaf39fd8e25508a811964d4619befc9c644c0
parent4a98f42330b81369f63e0f0ac598927e818b8bdd (diff)
downloadphp-git-ea115a617fea566bda787ad77ae9f9d0396da203.tar.gz
Fix removal of unreachable code in SCCP
Due to a wrongly placed check, we were only performing the unreachable code removal if there were loop vars...
-rw-r--r--ext/opcache/Optimizer/scdf.c7
-rw-r--r--ext/opcache/tests/opt/sccp_026.phpt38
2 files changed, 41 insertions, 4 deletions
diff --git a/ext/opcache/Optimizer/scdf.c b/ext/opcache/Optimizer/scdf.c
index f9b16411e7..96687e44f4 100644
--- a/ext/opcache/Optimizer/scdf.c
+++ b/ext/opcache/Optimizer/scdf.c
@@ -189,6 +189,9 @@ static zend_bool kept_alive_by_loop_var_free(scdf_ctx *scdf, uint32_t block_idx)
const zend_op_array *op_array = scdf->op_array;
const zend_cfg *cfg = &scdf->ssa->cfg;
const zend_basic_block *block = &cfg->blocks[block_idx];
+ if (!(cfg->flags & ZEND_FUNC_FREE_LOOP_VAR)) {
+ return 0;
+ }
for (i = block->start; i < block->start + block->len; i++) {
zend_op *opline = &op_array->opcodes[i];
if (opline->opcode == ZEND_FE_FREE ||
@@ -215,10 +218,6 @@ int scdf_remove_unreachable_blocks(scdf_ctx *scdf) {
zend_ssa *ssa = scdf->ssa;
int i;
int removed_ops = 0;
-
- if (!(ssa->cfg.flags & ZEND_FUNC_FREE_LOOP_VAR)) {
- return 0;
- }
for (i = 0; i < ssa->cfg.blocks_count; i++) {
if (!zend_bitset_in(scdf->executable_blocks, i)
&& (ssa->cfg.blocks[i].flags & ZEND_BB_REACHABLE)
diff --git a/ext/opcache/tests/opt/sccp_026.phpt b/ext/opcache/tests/opt/sccp_026.phpt
new file mode 100644
index 0000000000..132c9ddef3
--- /dev/null
+++ b/ext/opcache/tests/opt/sccp_026.phpt
@@ -0,0 +1,38 @@
+--TEST--
+SCCP 026: Elimination of dead code due to conflicting type checks
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.opt_debug_level=0x20000
+opcache.preload=
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+function test($var) {
+ if (!is_string($var) || (is_object($var) && !method_exists($var, '__toString'))) {
+ return;
+ }
+
+ var_dump($username);
+}
+?>
+--EXPECTF--
+$_main: ; (lines=1, args=0, vars=0, tmps=0)
+ ; (after optimizer)
+ ; %s:1-10
+L0 (10): RETURN int(1)
+
+test: ; (lines=9, args=1, vars=2, tmps=1)
+ ; (after optimizer)
+ ; %s:2-8
+L0 (2): CV0($var) = RECV 1
+L1 (3): T2 = TYPE_CHECK (string) CV0($var)
+L2 (3): JMPZ T2 L4
+L3 (3): JMP L5
+L4 (4): RETURN null
+L5 (7): INIT_FCALL 1 %d string("var_dump")
+L6 (7): SEND_VAR CV1($username) 1
+L7 (7): DO_ICALL
+L8 (8): RETURN null