Skip to content

Commit df6ffa8

Browse files
committed
Improve Range Inference
Support for simple negative range constraints on induction variables
1 parent 3724b49 commit df6ffa8

File tree

1 file changed

+44
-2
lines changed

1 file changed

+44
-2
lines changed

Zend/Optimizer/zend_inference.c

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -875,8 +875,50 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int
875875
if (p->pi >= 0 && p->has_range_constraint) {
876876
zend_ssa_range_constraint *constraint = &p->constraint.range;
877877
if (constraint->negative) {
878-
if (ssa->var_info[p->sources[0]].has_range) {
879-
*tmp = ssa->var_info[p->sources[0]].range;
878+
int src1 = p->sources[0];
879+
880+
if (ssa->var_info[src1].has_range) {
881+
*tmp = ssa->var_info[src1].range;
882+
if (constraint->range.min == constraint->range.max
883+
&& !constraint->range.underflow
884+
&& !constraint->range.overflow
885+
&& p->constraint.range.min_ssa_var < 0
886+
&& p->constraint.range.max_ssa_var < 0
887+
&& ssa->vars[src1].definition >= 0) {
888+
/* Check for constrained induction variable */
889+
line = ssa->vars[src1].definition;
890+
opline = op_array->opcodes + line;
891+
switch (opline->opcode) {
892+
case ZEND_PRE_DEC:
893+
case ZEND_POST_DEC:
894+
if (!tmp->underflow) {
895+
zend_ssa_phi *p = ssa->vars[ssa->ops[line].op1_use].definition_phi;
896+
897+
if (p && p->pi < 0
898+
&& ssa->cfg.blocks[p->block].predecessors_count == 2
899+
&& p->sources[1] == var
900+
&& ssa->var_info[p->sources[0]].has_range
901+
&& ssa->var_info[p->sources[0]].range.min > constraint->range.max) {
902+
tmp->min = constraint->range.max + 1;
903+
}
904+
}
905+
break;
906+
case ZEND_PRE_INC:
907+
case ZEND_POST_INC:
908+
if (!tmp->overflow) {
909+
zend_ssa_phi *p = ssa->vars[ssa->ops[line].op1_use].definition_phi;
910+
911+
if (p && p->pi < 0
912+
&& ssa->cfg.blocks[p->block].predecessors_count == 2
913+
&& p->sources[1] == var
914+
&& ssa->var_info[p->sources[0]].has_range
915+
&& ssa->var_info[p->sources[0]].range.max < constraint->range.min) {
916+
tmp->max = constraint->range.min - 1;
917+
}
918+
}
919+
break;
920+
}
921+
}
880922
} else if (narrowing) {
881923
tmp->underflow = 1;
882924
tmp->min = ZEND_LONG_MIN;

0 commit comments

Comments
 (0)