@@ -378,11 +378,15 @@ static bool try_remove_var_def(context *ctx, int free_var, int use_chain, zend_o
378
378
return 0 ;
379
379
}
380
380
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
+
381
385
static inline bool is_free_of_live_var (context * ctx , zend_op * opline , zend_ssa_op * ssa_op ) {
382
386
switch (opline -> opcode ) {
383
387
case ZEND_FREE :
384
388
/* 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 )) {
386
390
return 0 ;
387
391
}
388
392
ZEND_FALLTHROUGH ;
@@ -410,17 +414,16 @@ static bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
410
414
411
415
if ((opline -> op1_type & (IS_VAR |IS_TMP_VAR ))&& !is_var_dead (ctx , ssa_op -> op1_use )) {
412
416
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 ) {
416
419
free_var = ssa_op -> op1_use ;
417
420
free_var_type = opline -> op1_type ;
418
421
}
419
422
}
420
423
}
421
424
if ((opline -> op2_type & (IS_VAR |IS_TMP_VAR )) && !is_var_dead (ctx , ssa_op -> op2_use )) {
422
425
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 )) {
424
427
if (free_var >= 0 ) {
425
428
// TODO: We can't free two vars. Keep instruction alive.
426
429
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
531
534
* of the producing instructions, as it combines producing the result with control flow.
532
535
* This can be made more precise if there are any cases where this is not the case. */
533
536
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 )) {
535
539
zend_bitset_excl (ctx .phi_dead , phi -> ssa_var );
536
540
add_phi_sources_to_worklists (& ctx , phi , 0 );
537
541
}
0 commit comments