]> granicus.if.org Git - php/commitdiff
Move pi placement into separate function
authorNikita Popov <nikic@php.net>
Tue, 2 Feb 2016 16:09:26 +0000 (17:09 +0100)
committerNikita Popov <nikic@php.net>
Tue, 2 Feb 2016 16:39:59 +0000 (17:39 +0100)
Non-functional change, just moving code. This makes it easier to
change the order of operations.

ext/opcache/Optimizer/zend_ssa.c

index e80be77d2f068fdf237f239587fe045cf665377a..8ed6f4b3eb996d29bbc119263809c24055d9baff 100644 (file)
@@ -174,6 +174,278 @@ static inline zend_bool sub_will_overflow(zend_long a, zend_long b) {
                || (b < 0 && a > ZEND_LONG_MAX + b);
 }
 
+/* e-SSA construction: Pi placement (Pi is actually a Phi with single
+ * source and constraint).
+ * Order of Phis is importent, Pis must be placed before Phis
+ */
+static void place_essa_pis(
+               zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa,
+               zend_dfg *dfg) {
+       zend_basic_block *blocks = ssa->cfg.blocks;
+       int j, blocks_count = ssa->cfg.blocks_count;
+       for (j = 0; j < blocks_count; j++) {
+               zend_ssa_phi *pi;
+               zend_op *opline = op_array->opcodes + ssa->cfg.blocks[j].end;
+               int bt; /* successor block number if a condition is true */
+               int bf; /* successor block number if a condition is false */
+
+               if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
+                       continue;
+               }
+               /* the last instruction of basic block is conditional branch,
+                * based on comparison of CV(s)
+                */
+               switch (opline->opcode) {
+                       case ZEND_JMPZ:
+                       case ZEND_JMPZNZ:
+                               bf = ssa->cfg.blocks[j].successors[0];
+                               bt = ssa->cfg.blocks[j].successors[1];
+                               break;
+                       case ZEND_JMPNZ:
+                               bt = ssa->cfg.blocks[j].successors[0];
+                               bf = ssa->cfg.blocks[j].successors[1];
+                               break;
+                       default:
+                               continue;
+               }
+               if (opline->op1_type == IS_TMP_VAR &&
+                   ((opline-1)->opcode == ZEND_IS_EQUAL ||
+                    (opline-1)->opcode == ZEND_IS_NOT_EQUAL ||
+                    (opline-1)->opcode == ZEND_IS_SMALLER ||
+                    (opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) &&
+                   opline->op1.var == (opline-1)->result.var) {
+                       int  var1 = -1;
+                       int  var2 = -1;
+                       zend_long val1 = 0;
+                       zend_long val2 = 0;
+//                     long val = 0;
+
+                       if ((opline-1)->op1_type == IS_CV) {
+                               var1 = EX_VAR_TO_NUM((opline-1)->op1.var);
+                       } else if ((opline-1)->op1_type == IS_TMP_VAR) {
+                               var1 = find_adjusted_tmp_var(
+                                       op_array, build_flags, opline, (opline-1)->op1.var, &val2);
+                       }
+
+                       if ((opline-1)->op2_type == IS_CV) {
+                               var2 = EX_VAR_TO_NUM((opline-1)->op2.var);
+                       } else if ((opline-1)->op2_type == IS_TMP_VAR) {
+                               var2 = find_adjusted_tmp_var(
+                                       op_array, build_flags, opline, (opline-1)->op2.var, &val1);
+                       }
+
+                       if (var1 >= 0 && var2 >= 0) {
+                               if (!sub_will_overflow(val1, val2) && !sub_will_overflow(val2, val1)) {
+                                       zend_long tmp = val1;
+                                       val1 -= val2;
+                                       val2 -= tmp;
+                               } else {
+                                       var1 = -1;
+                                       var2 = -1;
+                               }
+                       } else if (var1 >= 0 && var2 < 0) {
+                               zend_long add_val2 = 0;
+                               if ((opline-1)->op2_type == IS_CONST &&
+                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_LONG) {
+                                       add_val2 = Z_LVAL_P(CRT_CONSTANT((opline-1)->op2));
+                               } else if ((opline-1)->op2_type == IS_CONST &&
+                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_FALSE) {
+                                       add_val2 = 0;
+                               } else if ((opline-1)->op2_type == IS_CONST &&
+                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_TRUE) {
+                                       add_val2 = 1;
+                               } else {
+                                       var1 = -1;
+                               }
+                               if (!add_will_overflow(val2, add_val2)) {
+                                       val2 += add_val2;
+                               } else {
+                                       var1 = -1;
+                               }
+                       } else if (var1 < 0 && var2 >= 0) {
+                               zend_long add_val1 = 0;
+                               if ((opline-1)->op1_type == IS_CONST &&
+                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_LONG) {
+                                       add_val1 = Z_LVAL_P(CRT_CONSTANT((opline-1)->op1));
+                               } else if ((opline-1)->op1_type == IS_CONST &&
+                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_FALSE) {
+                                       add_val1 = 0;
+                               } else if ((opline-1)->op1_type == IS_CONST &&
+                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_TRUE) {
+                                       add_val1 = 1;
+                               } else {
+                                       var2 = -1;
+                               }
+                               if (!add_will_overflow(val1, add_val1)) {
+                                       val1 += add_val1;
+                               } else {
+                                       var2 = -1;
+                               }
+                       }
+
+                       if (var1 >= 0) {
+                               if ((opline-1)->opcode == ZEND_IS_EQUAL) {
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) {
+                                               pi_range_equals(pi, var2, val2);
+                                       }
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) {
+                                               pi_range_not_equals(pi, var2, val2);
+                                       }
+                               } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) {
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) {
+                                               pi_range_equals(pi, var2, val2);
+                                       }
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) {
+                                               pi_range_not_equals(pi, var2, val2);
+                                       }
+                               } else if ((opline-1)->opcode == ZEND_IS_SMALLER) {
+                                       if (val2 > ZEND_LONG_MIN) {
+                                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) {
+                                                       pi_range_max(pi, var2, val2-1);
+                                               }
+                                       }
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) {
+                                               pi_range_min(pi, var2, val2);
+                                       }
+                               } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) {
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) {
+                                               pi_range_max(pi, var2, val2);
+                                       }
+                                       if (val2 < ZEND_LONG_MAX) {
+                                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) {
+                                                       pi_range_min(pi, var2, val2+1);
+                                               }
+                                       }
+                               }
+                       }
+                       if (var2 >= 0) {
+                               if((opline-1)->opcode == ZEND_IS_EQUAL) {
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) {
+                                               pi_range_equals(pi, var1, val1);
+                                       }
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) {
+                                               pi_range_not_equals(pi, var1, val1);
+                                       }
+                               } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) {
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) {
+                                               pi_range_equals(pi, var1, val1);
+                                       }
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) {
+                                               pi_range_not_equals(pi, var1, val1);
+                                       }
+                               } else if ((opline-1)->opcode == ZEND_IS_SMALLER) {
+                                       if (val1 < ZEND_LONG_MAX) {
+                                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) {
+                                                       pi_range_min(pi, var1, val1+1);
+                                               }
+                                       }
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) {
+                                               pi_range_max(pi, var1, val1);
+                                       }
+                               } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) {
+                                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) {
+                                               pi_range_min(pi, var1, val1);
+                                       }
+                                       if (val1 > ZEND_LONG_MIN) {
+                                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) {
+                                                       pi_range_max(pi, var1, val1-1);
+                                               }
+                                       }
+                               }
+                       }
+               } else if (opline->op1_type == IS_TMP_VAR &&
+                          ((opline-1)->opcode == ZEND_POST_INC ||
+                           (opline-1)->opcode == ZEND_POST_DEC) &&
+                          opline->op1.var == (opline-1)->result.var &&
+                          (opline-1)->op1_type == IS_CV) {
+                       int var = EX_VAR_TO_NUM((opline-1)->op1.var);
+
+                       if ((opline-1)->opcode == ZEND_POST_DEC) {
+                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
+                                       pi_range_equals(pi, -1, -1);
+                               }
+                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
+                                       pi_range_not_equals(pi, -1, -1);
+                               }
+                       } else if ((opline-1)->opcode == ZEND_POST_INC) {
+                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
+                                       pi_range_equals(pi, -1, 1);
+                               }
+                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
+                                       pi_range_not_equals(pi, -1, 1);
+                               }
+                       }
+               } else if (opline->op1_type == IS_VAR &&
+                          ((opline-1)->opcode == ZEND_PRE_INC ||
+                           (opline-1)->opcode == ZEND_PRE_DEC) &&
+                          opline->op1.var == (opline-1)->result.var &&
+                          (opline-1)->op1_type == IS_CV) {
+                       int var = EX_VAR_TO_NUM((opline-1)->op1.var);
+
+                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
+                               pi_range_equals(pi, -1, 0);
+                       }
+                       /* speculative */
+                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
+                               pi_range_not_equals(pi, -1, 0);
+                       }
+               } else if (opline->op1_type == IS_TMP_VAR && (opline-1)->opcode == ZEND_TYPE_CHECK &&
+                                  opline->op1.var == (opline-1)->result.var && (opline-1)->op1_type == IS_CV) {
+                       int var = EX_VAR_TO_NUM((opline-1)->op1.var);
+                       uint32_t type = (opline-1)->extended_value;
+                       if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
+                               pi_type_mask(pi, mask_for_type_check(type));
+                       }
+                       if (type != IS_OBJECT && type != IS_RESOURCE) {
+                               /* is_object() and is_resource() may return false, even though the value is
+                                * an object/resource. */
+                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
+                                       pi_not_type_mask(pi, mask_for_type_check(type));
+                               }
+                       }
+               } else if (opline->op1_type == IS_TMP_VAR &&
+                                  ((opline-1)->opcode == ZEND_IS_IDENTICAL
+                                       || (opline-1)->opcode == ZEND_IS_NOT_IDENTICAL) &&
+                                  opline->op1.var == (opline-1)->result.var) {
+                       int var;
+                       zval *val;
+                       uint32_t type_mask;
+                       if ((opline-1)->op1_type == IS_CV && (opline-1)->op2_type == IS_CONST) {
+                               var = EX_VAR_TO_NUM((opline-1)->op1.var);
+                               val = CRT_CONSTANT((opline-1)->op2);
+                       } else if ((opline-1)->op1_type == IS_CONST && (opline-1)->op2_type == IS_CV) {
+                               var = EX_VAR_TO_NUM((opline-1)->op2.var);
+                               val = CRT_CONSTANT((opline-1)->op1);
+                       } else {
+                               continue;
+                       }
+
+                       /* We're interested in === null/true/false comparisons here, because they eliminate
+                        * a type in the false-branch. Other === VAL comparisons are unlikely to be useful. */
+                       if (Z_TYPE_P(val) != IS_NULL && Z_TYPE_P(val) != IS_TRUE && Z_TYPE_P(val) != IS_FALSE) {
+                               continue;
+                       }
+
+                       type_mask = _const_op_type(val);
+                       if ((opline-1)->opcode == ZEND_IS_IDENTICAL) {
+                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
+                                       pi_type_mask(pi, type_mask);
+                               }
+                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
+                                       pi_not_type_mask(pi, type_mask);
+                               }
+                       } else {
+                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) {
+                                       pi_type_mask(pi, type_mask);
+                               }
+                               if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) {
+                                       pi_not_type_mask(pi, type_mask);
+                               }
+                       }
+               }
+       }
+}
+
 static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, int *var, int n) /* {{{ */
 {
        zend_basic_block *blocks = ssa->cfg.blocks;
@@ -626,271 +898,7 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b
                }
        }
 
