@@ -204,11 +204,23 @@ static inline zend_bool may_have_side_effects(
204
204
case ZEND_ASSIGN_BW_AND :
205
205
case ZEND_ASSIGN_BW_XOR :
206
206
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 ) {
209
214
return 1 ;
210
215
}
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 ;
212
224
default :
213
225
/* For everything we didn't handle, assume a side-effect */
214
226
return 1 ;
@@ -645,6 +657,8 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
645
657
/* Mark reacable instruction without side effects as dead */
646
658
int b = ssa -> cfg .blocks_count ;
647
659
while (b > 0 ) {
660
+ int op_data = -1 ;
661
+
648
662
b -- ;
649
663
zend_basic_block * block = & ssa -> cfg .blocks [b ];
650
664
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
654
668
while (i > block -> start ) {
655
669
i -- ;
656
670
671
+ if (op_array -> opcodes [i ].opcode == ZEND_OP_DATA ) {
672
+ op_data = i ;
673
+ continue ;
674
+ }
675
+
657
676
if (zend_bitset_in (ctx .instr_worklist , i )) {
658
677
zend_bitset_excl (ctx .instr_worklist , i );
659
678
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
+ }
660
682
} else if (may_have_side_effects (op_array , ssa , & op_array -> opcodes [i ], & ssa -> ops [i ], ctx .reorder_dtor_effects )
661
683
|| zend_may_throw (& op_array -> opcodes [i ], op_array , ssa )
662
684
|| (has_varargs && may_break_varargs (op_array , ssa , & ssa -> ops [i ]))) {
663
685
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
+ }
664
689
} else {
665
690
zend_bitset_incl (ctx .instr_dead , i );
691
+ if (op_data >= 0 ) {
692
+ zend_bitset_incl (ctx .instr_dead , op_data );
693
+ }
666
694
}
667
-
695
+ op_data = -1 ;
668
696
}
669
697
}
670
698
@@ -674,6 +702,10 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
674
702
while ((i = zend_bitset_pop_first (ctx .instr_worklist , ctx .instr_worklist_len )) >= 0 ) {
675
703
zend_bitset_excl (ctx .instr_dead , i );
676
704
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
+ }
677
709
}
678
710
while ((i = zend_bitset_pop_first (ctx .phi_worklist , ctx .phi_worklist_len )) >= 0 ) {
679
711
zend_bitset_excl (ctx .phi_dead , i );
0 commit comments