com php-src: Support more than two successors in opcache CFG: ext/opcache/Optimizer/block_pass.c ext/opcache/Optimizer/ zend_cfg.c ext/opcache/Optimizer/zend_cfg.h ext/opc ache/Optimizer/zend_dfg.c ext/opcache/Optimizer/zend_ss a.c

[email protected] (Nikita Popov)
Newsgroups php.cvs
Message-ID <[email protected]>
Commit:    d1a012b60270b751449de79235028295696145b2
Author:    Nikita Popov <[email protected]>         Fri, 17 Mar 2017 21:37:57 +0100
Parents:   eeb6cdf810b5781a29c9cd70f31979aac062ef1c
Branches:  master

Link:       http://git.php.net/?p=php-src.git;a=commitdiff;h=d1a012b60270b751449de79235028295696145b2

Log:
Support more than two successors in opcache CFG

Changed paths:
  M  ext/opcache/Optimizer/block_pass.c
  M  ext/opcache/Optimizer/zend_cfg.c
  M  ext/opcache/Optimizer/zend_cfg.h
  M  ext/opcache/Optimizer/zend_dfg.c
  M  ext/opcache/Optimizer/zend_ssa.c
diff_d1a012b60270b751449de79235028295696145b2.txt (text/plain, 21 KB)
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index 767fb67..7436c55 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -1079,7 +1079,7 @@ static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_arr
 						last_op->op1.constant = zend_optimizer_add_literal(op_array, &zv);
 					}
 					DEL_SOURCE(block, block->successors[0]);
-					block->successors[0] = -1;
+					block->successors_count = 0;
 #if 0
 				/* Temporarily disabled - see bug #0025274 */
 				} else if (0&& block->op1_to != block &&
@@ -1152,13 +1152,13 @@ static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_arr
 					/* JMPNZ(true) -> JMP */
 					last_op->opcode = ZEND_JMP;
 					DEL_SOURCE(block, block->successors[1]);
-					block->successors[1] = -1;
+					block->successors_count = 1;
 				} else {
 					/* JMPNZ(false) -> NOP */
 					MAKE_NOP(last_op);
 					DEL_SOURCE(block, block->successors[0]);
+					block->successors_count = 1;
 					block->successors[0] = block->successors[1];
-					block->successors[1] = -1;
 				}
 				break;
 			}
@@ -1175,7 +1175,7 @@ static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_arr
 				} else {
 					MAKE_NOP(last_op);
 				}
-				block->successors[1] = -1;
+				block->successors_count = 1;
 				break;
 			}
 
@@ -1304,8 +1304,8 @@ next_target:
 					last_op->opcode = ZEND_QM_ASSIGN;
 					SET_UNUSED(last_op->op2);
 					DEL_SOURCE(block, block->successors[0]);
+					block->successors_count = 1;
 					block->successors[0] = block->successors[1];
-					block->successors[1] = -1;
 				}
 				break;
 			}
@@ -1404,7 +1404,7 @@ next_target_ex:
 					SET_UNUSED(last_op->op1);
 					SET_UNUSED(last_op->op2);
 					DEL_SOURCE(block, block->successors[1]);
-					block->successors[1] = -1;
+					block->successors_count = 1;
 				} else {
 					/* JMPZNZ(true,L1,L2) -> JMP(L2) */
 					literal_dtor(&ZEND_OP1_LITERAL(last_op));
@@ -1412,8 +1412,8 @@ next_target_ex:
 					SET_UNUSED(last_op->op1);
 					SET_UNUSED(last_op->op2);
 					DEL_SOURCE(block, block->successors[0]);
+					block->successors_count = 1;
 					block->successors[0] = block->successors[1];
-					block->successors[1] = -1;
 				}
 			} else if (block->successors[0] == block->successors[1]) {
 				/* both goto the same one - it's JMP */
@@ -1422,7 +1422,7 @@ next_target_ex:
 					last_op->opcode = ZEND_JMP;
 					SET_UNUSED(last_op->op1);
 					SET_UNUSED(last_op->op2);
-					block->successors[1] = -1;
+					block->successors_count = 1;
 				}
 			} else if (block->successors[0] == next) {
 				/* jumping to next on Z - can follow to it and jump only on NZ */
@@ -1606,7 +1606,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
 		    (next_block->flags & ZEND_BB_TARGET)) {
 			/* Skip continuation of "extended" BB */
 			zend_bitset_copy(usage, used_ext, bitset_len);
-		} else if (block->successors[1] != -1) {
+		} else if (block->successors_count > 1) {
 			zend_bitset_union(usage, used_ext, bitset_len);
 		}
 		next_block = block;
