mirror of
https://github.com/php/php-src.git
synced 2024-09-22 10:27:25 +00:00
Fix DCE of FREE of COALESCE
When encountering the following SSA graph: BB1: #2.T1 [string] = COALESCE #1.CV0($str) [null, string] BB2 BB2: #5.T1 [string] = QM_ASSIGN string("") BB3: #7.X1 [string] = Phi(#2.X1 [string], #5.X1 [string]) FREE #7.T1 [string] We would currently determine that #7, #5 are dead, and eliminate the FREE and QM_ASSIGN. However, we cannot eliminate #2, as COALESCE is also responsible for control flow. Fix this my marking all non-CV phis as live to start with. This can be relaxed to check the kind of the source instruction, but I couldn't immediately come up with a case where it would be useful.
This commit is contained in:
parent
25f5a1b2e1
commit
0826a54836
@ -503,6 +503,16 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
|
|||||||
ctx.phi_dead = alloca(sizeof(zend_ulong) * ctx.phi_worklist_len);
|
ctx.phi_dead = alloca(sizeof(zend_ulong) * ctx.phi_worklist_len);
|
||||||
memset(ctx.phi_dead, 0xff, sizeof(zend_ulong) * ctx.phi_worklist_len);
|
memset(ctx.phi_dead, 0xff, sizeof(zend_ulong) * ctx.phi_worklist_len);
|
||||||
|
|
||||||
|
/* Mark non-CV phis as live. Even if the result is unused, we generally cannot remove one
|
||||||
|
* of the producing instructions, as it combines producing the result with control flow.
|
||||||
|
* This can be made more precise if there are any cases where this is not the case. */
|
||||||
|
FOREACH_PHI(phi) {
|
||||||
|
if (phi->var >= op_array->last_var) {
|
||||||
|
zend_bitset_excl(ctx.phi_dead, phi->ssa_var);
|
||||||
|
add_phi_sources_to_worklists(&ctx, phi, 0);
|
||||||
|
}
|
||||||
|
} FOREACH_PHI_END();
|
||||||
|
|
||||||
/* Mark reacable instruction without side effects as dead */
|
/* Mark reacable instruction without side effects as dead */
|
||||||
int b = ssa->cfg.blocks_count;
|
int b = ssa->cfg.blocks_count;
|
||||||
while (b > 0) {
|
while (b > 0) {
|
||||||
|
17
ext/opcache/tests/opt/dce_009.phpt
Normal file
17
ext/opcache/tests/opt/dce_009.phpt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
--TEST--
|
||||||
|
Incorrect DCE of FREE of COALESCE
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test(?string $str) {
|
||||||
|
$str ?? $str = '';
|
||||||
|
return strlen($str);
|
||||||
|
}
|
||||||
|
|
||||||
|
$foo = 'foo';
|
||||||
|
$foo .= 'bar';
|
||||||
|
var_dump(test($foo));
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
int(6)
|
Loading…
Reference in New Issue
Block a user