@@ -457,14 +457,29 @@ static void try_remove_trivial_phi(context *ctx, zend_ssa_phi *phi) {
457
457
}
458
458
}
459
459
460
+ static inline zend_bool may_break_varargs (const zend_op_array * op_array , const zend_ssa * ssa , const zend_ssa_op * ssa_op ) {
461
+ if (ssa_op -> op1_def >= 0
462
+ && ssa -> vars [ssa_op -> op1_def ].var < op_array -> num_args ) {
463
+ return 1 ;
464
+ }
465
+ if (ssa_op -> op2_def >= 0
466
+ && ssa -> vars [ssa_op -> op2_def ].var < op_array -> num_args ) {
467
+ return 1 ;
468
+ }
469
+ if (ssa_op -> result_def >= 0
470
+ && ssa -> vars [ssa_op -> result_def ].var < op_array -> num_args ) {
471
+ return 1 ;
472
+ }
473
+ return 0 ;
474
+ }
475
+
460
476
int dce_optimize_op_array (zend_op_array * op_array , zend_ssa * ssa , zend_bool reorder_dtor_effects ) {
461
477
int i ;
462
478
zend_ssa_phi * phi ;
463
479
int removed_ops = 0 ;
464
480
465
- /* DCE of CV operations may affect vararg functions. For now simply treat all instructions
466
- * as live if varargs in use and only collect dead phis. */
467
- zend_bool has_varargs = (ZEND_FUNC_INFO (op_array )-> flags & ZEND_FUNC_VARARG ) != 0 ;
481
+ /* DCE of CV operations that changes arguments may affect vararg functions. */
482
+ zend_bool has_varargs = ssa -> cfg .vararg ;
468
483
469
484
context ctx ;
470
485
ctx .ssa = ssa ;
@@ -504,7 +519,7 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
504
519
add_operands_to_worklists (& ctx , & op_array -> opcodes [i ], & ssa -> ops [i ], 0 );
505
520
} else if (may_have_side_effects (op_array , ssa , & op_array -> opcodes [i ], & ssa -> ops [i ], ctx .reorder_dtor_effects )
506
521
|| zend_may_throw (& op_array -> opcodes [i ], op_array , ssa )
507
- || has_varargs ) {
522
+ || ( has_varargs && may_break_varargs ( op_array , ssa , & ssa -> ops [ i ])) ) {
508
523
add_operands_to_worklists (& ctx , & op_array -> opcodes [i ], & ssa -> ops [i ], 0 );
509
524
} else {
510
525
zend_bitset_incl (ctx .instr_dead , i );
0 commit comments