@@ -1724,8 +1724,7 @@ static void zend_merge_blocks(zend_op_array *op_array, zend_cfg *cfg)
 		if (b->flags & ZEND_BB_REACHABLE) {
 			if ((b->flags & ZEND_BB_FOLLOW) &&
 			    !(b->flags & (ZEND_BB_TARGET | ZEND_BB_PROTECTED)) &&
-			    prev &&
-			    prev->successors[0] == i && prev->successors[1] == -1)
+			    prev && prev->successors_count == 1 && prev->successors[0] == i)
 			{
 				zend_op *last_op = op_array->opcodes + prev->start + prev->len - 1;
 				if (prev->len != 0 && last_op->opcode == ZEND_JMP) {
@@ -1752,14 +1751,13 @@ static void zend_merge_blocks(zend_op_array *op_array, zend_cfg *cfg)
 				/* re-link */
 				prev->flags |= (b->flags & ZEND_BB_EXIT);
 				prev->len = b->start + b->len - prev->start;
-				prev->successors[0] = b->successors[0];
-				prev->successors[1] = b->successors[1];
+				prev->successors_count = b->successors_count;
+				memcpy(prev->successors, b->successors, b->successors_count * sizeof(int));
 
 				/* unlink & make block empty and unreachable */
 				b->flags = 0;
 				b->len = 0;
-				b->successors[0] = -1;
-				b->successors[1] = -1;
+				b->successors_count = 0;
 			} else {
 				prev = b;
 			}
diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c
index 0f0cabb..c439475 100644
--- a/ext/opcache/Optimizer/zend_cfg.c
+++ b/ext/opcache/Optimizer/zend_cfg.c
@@ -26,65 +26,73 @@
 
 static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_block *b) /* {{{ */
 {
-	zend_uchar opcode;
-	zend_basic_block *b0;
-	int successor_0, successor_1;
 	zend_basic_block *blocks = cfg->blocks;
 
 	while (1) {
+		int i;
+
 		b->flags |= ZEND_BB_REACHABLE;
-		successor_0 = b->successors[0];
-		if (successor_0 >= 0) {
-			successor_1 = b->successors[1];
-			if (successor_1 >= 0) {
-				b0 = blocks + successor_0;
-				b0->flags |= ZEND_BB_TARGET;
-				if (!(b0->flags & ZEND_BB_REACHABLE)) {
-					zend_mark_reachable(opcodes, cfg, b0);
-				}
+		if (b->successors_count == 0) {
+			b->flags |= ZEND_BB_EXIT;
+			return;
+		}
 
-				ZEND_ASSERT(b->len != 0);
-				opcode = opcodes[b->start + b->len - 1].opcode;
-				b = blocks + successor_1;
-				if (opcode == ZEND_JMPZNZ) {
-					b->flags |= ZEND_BB_TARGET;
-				} else {
-					b->flags |= ZEND_BB_FOLLOW;
-				}
-			} else if (b->len != 0) {
-				opcode = opcodes[b->start + b->len - 1].opcode;
-				b = blocks + successor_0;
-				if (opcode == ZEND_JMP) {
-					b->flags |= ZEND_BB_TARGET;
-				} else {
-					b->flags |= ZEND_BB_FOLLOW;
-
-					if (cfg->split_at_calls) {
-						if (opcode == ZEND_INCLUDE_OR_EVAL ||
-						    opcode == ZEND_GENERATOR_CREATE ||
-						    opcode == ZEND_YIELD ||
-						    opcode == ZEND_YIELD_FROM ||
-						    opcode == ZEND_DO_FCALL ||
-						    opcode == ZEND_DO_UCALL ||
-						    opcode == ZEND_DO_FCALL_BY_NAME) {
-							b->flags |= ZEND_BB_ENTRY;
+		for (i = 0; i < b->successors_count; i++) {
+			zend_basic_block *succ = blocks + b->successors[i];
+
+			if (b->len != 0) {
+				zend_uchar opcode = opcodes[b->start + b->len - 1].opcode;
+				if (b->successors_count == 1) {
+					if (opcode == ZEND_JMP) {
+						succ->flags |= ZEND_BB_TARGET;
+
+						if (cfg->split_at_calls) {
+							if (opcode == ZEND_INCLUDE_OR_EVAL ||
+								opcode == ZEND_GENERATOR_CREATE ||
+								opcode == ZEND_YIELD ||
+								opcode == ZEND_YIELD_FROM ||
+								opcode == ZEND_DO_FCALL ||
+								opcode == ZEND_DO_UCALL ||
+								opcode == ZEND_DO_FCALL_BY_NAME) {
+								b->flags |= ZEND_BB_ENTRY;
+							}
 						}
-					}
-					if (cfg->split_at_recv) {
-						if (opcode == ZEND_RECV ||
-						    opcode == ZEND_RECV_INIT) {
-							b->flags |= ZEND_BB_RECV_ENTRY;
+						if (cfg->split_at_recv) {
+							if (opcode == ZEND_RECV ||
+								opcode == ZEND_RECV_INIT) {
+								b->flags |= ZEND_BB_RECV_ENTRY;
+							}
 						}
+					} else {
+						succ->flags |= ZEND_BB_FOLLOW;
+					}
+				} else if (b->successors_count == 2) {
+					if (i == 0 || opcode == ZEND_JMPZNZ) {
+						succ->flags |= ZEND_BB_TARGET;
+					} else {
+						succ->flags |= ZEND_BB_FOLLOW;
 					}
+				} else {
+					ZEND_ASSERT(0);
 				}
 			} else {
-				b = blocks + successor_0;
-				b->flags |= ZEND_BB_FOLLOW;
+				succ->flags |= ZEND_BB_FOLLOW;
+			}
+
+			if (i == b->successors_count - 1) {
+				/* Tail call optimization */
+				if (succ->flags & ZEND_BB_REACHABLE) {
+					return;
+				}
+
+				b = succ;
+				break;
+			} else {
+				/* Recusively check reachability */
+				if (!(succ->flags & ZEND_BB_REACHABLE)) {
+					zend_mark_reachable(opcodes, cfg, succ);
+				}
 			}
-			if (b->flags & ZEND_BB_REACHABLE) return;
-		} else {
-			b->flags |= ZEND_BB_EXIT;
-			return;
 		}
 	}
 }
@@ -251,15 +259,10 @@ void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *c
 }
 /* }}} */
 
-static void record_successor(zend_basic_block *blocks, int pred, int n, int succ)
-{
-	blocks[pred].successors[n] = succ;
-}
-
 static void initialize_block(zend_basic_block *block) {
 	block->flags = 0;
-	block->successors[0] = -1;
-	block->successors[1] = -1;
+	block->successors = block->successors_storage;
+	block->successors_count = 0;
 	block->predecessors_count = 0;
 	block->predecessor_offset = -1;
 	block->idom = -1;
@@ -484,13 +487,15 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
 
 	/* Build CFG, Step 3: Calculate successors */
 	for (j = 0; j < blocks_count; j++) {
+		zend_basic_block *block = &blocks[j];
 		zend_op *opline;
-		if (blocks[j].len == 0) {
-			record_successor(blocks, j, 0, j + 1);
+		if (block->len == 0) {
+			block->successors_count = 1;
+			block->successors[0] = j + 1;
 			continue;
 		}
 
-		opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1;
+		opline = op_array->opcodes + block->start + block->len - 1;
 		switch (opline->opcode) {
 			case ZEND_FAST_RET:
 			case ZEND_RETURN:
@@ -500,11 +505,13 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
 			case ZEND_THROW:
 				break;
 			case ZEND_JMP:
-				record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes]);
+				block->successors_count = 1;
+				block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes];
 				break;
 			case ZEND_JMPZNZ:
-				record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]);
-				record_successor(blocks, j, 1, block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
+				block->successors_count = 2;
+				block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes];
+				block->successors[1] = block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
 				break;
 			case ZEND_JMPZ:
 			case ZEND_JMPNZ:
@@ -513,35 +520,42 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
 			case ZEND_JMP_SET:
 			case ZEND_COALESCE:
 			case ZEND_ASSERT_CHECK:
-				record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]);
-				record_successor(blocks, j, 1, j + 1);
+				block->successors_count = 2;
+				block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes];
+				block->successors[1] = j + 1;
 				break;
 			case ZEND_CATCH:
 				if (!opline->result.num) {
-					record_successor(blocks, j, 0, block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
-					record_successor(blocks, j, 1, j + 1);
+					block->successors_count = 2;
+					block->successors[0] = block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
+					block->successors[1] = j + 1;
 				} else {
-					record_successor(blocks, j, 0, j + 1);
+					block->successors_count = 1;
+					block->successors[0] = j + 1;
 				}
 				break;
 			case ZEND_DECLARE_ANON_CLASS:
 			case ZEND_DECLARE_ANON_INHERITED_CLASS:
 			case ZEND_FE_FETCH_R:
 			case ZEND_FE_FETCH_RW:
-				record_successor(blocks, j, 0, block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
-				record_successor(blocks, j, 1, j + 1);
+				block->successors_count = 2;
+				block->successors[0] = block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
+				block->successors[1] = j + 1;
 				break;
 			case ZEND_FE_RESET_R:
 			case ZEND_FE_RESET_RW:
-				record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]);
-				record_successor(blocks, j, 1, j + 1);
+				block->successors_count = 2;
+				block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes];
+				block->successors[1] = j + 1;
 				break;
 			case ZEND_FAST_CALL:
