aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'rpython/jit/metainterp/optimizeopt/intutils.py')
-rw-r--r--rpython/jit/metainterp/optimizeopt/intutils.py32
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):