From f455894bb6c83f116ea34fe7feefd3ef8f0c10dc Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 6 Oct 2021 09:56:32 +0200 Subject: [PATCH] Don't start new block after loop free This reverts the change from 493c91c7429ee4552d2b80a2648271e2ba97f15c. Starting a new block means that in the common case where the loop var free is not unreachable, we'll always merge back the block. Instead fix the original problem by explicitly removing instructions apart from the loop var free in block pass. --- Zend/Optimizer/block_pass.c | 9 +++++++++ Zend/Optimizer/zend_cfg.c | 3 --- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index 61c8f420aa4..18f5a98cc15 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -1892,6 +1892,15 @@ void zend_optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx) /* Eliminate NOPs */ for (b = blocks; b < end; b++) { + if (b->flags & ZEND_BB_UNREACHABLE_FREE) { + /* In unreachable_free blocks only preserve loop var frees. */ + for (uint32_t i = b->start; i < b->start + b->len; i++) { + zend_op *opline = &op_array->opcodes[i]; + if (!zend_optimizer_is_loop_var_free(opline)) { + MAKE_NOP(opline); + } + } + } if (b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) { strip_nops(op_array, b); } diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index cbdf32c1c4c..4294e44f2e4 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -437,9 +437,6 @@ ZEND_API int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, u case ZEND_FE_FREE: if (zend_optimizer_is_loop_var_free(opline)) { BB_START(i); - if (i + 1 < op_array->last) { - BB_START(i + 1); - } flags |= ZEND_FUNC_FREE_LOOP_VAR; } break;