Skip to content

Commit 47a722e

Browse files
committed
Merge branch 'PHP-8.0'
* PHP-8.0: Don't mark non-refcounted phi as live
2 parents dbe2cdd + 332a367 commit 47a722e

File tree

2 files changed

+16
-14
lines changed

2 files changed

+16
-14
lines changed

Zend/Optimizer/dce.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -378,11 +378,15 @@ static bool try_remove_var_def(context *ctx, int free_var, int use_chain, zend_o
378378
return 0;
379379
}
380380

381+
static zend_always_inline zend_bool may_be_refcounted(uint32_t type) {
382+
return (type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) != 0;
383+
}
384+
381385
static inline bool is_free_of_live_var(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
382386
switch (opline->opcode) {
383387
case ZEND_FREE:
384388
/* It is always safe to remove FREEs of non-refcounted values, even if they are live. */
385-
if (!(ctx->ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) {
389+
if (!may_be_refcounted(ctx->ssa->var_info[ssa_op->op1_use].type)) {
386390
return 0;
387391
}
388392
ZEND_FALLTHROUGH;
@@ -410,17 +414,16 @@ static bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
410414

411415
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))&& !is_var_dead(ctx, ssa_op->op1_use)) {
412416
if (!try_remove_var_def(ctx, ssa_op->op1_use, ssa_op->op1_use_chain, opline)) {
413-
if (ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)
414-
&& opline->opcode != ZEND_CASE
415-
&& opline->opcode != ZEND_CASE_STRICT) {
417+
if (may_be_refcounted(ssa->var_info[ssa_op->op1_use].type)
418+
&& opline->opcode != ZEND_CASE && opline->opcode != ZEND_CASE_STRICT) {
416419
free_var = ssa_op->op1_use;
417420
free_var_type = opline->op1_type;
418421
}
419422
}
420423
}
421424
if ((opline->op2_type & (IS_VAR|IS_TMP_VAR)) && !is_var_dead(ctx, ssa_op->op2_use)) {
422425
if (!try_remove_var_def(ctx, ssa_op->op2_use, ssa_op->op2_use_chain, opline)) {
423-
if (ssa->var_info[ssa_op->op2_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
426+
if (may_be_refcounted(ssa->var_info[ssa_op->op2_use].type)) {
424427
if (free_var >= 0) {
425428
// TODO: We can't free two vars. Keep instruction alive.
426429
zend_bitset_excl(ctx->instr_dead, opline - ctx->op_array->opcodes);
@@ -531,7 +534,8 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, bool reorder_d
531534
* of the producing instructions, as it combines producing the result with control flow.
532535
* This can be made more precise if there are any cases where this is not the case. */
533536
FOREACH_PHI(phi) {
534-
if (phi->var >= op_array->last_var) {
537+
if (phi->var >= op_array->last_var
538+
&& may_be_refcounted(ssa->var_info[phi->ssa_var].type)) {
535539
zend_bitset_excl(ctx.phi_dead, phi->ssa_var);
536540
add_phi_sources_to_worklists(&ctx, phi, 0);
537541
}

ext/opcache/tests/opt/coalesce.phpt

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,15 @@ $_main:
2929
0000 RETURN int(1)
3030

3131
a:
32-
; (lines=3, args=0, vars=1, tmps=1)
32+
; (lines=2, args=0, vars=1, tmps=1)
3333
; (after optimizer)
3434
; %s
35-
0000 T1 = COALESCE CV0($test) 0002
36-
0001 T1 = QM_ASSIGN bool(true)
37-
0002 RETURN bool(true)
35+
0000 T1 = COALESCE CV0($test) 0001
36+
0001 RETURN bool(true)
3837

3938
b:
40-
; (lines=3, args=0, vars=1, tmps=1)
39+
; (lines=2, args=0, vars=1, tmps=1)
4140
; (after optimizer)
4241
; %s
43-
0000 T1 = COALESCE CV0($test) 0002
44-
0001 T1 = ASSIGN CV0($test) bool(true)
45-
0002 RETURN bool(true)
42+
0000 T1 = COALESCE CV0($test) 0001
43+
0001 RETURN bool(true)

0 commit comments

Comments
 (0)