Skip to content

Commit fb571f2

Browse files
committed
Make assignment to elements of non-esaping arrays and objects removable by DCE pass.
1 parent c890ee9 commit fb571f2

File tree

1 file changed

+36
-4
lines changed
  • ext/opcache/Optimizer

1 file changed

+36
-4
lines changed

ext/opcache/Optimizer/dce.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,23 @@ static inline zend_bool may_have_side_effects(
204204
case ZEND_ASSIGN_BW_AND:
205205
case ZEND_ASSIGN_BW_XOR:
206206
case ZEND_ASSIGN_POW:
207-
if (opline->extended_value) {
208-
/* ASSIGN_DIM has no side-effect, but we can't deal with OP_DATA anyway */
207+
return is_bad_mod(ssa, ssa_op->op1_use, ssa_op->op1_def)
208+
|| (opline->extended_value
209+
&& ssa->vars[ssa_op->op1_def].escape_state != ESCAPE_STATE_NO_ESCAPE);
210+
case ZEND_ASSIGN_DIM:
211+
case ZEND_ASSIGN_OBJ:
212+
if (is_bad_mod(ssa, ssa_op->op1_use, ssa_op->op1_def)
213+
|| ssa->vars[ssa_op->op1_def].escape_state != ESCAPE_STATE_NO_ESCAPE) {
209214
return 1;
210215
}
211-
return is_bad_mod(ssa, ssa_op->op1_use, ssa_op->op1_def);
216+
if (!reorder_dtor_effects) {
217+
opline++;
218+
if (opline->op1_type != IS_CONST && (OP1_INFO() & MAY_HAVE_DTOR)) {
219+
/* DCE might shorten lifetime */
220+
return 1;
221+
}
222+
}
223+
return 0;
212224
default:
213225
/* For everything we didn't handle, assume a side-effect */
214226
return 1;
@@ -645,6 +657,8 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
645657
/* Mark reacable instruction without side effects as dead */
646658
int b = ssa->cfg.blocks_count;
647659
while (b > 0) {
660+
int op_data = -1;
661+
648662
b--;
649663
zend_basic_block *block = &ssa->cfg.blocks[b];
650664
if (!(block->flags & ZEND_BB_REACHABLE)) {
@@ -654,17 +668,31 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
654668
while (i > block->start) {
655669
i--;
656670

671+
if (op_array->opcodes[i].opcode == ZEND_OP_DATA) {
672+
op_data = i;
673+
continue;
674+
}
675+
657676
if (zend_bitset_in(ctx.instr_worklist, i)) {
658677
zend_bitset_excl(ctx.instr_worklist, i);
659678
add_operands_to_worklists(&ctx, &op_array->opcodes[i], &ssa->ops[i], 0);
679+
if (op_data >= 0) {
680+
add_operands_to_worklists(&ctx, &op_array->opcodes[op_data], &ssa->ops[op_data], 0);
681+
}
660682
} else if (may_have_side_effects(op_array, ssa, &op_array->opcodes[i], &ssa->ops[i], ctx.reorder_dtor_effects)
661683
|| zend_may_throw(&op_array->opcodes[i], op_array, ssa)
662684
|| (has_varargs && may_break_varargs(op_array, ssa, &ssa->ops[i]))) {
663685
add_operands_to_worklists(&ctx, &op_array->opcodes[i], &ssa->ops[i], 0);
686+
if (op_data >= 0) {
687+
add_operands_to_worklists(&ctx, &op_array->opcodes[op_data], &ssa->ops[op_data], 0);
688+
}
664689
} else {
665690
zend_bitset_incl(ctx.instr_dead, i);
691+
if (op_data >= 0) {
692+
zend_bitset_incl(ctx.instr_dead, op_data);
693+
}
666694
}
667-
695+
op_data = -1;
668696
}
669697
}
670698

@@ -674,6 +702,10 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
674702
while ((i = zend_bitset_pop_first(ctx.instr_worklist, ctx.instr_worklist_len)) >= 0) {
675703
zend_bitset_excl(ctx.instr_dead, i);
676704
add_operands_to_worklists(&ctx, &op_array->opcodes[i], &ssa->ops[i], 1);
705+
if (i < op_array->last && op_array->opcodes[i+1].opcode == ZEND_OP_DATA) {
706+
zend_bitset_excl(ctx.instr_dead, i+1);
707+
add_operands_to_worklists(&ctx, &op_array->opcodes[i+1], &ssa->ops[i+1], 1);
708+
}
677709
}
678710
while ((i = zend_bitset_pop_first(ctx.phi_worklist, ctx.phi_worklist_len)) >= 0) {
679711
zend_bitset_excl(ctx.phi_dead, i);

0 commit comments

Comments
 (0)