@@ -82,6 +82,7 @@ static inline zend_bool may_have_side_effects(
82
82
case ZEND_IS_NOT_IDENTICAL :
83
83
case ZEND_QM_ASSIGN :
84
84
case ZEND_FREE :
85
+ case ZEND_FE_FREE :
85
86
case ZEND_TYPE_CHECK :
86
87
case ZEND_DEFINED :
87
88
case ZEND_ADD :
@@ -246,6 +247,11 @@ static inline zend_bool may_have_side_effects(
246
247
return 0 ;
247
248
case ZEND_CHECK_VAR :
248
249
return (OP1_INFO () & MAY_BE_UNDEF ) != 0 ;
250
+ case ZEND_FE_RESET_R :
251
+ case ZEND_FE_RESET_RW :
252
+ /* Model as not having side-effects -- let the side-effect be introduced by
253
+ * FE_FETCH if the array is not known to be non-empty. */
254
+ return (OP1_INFO () & MAY_BE_ANY ) != MAY_BE_ARRAY ;
249
255
default :
250
256
/* For everything we didn't handle, assume a side-effect */
251
257
return 1 ;
@@ -373,6 +379,21 @@ static zend_bool try_remove_var_def(context *ctx, int free_var, int use_chain, z
373
379
return 0 ;
374
380
}
375
381
382
+ static inline zend_bool is_free_of_live_var (context * ctx , zend_op * opline , zend_ssa_op * ssa_op ) {
383
+ switch (opline -> opcode ) {
384
+ case ZEND_FREE :
385
+ /* It is always safe to remove FREEs of non-refcounted values, even if they are live. */
386
+ 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 ))) {
387
+ return 0 ;
388
+ }
389
+ /* break missing intentionally */
390
+ case ZEND_FE_FREE :
391
+ return !is_var_dead (ctx , ssa_op -> op1_use );
392
+ default :
393
+ return 0 ;
394
+ }
395
+ }
396
+
376
397
/* Returns whether the instruction has been DCEd */
377
398
static zend_bool dce_instr (context * ctx , zend_op * opline , zend_ssa_op * ssa_op ) {
378
399
zend_ssa * ssa = ctx -> ssa ;
@@ -384,9 +405,7 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
384
405
}
385
406
386
407
/* 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 ))
389
- && !is_var_dead (ctx , ssa_op -> op1_use )) {
408
+ if (is_free_of_live_var (ctx , opline , ssa_op )) {
390
409
return 0 ;
391
410
}
392
411
0 commit comments