diff --git a/ext/opcache/Optimizer/dce.c b/ext/opcache/Optimizer/dce.c index 8370bdc7792..0ba91e66e0c 100644 --- a/ext/opcache/Optimizer/dce.c +++ b/ext/opcache/Optimizer/dce.c @@ -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); 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 */ int b = ssa->cfg.blocks_count; while (b > 0) { diff --git a/ext/opcache/tests/opt/dce_009.phpt b/ext/opcache/tests/opt/dce_009.phpt new file mode 100644 index 00000000000..d6eba581728 --- /dev/null +++ b/ext/opcache/tests/opt/dce_009.phpt @@ -0,0 +1,17 @@ +--TEST-- +Incorrect DCE of FREE of COALESCE +--FILE-- + +--EXPECT-- +int(6)