-				record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes]);
-				record_successor(blocks, j, 1, j + 1);
+				block->successors_count = 2;
+				block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes];
+				block->successors[1] = j + 1;
 				break;
 			default:
-				record_successor(blocks, j, 0, j + 1);
+				block->successors_count = 1;
+				block->successors[0] = j + 1;
 				break;
 		}
 	}
@@ -559,7 +573,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
 
 int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /* {{{ */
 {
-	int j, edges;
+	int j, s, edges;
 	zend_basic_block *b;
 	zend_basic_block *blocks = cfg->blocks;
 	zend_basic_block *end = blocks + cfg->blocks_count;
@@ -571,17 +585,12 @@ int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /* {{{ */
 	}
 	for (b = blocks; b < end; b++) {
 		if (!(b->flags & ZEND_BB_REACHABLE)) {
-			b->successors[0] = -1;
-			b->successors[1] = -1;
+			b->successors_count = 0;
 			b->predecessors_count = 0;
 		} else {
-			if (b->successors[0] >= 0) {
+			for (s = 0; s < b->successors_count; s++) {
 				edges++;
-				blocks[b->successors[0]].predecessors_count++;
-				if (b->successors[1] >= 0 && b->successors[1] != b->successors[0]) {
-					edges++;
-					blocks[b->successors[1]].predecessors_count++;
-				}
+				blocks[b->successors[s]].predecessors_count++;
 			}
 		}
 	}
@@ -599,16 +608,10 @@ int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /* {{{ */
 
 	for (j = 0; j < cfg->blocks_count; j++) {
 		if (blocks[j].flags & ZEND_BB_REACHABLE) {
-			if (blocks[j].successors[0] >= 0) {
-				zend_basic_block *b = blocks + blocks[j].successors[0];
+			for (s = 0; s < blocks[j].successors_count; s++) {
+				zend_basic_block *b = blocks + blocks[j].successors[s];
 				predecessors[b->predecessor_offset + b->predecessors_count] = j;
 				b->predecessors_count++;
-				if (blocks[j].successors[1] >= 0
-						&& blocks[j].successors[1] != blocks[j].successors[0]) {
-					zend_basic_block *b = blocks + blocks[j].successors[1];
-					predecessors[b->predecessor_offset + b->predecessors_count] = j;
-					b->predecessors_count++;
-				}
 			}
 		}
 	}
@@ -621,17 +624,15 @@ int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /* {{{ */
 static void compute_postnum_recursive(
 		int *postnum, int *cur, const zend_cfg *cfg, int block_num) /* {{{ */
 {
+	int s;
 	zend_basic_block *block = &cfg->blocks[block_num];
 	if (postnum[block_num] != -1) {
 		return;
 	}
 
 	postnum[block_num] = -2; /* Marker for "currently visiting" */
-	if (block->successors[0] >= 0) {
-		compute_postnum_recursive(postnum, cur, cfg, block->successors[0]);
-		if (block->successors[1] >= 0) {
-			compute_postnum_recursive(postnum, cur, cfg, block->successors[1]);
-		}
+	for (s = 0; s < block->successors_count; s++) {
+		compute_postnum_recursive(postnum, cur, cfg, block->successors[s]);
 	}
 	postnum[block_num] = (*cur)++;
 }
@@ -788,11 +789,9 @@ int zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg, uint32
 			}
 		}
 		/* Visit join edges.  */
-		for (j = 0; j < 2; j++) {
+		for (j = 0; j < blocks[i].successors_count; j++) {
 			int succ = blocks[i].successors[j];
-			if (succ < 0) {
-				continue;
-			} else if (blocks[succ].idom == i) {
+			if (blocks[succ].idom == i) {
 				continue;
 			} else if (zend_worklist_push(&work, succ)) {
 				goto next;
diff --git a/ext/opcache/Optimizer/zend_cfg.h b/ext/opcache/Optimizer/zend_cfg.h
index d24bbd9..315b93e 100644
--- a/ext/opcache/Optimizer/zend_cfg.h
+++ b/ext/opcache/Optimizer/zend_cfg.h
@@ -42,10 +42,11 @@
 #define ZEND_BB_PROTECTED        (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY|ZEND_BB_TRY|ZEND_BB_CATCH|ZEND_BB_FINALLY|ZEND_BB_FINALLY_END|ZEND_BB_GEN_VAR|ZEND_BB_KILL_VAR)
 
 typedef struct _zend_basic_block {
+	int              *successors;         /* successor block indices     */
 	uint32_t          flags;
 	uint32_t          start;              /* first opcode number         */
 	uint32_t          len;                /* number of opcodes           */
-	int               successors[2];      /* up to 2 successor blocks    */
+	int               successors_count;   /* number of successors        */
 	int               predecessors_count; /* number of predecessors      */
 	int               predecessor_offset; /* offset of 1-st predecessor  */
 	int               idom;               /* immediate dominator block   */
@@ -53,6 +54,7 @@ typedef struct _zend_basic_block {
 	int               level;              /* steps away from the entry in the dom. tree */
 	int               children;           /* list of dominated blocks    */
 	int               next_child;         /* next dominated block        */
+	int               successors_storage[2]; /* up to 2 successor blocks */
 } zend_basic_block;
 
 /*
diff --git a/ext/opcache/Optimizer/zend_dfg.c b/ext/opcache/Optimizer/zend_dfg.c
index 6e6997b..e51c3a5 100644
--- a/ext/opcache/Optimizer/zend_dfg.c
+++ b/ext/opcache/Optimizer/zend_dfg.c
@@ -220,10 +220,10 @@ op2_use:
 			if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
 				continue;
 			}
-			if (blocks[j].successors[0] >= 0) {
+			if (blocks[j].successors_count != 0) {
 				zend_bitset_copy(DFG_BITSET(out, set_size, j), DFG_BITSET(in, set_size, blocks[j].successors[0]), set_size);
-				if (blocks[j].successors[1] >= 0) {
-					zend_bitset_union(DFG_BITSET(out, set_size, j), DFG_BITSET(in, set_size, blocks[j].successors[1]), set_size);
+				for (k = 1; k < blocks[j].successors_count; k++) {
+					zend_bitset_union(DFG_BITSET(out, set_size, j), DFG_BITSET(in, set_size, blocks[j].successors[k]), set_size);
 				}
 			} else {
 				zend_bitset_clear(DFG_BITSET(out, set_size, j), set_size);
diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c
index 4c3361b..54bf985 100644
--- a/ext/opcache/Optimizer/zend_ssa.c
+++ b/ext/opcache/Optimizer/zend_ssa.c
@@ -61,6 +61,7 @@ static zend_bool needs_pi(const zend_op_array *op_array, zend_dfg *dfg, zend_ssa
 	/* Check that the other successor of the from block does not dominate all other predecessors.
 	 * If it does, we'd probably end up annihilating a positive+negative pi assertion. */
 	from_block = &ssa->cfg.blocks[from];
+	ZEND_ASSERT(from_block->successors_count == 2);
 	other_successor = from_block->successors[0] == to
 		? from_block->successors[1] : from_block->successors[0];
 	return !dominates_other_predecessors(&ssa->cfg, to_block, other_successor, from);
@@ -779,53 +780,51 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags,
 		}
 	}
 
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < blocks[n].successors_count; i++) {
 		int succ = blocks[n].successors[i];
-		if (succ >= 0) {
-			zend_ssa_phi *p;
-			for (p = ssa_blocks[succ].phis; p; p = p->next) {
-				if (p->pi == n) {
-					/* e-SSA Pi */
-					if (p->has_range_constraint) {
-						if (p->constraint.range.min_var >= 0) {
-							p->constraint.range.min_ssa_var = var[p->constraint.range.min_var];
-						}
-						if (p->constraint.range.max_var >= 0) {
-							p->constraint.range.max_ssa_var = var[p->constraint.range.max_var];
-						}
+		zend_ssa_phi *p;
+		for (p = ssa_blocks[succ].phis; p; p = p->next) {
+			if (p->pi == n) {
+				/* e-SSA Pi */
+				if (p->has_range_constraint) {
+					if (p->constraint.range.min_var >= 0) {
+						p->constraint.range.min_ssa_var = var[p->constraint.range.min_var];
 					}
-					for (j = 0; j < blocks[succ].predecessors_count; j++) {
-						p->sources[j] = var[p->var];
+					if (p->constraint.range.max_var >= 0) {
+						p->constraint.range.max_ssa_var = var[p->constraint.range.max_var];
 					}
-					if (p->ssa_var < 0) {
-						p->ssa_var = ssa_vars_count;
-						ssa_vars_count++;
-					}
-				} else if (p->pi < 0) {
-					/* Normal Phi */
-					for (j = 0; j < blocks[succ].predecessors_count; j++)
-						if (ssa->cfg.predecessors[blocks[succ].predecessor_offset + j] == n) {
-							break;
-						}
-					ZEND_ASSERT(j < blocks[succ].predecessors_count);
+				}
+				for (j = 0; j < blocks[succ].predecessors_count; j++) {
 					p->sources[j] = var[p->var];
 				}
+				if (p->ssa_var < 0) {
+					p->ssa_var = ssa_vars_count;
+					ssa_vars_count++;
+				}
+			} else if (p->pi < 0) {
+				/* Normal Phi */
+				for (j = 0; j < blocks[succ].predecessors_count; j++)
+					if (ssa->cfg.predecessors[blocks[succ].predecessor_offset + j] == n) {
+						break;
+					}
+				ZEND_ASSERT(j < blocks[succ].predecessors_count);
+				p->sources[j] = var[p->var];
 			}
-			for (p = ssa_blocks[succ].phis; p && (p->pi >= 0); p = p->next) {
-				if (p->pi == n) {
-					zend_ssa_phi *q = p->next;
-					while (q) {
-						if (q->pi < 0 && q->var == p->var) {
-							for (j = 0; j < blocks[succ].predecessors_count; j++) {
-								if (ssa->cfg.predecessors[blocks[succ].predecessor_offset + j] == n) {
-									break;
-								}
+		}
+		for (p = ssa_blocks[succ].phis; p && (p->pi >= 0); p = p->next) {
+			if (p->pi == n) {
+				zend_ssa_phi *q = p->next;
+				while (q) {
+					if (q->pi < 0 && q->var == p->var) {
+						for (j = 0; j < blocks[succ].predecessors_count; j++) {
+							if (ssa->cfg.predecessors[blocks[succ].predecessor_offset + j] == n) {
+								break;
 							}
-							ZEND_ASSERT(j < blocks[succ].predecessors_count);
-							q->sources[j] = p->ssa_var;
 						}
-						q = q->next;
+						ZEND_ASSERT(j < blocks[succ].predecessors_count);
+						q->sources[j] = p->ssa_var;
 					}
+					q = q->next;
 				}
 			}
 		}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.