com php-src: Remove dead JMP/JMPZ/JMPNZ/JMPZNZ (DCE pass can't remove them): ext/opcache/Optimizer/dfa_pass.c
| From: | Dmitry Stogov | Date: | Tue, 18 Jul 2017 17:43:06 +0000 |
| Subject: | com php-src: Remove dead JMP/JMPZ/JMPNZ/JMPZNZ (DCE pass can't remove them): ext/opcache/Optimizer/dfa_pass.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-98615@lists.php.net to get a copy of this message | ||
Commit: 0903f6bffb32f796711d8dd5b02c5c98e16ec7b5
Author: Dmitry Stogov <dmitry@zend.com> Tue, 18 Jul 2017 20:43:06 +0300
Parents: 582882ae18d0e2ce04992aa9e5979574562fb5bf
Branches: PHP-7.2 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=0903f6bffb32f796711d8dd5b02c5c98e16ec7b5
Log:
Remove dead JMP/JMPZ/JMPNZ/JMPZNZ (DCE pass can't remove them)
Changed paths:
M ext/opcache/Optimizer/dfa_pass.c
Diff:
diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c
index 642e0d3..5325977 100644
--- a/ext/opcache/Optimizer/dfa_pass.c
+++ b/ext/opcache/Optimizer/dfa_pass..c
@@ -450,6 +450,84 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa)
return removed_ops;
}
+static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
+{
+ int removed_ops = 0;
+ int block_num = 0;
+
+ while (block_num < ssa->cfg.blocks_count
+ && !(ssa->cfg.blocks[block_num].flags & ZEND_BB_REACHABLE)) {
+ block_num++;
+ }
+ while (block_num < ssa->cfg.blocks_count) {
+ int next_block_num = block_num + 1;
+ zend_basic_block *block = &ssa->cfg.blocks[block_num];
+ uint32_t op_num;
+ zend_op *opline;
+ zend_ssa_op *op;
+
+ while (next_block_num < ssa->cfg.blocks_count
+ && !(ssa->cfg.blocks[next_block_num].flags & ZEND_BB_REACHABLE)) {
+ next_block_num++;
+ }
+
+ if (block->len) {
+ if (block->successors_count == 2) {
+ if (block->successors[0] == block->successors[1]) {
+ op_num = block->start + block->len - 1;
+ opline = op_array->opcodes + op_num;
+ switch (opline->opcode) {
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZNZ:
+ op = ssa->ops + op_num;
+ if (block->successors[0] == next_block_num) {
+ if (opline->op1_type & (IS_CV|IS_CONST)) {
+ zend_ssa_remove_instr(ssa, opline, op);
+ if (op->op1_use >= 0) {
+ zend_ssa_unlink_use_chain(ssa, op_num, op->op1_use);
+ op->op1_use = -1;
+ op->op1_use_chain = -1;
+ }
+ MAKE_NOP(opline);
+ removed_ops++;
+ } else {
+ opline->opcode = ZEND_FREE;
+ opline->op2.num = 0;
+ }
+ } else {
+ if (opline->op1_type & (IS_CV|IS_CONST)) {
+ if (op->op1_use >= 0) {
+ zend_ssa_unlink_use_chain(ssa, op_num, op->op1_use);
+ op->op1_use = -1;
+ op->op1_use_chain = -1;
+ }
+ opline->opcode = ZEND_JMP;
+ opline->op1_type = IS_UNUSED;
+ opline->op1.num = opline->op2.num;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ } else if (block->successors_count == 1 && block->successors[0] == next_block_num)
{
+ op_num = block->start + block->len - 1;
+ opline = op_array->opcodes + op_num;
+ if (opline->opcode == ZEND_JMP) {
+ MAKE_NOP(opline);
+ removed_ops++;
+ }
+ }
+ }
+
+ block_num = next_block_num;
+ }
+
+ return removed_ops;
+}
+
void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa,
zend_call_info **call_map)
{
if (ctx->debug_level & ZEND_DUMP_BEFORE_DFA_PASS) {
@@ -467,6 +545,11 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx
*ctx
if (sccp_optimize_op_array(ctx, op_array, ssa, call_map)) {
remove_nops = 1;
}
+
+ if (zend_dfa_optimize_jmps(op_array, ssa)) {
+ remove_nops = 1;
+ }
+
#if ZEND_DEBUG_DFA
ssa_verify_integrity(op_array, ssa, "after sccp");
#endif