Skip to content

Commit ea115a6

Browse files
committed
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...
1 parent 4a98f42 commit ea115a6

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

ext/opcache/Optimizer/scdf.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ static zend_bool kept_alive_by_loop_var_free(scdf_ctx *scdf, uint32_t block_idx)
189189
const zend_op_array *op_array = scdf->op_array;
190190
const zend_cfg *cfg = &scdf->ssa->cfg;
191191
const zend_basic_block *block = &cfg->blocks[block_idx];
192+
if (!(cfg->flags & ZEND_FUNC_FREE_LOOP_VAR)) {
193+
return 0;
194+
}
192195
for (i = block->start; i < block->start + block->len; i++) {
193196
zend_op *opline = &op_array->opcodes[i];
194197
if (opline->opcode == ZEND_FE_FREE ||
@@ -215,10 +218,6 @@ int scdf_remove_unreachable_blocks(scdf_ctx *scdf) {
215218
zend_ssa *ssa = scdf->ssa;
216219
int i;
217220
int removed_ops = 0;
218-
219-
if (!(ssa->cfg.flags & ZEND_FUNC_FREE_LOOP_VAR)) {
220-
return 0;
221-
}
222221
for (i = 0; i < ssa->cfg.blocks_count; i++) {
223222
if (!zend_bitset_in(scdf->executable_blocks, i)
224223
&& (ssa->cfg.blocks[i].flags & ZEND_BB_REACHABLE)

ext/opcache/tests/opt/sccp_026.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
SCCP 026: Elimination of dead code due to conflicting type checks
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.opt_debug_level=0x20000
8+
opcache.preload=
9+
--SKIPIF--
10+
<?php require_once('skipif.inc'); ?>
11+
--FILE--
12+
<?php
13+
function test($var) {
14+
if (!is_string($var) || (is_object($var) && !method_exists($var, '__toString'))) {
15+
return;
16+
}
17+
18+
var_dump($username);
19+
}
20+
?>
21+
--EXPECTF--
22+
$_main: ; (lines=1, args=0, vars=0, tmps=0)
23+
; (after optimizer)
24+
; %s:1-10
25+
L0 (10): RETURN int(1)
26+
27+
test: ; (lines=9, args=1, vars=2, tmps=1)
28+
; (after optimizer)
29+
; %s:2-8
30+
L0 (2): CV0($var) = RECV 1
31+
L1 (3): T2 = TYPE_CHECK (string) CV0($var)
32+
L2 (3): JMPZ T2 L4
33+
L3 (3): JMP L5
34+
L4 (4): RETURN null
35+
L5 (7): INIT_FCALL 1 %d string("var_dump")
36+
L6 (7): SEND_VAR CV1($username) 1
37+
L7 (7): DO_ICALL
38+
L8 (8): RETURN null

0 commit comments

Comments
 (0)