summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-11-09 17:08:38 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-11-09 17:08:38 +0100
commit523dd9a2d908a91b42a5cee1f124bb07964ca57c (patch)
treed6e1097e3aff3134264084196069f6ac517b0618
parent975735c02751d9409c4a4757e7b70d217f0f54fe (diff)
parentd971b67027c69390cb1fc2243eca1e3901401bf6 (diff)
downloadphp-git-523dd9a2d908a91b42a5cee1f124bb07964ca57c.tar.gz
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Fix phi use chain management when renaming variable
-rw-r--r--ext/opcache/Optimizer/ssa_integrity.c16
-rw-r--r--ext/opcache/Optimizer/zend_ssa.c8
-rw-r--r--ext/opcache/tests/phi_use_chain.phpt19
3 files changed, 35 insertions, 8 deletions
diff --git a/ext/opcache/Optimizer/ssa_integrity.c b/ext/opcache/Optimizer/ssa_integrity.c
index 4f042cae74..5cb383c77a 100644
--- a/ext/opcache/Optimizer/ssa_integrity.c
+++ b/ext/opcache/Optimizer/ssa_integrity.c
@@ -287,8 +287,9 @@ int ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *ext
/* 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));
}
@@ -298,7 +299,16 @@ int ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *ext
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));
}
diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c
index 28a39823b5..3a6a098196 100644
--- a/ext/opcache/Optimizer/zend_ssa.c
+++ b/ext/opcache/Optimizer/zend_ssa.c
@@ -1319,11 +1319,7 @@ static inline void zend_ssa_remove_phi_source(zend_ssa *ssa, zend_ssa_phi *phi,
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;
}
@@ -1612,6 +1608,8 @@ void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, zend_bool update_
new_var->phi_use_chain = phi;
}
after_first_new_source = 1;
+ } else {
+ phi->use_chains[j] = NULL;
}
}
}
diff --git a/ext/opcache/tests/phi_use_chain.phpt b/ext/opcache/tests/phi_use_chain.phpt
new file mode 100644
index 0000000000..173d874d21
--- /dev/null
+++ b/ext/opcache/tests/phi_use_chain.phpt
@@ -0,0 +1,19 @@
+--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===