diff --git a/rpython/jit/metainterp/optimizeopt/intrelational.py b/rpython/jit/metainterp/optimizeopt/intrelational.py index 88fc1b7b7ec..1a24b49cad4 100644 --- a/rpython/jit/metainterp/optimizeopt/intrelational.py +++ b/rpython/jit/metainterp/optimizeopt/intrelational.py @@ -1,12 +1,44 @@ from rpython.jit.metainterp.optimize import InvalidLoop - +from rpython.jit.metainterp.optimizeopt.intutils import IntBound class IntOrderInfo(object): - def __init__(self): + def __init__(self, bounds=None): + if bounds is None: + bounds = IntBound.unbounded() + self.bounds = bounds self.relations = [] + def contains(self, concrete_values): + if isinstance(concrete_values, dict): + return self._contains(concrete_values) + else: + # assume that `default_values` is a single integer + return self.bounds.contains(concrete_values) + + def make_lt(self, other): + self.bounds.make_lt(other.bounds) + self._make_lt(other) + + def known_lt(self, other): + # ask bounds first, as it is cheaper + return self.bounds.known_lt(other.bounds) \ + or self._known_lt(other) + + def abstract_add_const(self, const): + bound_other = IntBound.from_constant(const) + bounds = self.bounds.add_bound(bound_other) + res = IntOrderInfo(bounds) + if self.bounds.add_bound_cannot_overflow(bound_other): + if const > 0: + self.make_lt(res) + elif const < 0: + res.make_lt(self) + return res + + + def _contains(self, concrete_values): # concrete_values: dict[IntOrderInfo, int] for order, value in concrete_values.iteritems(): for relation in order.relations: @@ -16,14 +48,14 @@ def contains(self, concrete_values): return False return True - def make_lt(self, other): + def _make_lt(self, other): if other.known_lt(self): raise InvalidLoop("Invalid relations: self < other < self") if self.known_lt(other): return self.relations.append(Bigger(other)) - def known_lt(self, other): + def _known_lt(self, other): todo = self.relations[:] seen = dict() while todo: diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intrelational.py b/rpython/jit/metainterp/optimizeopt/test/test_intrelational.py index 47c42ada659..d3c0350a719 100644 --- a/rpython/jit/metainterp/optimizeopt/test/test_intrelational.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_intrelational.py @@ -1,5 +1,6 @@ import pytest from rpython.jit.metainterp.optimizeopt.intrelational import IntOrderInfo +from rpython.jit.metainterp.optimizeopt.intutils import IntBound from rpython.jit.metainterp.optimize import InvalidLoop @@ -49,5 +50,14 @@ def test_lt_raises_invalidloop(): a = IntOrderInfo() b = IntOrderInfo() a.make_lt(b) - with pytest.raises(InvalidLoop) as e: + with pytest.raises(InvalidLoop): b.make_lt(a) + +def test_abstract_add(): + a = IntOrderInfo() + b = a.abstract_add_const(1) + assert not a.known_lt(b) # could have overflowed + + a = IntOrderInfo(IntBound(0, 10)) + b = a.abstract_add_const(1) + assert a.known_lt(b) # no overflow