Skip to content

Commit 332a367

Browse files
committed
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Don't mark non-refcounted phi as live
2 parents 59b2a89 + 29fa4d2 commit 332a367

File tree

1 file changed

+10
-7
lines changed
  • ext/opcache/Optimizer

1 file changed

+10
-7
lines changed

ext/opcache/Optimizer/dce.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ static zend_bool try_remove_var_def(context *ctx, int free_var, int use_chain, z
373373
return 0;
374374
}
375375

376+
static zend_always_inline zend_bool may_be_refcounted(uint32_t type) {
377+
return (type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) != 0;
378+
}
379+
376380
/* Returns whether the instruction has been DCEd */
377381
static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
378382
zend_ssa *ssa = ctx->ssa;
@@ -384,25 +388,23 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
384388
}
385389

386390
/* We mark FREEs as dead, but they're only really dead if the destroyed var is dead */
387-
if (opline->opcode == ZEND_FREE
388-
&& (ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))
391+
if (opline->opcode == ZEND_FREE && may_be_refcounted(ssa->var_info[ssa_op->op1_use].type)
389392
&& !is_var_dead(ctx, ssa_op->op1_use)) {
390393
return 0;
391394
}
392395

393396
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))&& !is_var_dead(ctx, ssa_op->op1_use)) {
394397
if (!try_remove_var_def(ctx, ssa_op->op1_use, ssa_op->op1_use_chain, opline)) {
395-
if (ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)
396-
&& opline->opcode != ZEND_CASE
397-
&& opline->opcode != ZEND_CASE_STRICT) {
398+
if (may_be_refcounted(ssa->var_info[ssa_op->op1_use].type)
399+
&& opline->opcode != ZEND_CASE && opline->opcode != ZEND_CASE_STRICT) {
398400
free_var = ssa_op->op1_use;
399401
free_var_type = opline->op1_type;
400402
}
401403
}
402404
}
403405
if ((opline->op2_type & (IS_VAR|IS_TMP_VAR)) && !is_var_dead(ctx, ssa_op->op2_use)) {
404406
if (!try_remove_var_def(ctx, ssa_op->op2_use, ssa_op->op2_use_chain, opline)) {
405-
if (ssa->var_info[ssa_op->op2_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
407+
if (may_be_refcounted(ssa->var_info[ssa_op->op2_use].type)) {
406408
if (free_var >= 0) {
407409
// TODO: We can't free two vars. Keep instruction alive.
408410
zend_bitset_excl(ctx->instr_dead, opline - ctx->op_array->opcodes);
@@ -513,7 +515,8 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
513515
* of the producing instructions, as it combines producing the result with control flow.
514516
* This can be made more precise if there are any cases where this is not the case. */
515517
FOREACH_PHI(phi) {
516-
if (phi->var >= op_array->last_var) {
518+
if (phi->var >= op_array->last_var
519+
&& may_be_refcounted(ssa->var_info[phi->ssa_var].type)) {
517520
zend_bitset_excl(ctx.phi_dead, phi->ssa_var);
518521
add_phi_sources_to_worklists(&ctx, phi, 0);
519522
}

0 commit comments

Comments
 (0)