summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2019-10-04 12:51:01 +0300
committerDmitry Stogov <dmitry@zend.com>2019-10-04 12:52:46 +0300
commitdc3c8c75dad511f08ac5e1dd2e854003e175894f (patch)
treed2ab2efab19ce2dbeade89fe875043455422b7be
parentd44cf9b539c5dfbd3ff0295bac25165e79214e09 (diff)
downloadphp-git-dc3c8c75dad511f08ac5e1dd2e854003e175894f.tar.gz
Prefer optimization without JMPZNZ instruction
-rw-r--r--ext/opcache/Optimizer/block_pass.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index d0671d1a5b..6ca3d02468 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -1343,9 +1343,38 @@ next_target:
break;
}
}
- /* JMPZ(X,L1), JMP(L2) -> JMPZNZ(X,L1,L2) */
+
if (target->opcode == ZEND_JMP &&
!(target_block->flags & ZEND_BB_PROTECTED)) {
+
+ if (!(target_block->flags & ZEND_BB_TARGET)) {
+ int next = (target_block - blocks) + 1;
+
+ while (next < cfg->blocks_count && !(blocks[next].flags & ZEND_BB_REACHABLE)) {
+ /* find used one */
+ next++;
+ }
+ if (next < cfg->blocks_count &&
+ block->successors[0] == next) {
+ /* JMPZ(X,L1) JMP(L2) L1: -> JMPNZ(X,L2) NOP*/
+
+ last_op->opcode = INV_COND(last_op->opcode);
+
+ DEL_SOURCE(block, block->successors[1]);
+ block->successors[0] = target_block->successors[0];
+ block->successors[1] = next;
+ ADD_SOURCE(block, block->successors[1]);
+
+ target_block->flags &= ~ZEND_BB_REACHABLE;
+ MAKE_NOP(target);
+
+ blocks[next].flags |= ZEND_BB_FOLLOW;
+
+ break;
+ }
+ }
+
+ /* JMPZ(X,L1), JMP(L2) -> JMPZNZ(X,L1,L2) */
DEL_SOURCE(block, block->successors[1]);
if (last_op->opcode == ZEND_JMPZ) {
block->successors[1] = target_block->successors[0];