@@ -373,6 +373,10 @@ static zend_bool try_remove_var_def(context *ctx, int free_var, int use_chain, z
373
373
return 0 ;
374
374
}
375
375
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
+
376
380
/* Returns whether the instruction has been DCEd */
377
381
static zend_bool dce_instr (context * ctx , zend_op * opline , zend_ssa_op * ssa_op ) {
378
382
zend_ssa * ssa = ctx -> ssa ;
@@ -384,25 +388,23 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
384
388
}
385
389
386
390
/* 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 )
389
392
&& !is_var_dead (ctx , ssa_op -> op1_use )) {
390
393
return 0 ;
391
394
}
392
395
393
396
if ((opline -> op1_type & (IS_VAR |IS_TMP_VAR ))&& !is_var_dead (ctx , ssa_op -> op1_use )) {
394
397
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 ) {
398
400
free_var = ssa_op -> op1_use ;
399
401
free_var_type = opline -> op1_type ;
400
402
}
401
403
}
402
404
}
403
405
if ((opline -> op2_type & (IS_VAR |IS_TMP_VAR )) && !is_var_dead (ctx , ssa_op -> op2_use )) {
404
406
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 )) {
406
408
if (free_var >= 0 ) {
407
409
// TODO: We can't free two vars. Keep instruction alive.
408
410
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
513
515
* of the producing instructions, as it combines producing the result with control flow.
514
516
* This can be made more precise if there are any cases where this is not the case. */
515
517
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 )) {
517
520
zend_bitset_excl (ctx .phi_dead , phi -> ssa_var );
518
521
add_phi_sources_to_worklists (& ctx , phi , 0 );
519
522
}
0 commit comments