-       /* e-SSA construction: Pi placement (Pi is actually a Phi with single
-        * source and constraint).
-        * Order of Phis is importent, Pis must be placed before Phis
-        */
-       for (j = 0; j < blocks_count; j++) {
-               zend_ssa_phi *pi;
-               zend_op *opline = op_array->opcodes + ssa->cfg.blocks[j].end;
-               int bt; /* successor block number if a condition is true */
-               int bf; /* successor block number if a condition is false */
-
-               if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
-                       continue;
-               }
-               /* the last instruction of basic block is conditional branch,
-                * based on comparison of CV(s)
-                */
-               switch (opline->opcode) {
-                       case ZEND_JMPZ:
-                       case ZEND_JMPZNZ:
-                               bf = ssa->cfg.blocks[j].successors[0];
-                               bt = ssa->cfg.blocks[j].successors[1];
-                               break;
-                       case ZEND_JMPNZ:
-                               bt = ssa->cfg.blocks[j].successors[0];
-                               bf = ssa->cfg.blocks[j].successors[1];
-                               break;
-                       default:
-                               continue;
-               }
-               if (opline->op1_type == IS_TMP_VAR &&
-                   ((opline-1)->opcode == ZEND_IS_EQUAL ||
-                    (opline-1)->opcode == ZEND_IS_NOT_EQUAL ||
-                    (opline-1)->opcode == ZEND_IS_SMALLER ||
-                    (opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) &&
-                   opline->op1.var == (opline-1)->result.var) {
-                       int  var1 = -1;
-                       int  var2 = -1;
-                       zend_long val1 = 0;
-                       zend_long val2 = 0;
-//                     long val = 0;
-
-                       if ((opline-1)->op1_type == IS_CV) {
-                               var1 = EX_VAR_TO_NUM((opline-1)->op1.var);
-                       } else if ((opline-1)->op1_type == IS_TMP_VAR) {
-                               var1 = find_adjusted_tmp_var(
-                                       op_array, build_flags, opline, (opline-1)->op1.var, &val2);
-                       }
-
-                       if ((opline-1)->op2_type == IS_CV) {
-                               var2 = EX_VAR_TO_NUM((opline-1)->op2.var);
-                       } else if ((opline-1)->op2_type == IS_TMP_VAR) {
-                               var2 = find_adjusted_tmp_var(
-                                       op_array, build_flags, opline, (opline-1)->op2.var, &val1);
-                       }
-
-                       if (var1 >= 0 && var2 >= 0) {
-                               if (!sub_will_overflow(val1, val2) && !sub_will_overflow(val2, val1)) {
-                                       zend_long tmp = val1;
-                                       val1 -= val2;
-                                       val2 -= tmp;
-                               } else {
-                                       var1 = -1;
-                                       var2 = -1;
-                               }
-                       } else if (var1 >= 0 && var2 < 0) {
-                               zend_long add_val2 = 0;
-                               if ((opline-1)->op2_type == IS_CONST &&
-                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_LONG) {
-                                       add_val2 = Z_LVAL_P(CRT_CONSTANT((opline-1)->op2));
-                               } else if ((opline-1)->op2_type == IS_CONST &&
-                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_FALSE) {
-                                       add_val2 = 0;
-                               } else if ((opline-1)->op2_type == IS_CONST &&
-                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_TRUE) {
-                                       add_val2 = 1;
-                               } else {
-                                       var1 = -1;
-                               }
-                               if (!add_will_overflow(val2, add_val2)) {
-                                       val2 += add_val2;
-                               } else {
-                                       var1 = -1;
-                               }
-                       } else if (var1 < 0 && var2 >= 0) {
-                               zend_long add_val1 = 0;
-                               if ((opline-1)->op1_type == IS_CONST &&
-                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_LONG) {
-                                       add_val1 = Z_LVAL_P(CRT_CONSTANT((opline-1)->op1));
-                               } else if ((opline-1)->op1_type == IS_CONST &&
-                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_FALSE) {
-                                       add_val1 = 0;
-                               } else if ((opline-1)->op1_type == IS_CONST &&
-                                   Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_TRUE) {
-                                       add_val1 = 1;
-                               } else {
-                                       var2 = -1;
-                               }
-                               if (!add_will_overflow(val1, add_val1)) {
-                                       val1 += add_val1;
-                               } else {
-                                       var2 = -1;
-                               }
-                       }
-
-                       if (var1 >= 0) {
-                               if ((opline-1)->opcode == ZEND_IS_EQUAL) {
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var1))) {
-                                               pi_range_equals(pi, var2, val2);
-                                       }
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var1))) {
-                                               pi_range_not_equals(pi, var2, val2);
-                                       }
-                               } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) {
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var1))) {
-                                               pi_range_equals(pi, var2, val2);
-                                       }
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var1))) {
-                                               pi_range_not_equals(pi, var2, val2);
-                                       }
-                               } else if ((opline-1)->opcode == ZEND_IS_SMALLER) {
-                                       if (val2 > ZEND_LONG_MIN) {
-                                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var1))) {
-                                                       pi_range_max(pi, var2, val2-1);
-                                               }
-                                       }
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var1))) {
-                                               pi_range_min(pi, var2, val2);
-                                       }
-                               } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) {
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var1))) {
-                                               pi_range_max(pi, var2, val2);
-                                       }
-                                       if (val2 < ZEND_LONG_MAX) {
-                                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var1))) {
-                                                       pi_range_min(pi, var2, val2+1);
-                                               }
-                                       }
-                               }
-                       }
-                       if (var2 >= 0) {
-                               if((opline-1)->opcode == ZEND_IS_EQUAL) {
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var2))) {
-                                               pi_range_equals(pi, var1, val1);
-                                       }
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var2))) {
-                                               pi_range_not_equals(pi, var1, val1);
-                                       }
-                               } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) {
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var2))) {
-                                               pi_range_equals(pi, var1, val1);
-                                       }
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var2))) {
-                                               pi_range_not_equals(pi, var1, val1);
-                                       }
-                               } else if ((opline-1)->opcode == ZEND_IS_SMALLER) {
-                                       if (val1 < ZEND_LONG_MAX) {
-                                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var2))) {
-                                                       pi_range_min(pi, var1, val1+1);
-                                               }
-                                       }
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var2))) {
-                                               pi_range_max(pi, var1, val1);
-                                       }
-                               } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) {
-                                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var2))) {
-                                               pi_range_min(pi, var1, val1);
-                                       }
-                                       if (val1 > ZEND_LONG_MIN) {
-                                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var2))) {
-                                                       pi_range_max(pi, var1, val1-1);
-                                               }
-                                       }
-                               }
-                       }
-               } else if (opline->op1_type == IS_TMP_VAR &&
-                          ((opline-1)->opcode == ZEND_POST_INC ||
-                           (opline-1)->opcode == ZEND_POST_DEC) &&
-                          opline->op1.var == (opline-1)->result.var &&
-                          (opline-1)->op1_type == IS_CV) {
-                       int var = EX_VAR_TO_NUM((opline-1)->op1.var);
-
-                       if ((opline-1)->opcode == ZEND_POST_DEC) {
-                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var))) {
-                                       pi_range_equals(pi, -1, -1);
-                               }
-                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
-                                       pi_range_not_equals(pi, -1, -1);
-                               }
-                       } else if ((opline-1)->opcode == ZEND_POST_INC) {
-                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var))) {
-                                       pi_range_equals(pi, -1, 1);
-                               }
-                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
-                                       pi_range_not_equals(pi, -1, 1);
-                               }
-                       }
-               } else if (opline->op1_type == IS_VAR &&
-                          ((opline-1)->opcode == ZEND_PRE_INC ||
-                           (opline-1)->opcode == ZEND_PRE_DEC) &&
-                          opline->op1.var == (opline-1)->result.var &&
-                          (opline-1)->op1_type == IS_CV) {
-                       int var = EX_VAR_TO_NUM((opline-1)->op1.var);
-
-                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var))) {
-                               pi_range_equals(pi, -1, 0);
-                       }
-                       /* speculative */
-                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
-                               pi_range_not_equals(pi, -1, 0);
-                       }
-               } else if (opline->op1_type == IS_TMP_VAR && (opline-1)->opcode == ZEND_TYPE_CHECK &&
-                                  opline->op1.var == (opline-1)->result.var && (opline-1)->op1_type == IS_CV) {
-                       int var = EX_VAR_TO_NUM((opline-1)->op1.var);
-                       uint32_t type = (opline-1)->extended_value;
-                       if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
-                               pi_type_mask(pi, mask_for_type_check(type));
-                       }
-                       if (type != IS_OBJECT && type != IS_RESOURCE) {
-                               /* is_object() and is_resource() may return false, even though the value is
-                                * an object/resource. */
-                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var))) {
-                                       pi_not_type_mask(pi, mask_for_type_check(type));
-                               }
-                       }
-               } else if (opline->op1_type == IS_TMP_VAR &&
-                                  ((opline-1)->opcode == ZEND_IS_IDENTICAL
-                                       || (opline-1)->opcode == ZEND_IS_NOT_IDENTICAL) &&
-                                  opline->op1.var == (opline-1)->result.var) {
-                       int var;
-                       zval *val;
-                       uint32_t type_mask;
-                       if ((opline-1)->op1_type == IS_CV && (opline-1)->op2_type == IS_CONST) {
-                               var = EX_VAR_TO_NUM((opline-1)->op1.var);
-                               val = CRT_CONSTANT((opline-1)->op2);
-                       } else if ((opline-1)->op1_type == IS_CONST && (opline-1)->op2_type == IS_CV) {
-                               var = EX_VAR_TO_NUM((opline-1)->op2.var);
-                               val = CRT_CONSTANT((opline-1)->op1);
-                       } else {
-                               continue;
-                       }
-
-                       /* We're interested in === null/true/false comparisons here, because they eliminate
-                        * a type in the false-branch. Other === VAL comparisons are unlikely to be useful. */
-                       if (Z_TYPE_P(val) != IS_NULL && Z_TYPE_P(val) != IS_TRUE && Z_TYPE_P(val) != IS_FALSE) {
-                               continue;
-                       }
-
-                       type_mask = _const_op_type(val);
-                       if ((opline-1)->opcode == ZEND_IS_IDENTICAL) {
-                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
-                                       pi_type_mask(pi, type_mask);
-                               }
-                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var))) {
-                                       pi_not_type_mask(pi, type_mask);
-                               }
-                       } else {
-                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var))) {
-                                       pi_type_mask(pi, type_mask);
-                               }
-                               if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
-                                       pi_not_type_mask(pi, type_mask);
-                               }
-                       }
-               }
-       }
+       place_essa_pis(arena, op_array, build_flags, ssa, &dfg);
 
        /* SSA construction, Step ?: Phi after Pi placement based on Dominance Frontiers */
        for (j = 0; j < blocks_count; j++) {