mirror of
https://github.com/php/php-src.git
synced 2026-04-28 18:53:33 +02:00
Move pi placement into separate function
Non-functional change, just moving code. This makes it easier to change the order of operations.
This commit is contained in:
+273
-265
@@ -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++) {
|
||||
|
||||
Reference in New Issue
Block a user