/* Phis */
FOREACH_PHI(phi) {
- int source;
- FOREACH_PHI_SOURCE(phi, source) {
+ unsigned num_sources = NUM_PHI_SOURCES(phi);
+ for (i = 0; i < num_sources; i++) {
+ int source = phi->sources[i];
if (source < 0) {
FAIL(VARFMT " negative source\n", VAR(phi->ssa_var));
}
if (ssa->vars[source].var != ssa->vars[phi->ssa_var].var) {
FAIL(VARFMT " source of phi for " VARFMT "\n", VAR(source), VAR(phi->ssa_var));
}
- } FOREACH_PHI_SOURCE_END();
+ if (phi->use_chains[i]) {
+ int j;
+ for (j = i + 1; j < num_sources; j++) {
+ if (phi->sources[j] == source && phi->use_chains[j]) {
+ FAIL("use chain for source " VARFMT " of phi " VARFMT
+ " at %d despite earlier use\n", VAR(source), VAR(phi->ssa_var), j);
+ }
+ }
+ }
+ }
if (ssa->vars[phi->ssa_var].definition_phi != phi) {
FAIL(VARFMT " does not define this phi\n", VAR(phi->ssa_var));
}
for (j = 0; j < predecessors_count; j++) {
if (phi->sources[j] == var_num) {
if (j < pred_offset) {
- if (next_phi == NULL) {
- next_phi = phi->use_chains[pred_offset];
- } else {
- ZEND_ASSERT(phi->use_chains[pred_offset] == NULL);
- }
+ ZEND_ASSERT(next_phi == NULL);
} else if (j >= pred_offset) {
phi->use_chains[j] = next_phi;
}
new_var->phi_use_chain = phi;
}
after_first_new_source = 1;
+ } else {
+ phi->use_chains[j] = NULL;
}
}
}
--- /dev/null
+--TEST--
+Check that phi use chains are correctly maintained when removing blocks
+--FILE--
+<?php
+
+function test(array $adapters) {
+ foreach ($adapters as $adapter) {
+ if (\in_array('cli-server', ['cli', 'phpdbg'], true) && $adapter instanceof stdClass && !\filter_var('1', \FILTER_VALIDATE_BOOLEAN)) {
+ continue;
+ }
+
+ $adapters[] = $adapter;
+ }
+}
+
+?>
+===DONE===
+--EXPECT--
+===DONE===