return 1; /* incorrect type */
}
break;
+ case ZEND_INIT_ARRAY:
+ case ZEND_ADD_ARRAY_ELEMENT:
+ if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
+ return 1;
+ }
+ if (OP1_INFO() & MAY_BE_OBJECT) {
+ /* object aliasing */
+ return 1;
+ }
+ /* reference dependencies processed separately */
+ break;
default:
return 1;
}
switch (opline->opcode) {
case ZEND_ASSIGN_DIM:
case ZEND_ASSIGN_OBJ:
+ if (OP1_INFO() & MAY_BE_OBJECT) {
+ /* object aliasing */
+ return 1;
+ }
/* reference dependencies processed separately */
break;
case ZEND_ASSIGN:
+ if (OP1_INFO() & MAY_BE_REF) {
+ return 1;
+ }
+ if (op->op1_def >= 0 && ssa->vars[op->op1_def].alias) {
+ return 1;
+ }
if (opline->op2_type == IS_CV || opline->result_type != IS_UNUSED) {
if (OP2_INFO() & MAY_BE_OBJECT) {
/* object aliasing */
FOREACH_USE(ssa->vars + i, use) {
zend_ssa_op *op = ssa->ops + use;
zend_op *opline = op_array->opcodes + use;
+ int enclosing_root;
if ((opline->opcode == ZEND_ASSIGN_DIM ||
opline->opcode == ZEND_ASSIGN_OBJ) &&
op->op2_use == i &&
op->op1_use >= 0) {
- int root2 = ees[op->op1_use];
-
- if (ssa_vars[root2].escape_state == ESCAPE_STATE_UNKNOWN ||
- ssa_vars[root2].escape_state > ssa_vars[root].escape_state) {
- if (ssa_vars[root2].escape_state == ESCAPE_STATE_UNKNOWN) {
- ssa_vars[root].escape_state = ESCAPE_STATE_GLOBAL_ESCAPE;
- } else {
- ssa_vars[root].escape_state = ssa_vars[root2].escape_state;
- }
- if (ssa_vars[root].escape_state == ESCAPE_STATE_GLOBAL_ESCAPE) {
- num_non_escaped--;
- if (num_non_escaped == 0) {
- i = ssa_vars_count;
- changed = 0;
- }
- break;
+ enclosing_root = ees[op->op1_use];
+ } else if ((opline->opcode == ZEND_INIT_ARRAY ||
+ opline->opcode == ZEND_ADD_ARRAY_ELEMENT) &&
+ op->op1_use == i &&
+ op->result_def >= 0) {
+ enclosing_root = ees[op->result_def];
+ } else {
+ continue;
+ }
+
+ if (ssa_vars[enclosing_root].escape_state == ESCAPE_STATE_UNKNOWN ||
+ ssa_vars[enclosing_root].escape_state > ssa_vars[root].escape_state) {
+ if (ssa_vars[enclosing_root].escape_state == ESCAPE_STATE_UNKNOWN) {
+ ssa_vars[root].escape_state = ESCAPE_STATE_GLOBAL_ESCAPE;
+ } else {
+ ssa_vars[root].escape_state = ssa_vars[enclosing_root].escape_state;
+ }
+ if (ssa_vars[root].escape_state == ESCAPE_STATE_GLOBAL_ESCAPE) {
+ num_non_escaped--;
+ if (num_non_escaped == 0) {
+ i = ssa_vars_count;
+ changed = 0;
} else {
changed = 1;
}
+ break;
+ } else {
+ changed = 1;
}
}
} FOREACH_USE_END();
--- /dev/null
+--TEST--
+DCE 007: Escaiping of enclosed arrays doesn't prevent removing of enclosing array
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.opt_debug_level=0x20000
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+function esc($x) {
+ $a = [$x];
+ $b = [$a];
+ return $a;
+}
+--EXPECTF--
+$_main: ; (lines=1, args=0, vars=0, tmps=0)
+ ; (after optimizer)
+ ; %sdce_007.php:1-7
+L0: RETURN int(1)
+
+esc: ; (lines=3, args=1, vars=2, tmps=0)
+ ; (after optimizer)
+ ; %sdce_007.php:2-6
+L0: CV0($x) = RECV 1
+L1: CV1($a) = INIT_ARRAY 1 (packed) CV0($x) NEXT
+L2: RETURN CV1($a)