diff options
Diffstat (limited to 'rpython/jit/metainterp/optimizeopt/intutils.py')
-rw-r--r-- | rpython/jit/metainterp/optimizeopt/intutils.py | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py b/rpython/jit/metainterp/optimizeopt/intutils.py index 9f2ced0f00..49e2b3498e 100644 --- a/rpython/jit/metainterp/optimizeopt/intutils.py +++ b/rpython/jit/metainterp/optimizeopt/intutils.py @@ -26,6 +26,18 @@ def next_pow2_m1(n): return n +def upper_bound_or_xor(upper1, upper2): + pow2 = next_pow2_m1(upper1 | upper2) + try: + # addition gives an ok (but not tight) upper bound of | and ^ (for + # known non-negative numbers) + add = ovfcheck(upper1 + upper2) + except OverflowError: + return pow2 + else: + return min(pow2, add) + + class IntBound(AbstractInfo): _attrs_ = ('has_upper', 'has_lower', 'upper', 'lower') @@ -302,11 +314,23 @@ class IntBound(AbstractInfo): r = IntUnbounded() if self.known_nonnegative() and \ other.known_nonnegative(): + r.make_ge_const(0) if self.has_upper and other.has_upper: - mostsignificant = self.upper | other.upper - r.intersect(IntBound(0, next_pow2_m1(mostsignificant))) - else: - r.make_ge_const(0) + r.make_le_const(upper_bound_or_xor(self.upper, other.upper)) + if self.has_lower and other.has_lower: + # max of the two lower bounds gives an ok (but not tight) lower + # bound of or + lower = max(self.lower, other.lower) + r.make_ge_const(lower) + return r + + def xor_bound(self, other): + r = IntUnbounded() + if self.known_nonnegative() and \ + other.known_nonnegative(): + r.make_ge_const(0) + if self.has_upper and other.has_upper: + r.make_le_const(upper_bound_or_xor(self.upper, other.upper)) return r def invert_bound(self): |