aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Friedrich Bolz-Tereick <cfbolz@gmx.de>2020-04-26 17:37:20 +0200
committerCarl Friedrich Bolz-Tereick <cfbolz@gmx.de>2020-04-26 17:37:20 +0200
commit7d4aa7a6f9cea93c50ad7c7b3fbb201154ae69dc (patch)
treedf714dcea7c57958aea07d281b84c0747f608f5d /rpython/jit/metainterp
parentdocument branch (diff)
downloadpypy-7d4aa7a6f9cea93c50ad7c7b3fbb201154ae69dc.tar.gz
pypy-7d4aa7a6f9cea93c50ad7c7b3fbb201154ae69dc.tar.bz2
pypy-7d4aa7a6f9cea93c50ad7c7b3fbb201154ae69dc.zip
make the JIT reason about int_invert and int_neg
Diffstat (limited to 'rpython/jit/metainterp')
-rw-r--r--rpython/jit/metainterp/optimizeopt/intbounds.py24
-rw-r--r--rpython/jit/metainterp/optimizeopt/intutils.py30
-rw-r--r--rpython/jit/metainterp/optimizeopt/rewrite.py3
-rw-r--r--rpython/jit/metainterp/optimizeopt/test/test_intbound.py28
-rw-r--r--rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py78
5 files changed, 163 insertions, 0 deletions
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py
index 628cbf2757..5e99a4999f 100644
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -491,6 +491,30 @@ class OptIntBounds(Optimization):
bres = self.getintbound(op)
bres.intersect_const(start, stop - 1)
+ def postprocess_INT_INVERT(self, op):
+ b = self.getintbound(op.getarg(0))
+ bounds = b.invert_bound()
+ bres = self.getintbound(op)
+ bres.intersect(bounds)
+
+ def propagate_bounds_INT_INVERT(self, op):
+ b = self.getintbound(op.getarg(0))
+ bres = self.getintbound(op)
+ bounds = bres.invert_bound()
+ b.intersect(bounds)
+
+ def propagate_bounds_INT_NEG(self, op):
+ b = self.getintbound(op.getarg(0))
+ bres = self.getintbound(op)
+ bounds = bres.neg_bound()
+ b.intersect(bounds)
+
+ def postprocess_INT_NEG(self, op):
+ b = self.getintbound(op.getarg(0))
+ bounds = b.neg_bound()
+ bres = self.getintbound(op)
+ bres.intersect(bounds)
+
def optimize_ARRAYLEN_GC(self, op):
return self.emit(op)
diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py b/rpython/jit/metainterp/optimizeopt/intutils.py
index cbe10face6..9f2ced0f00 100644
--- a/rpython/jit/metainterp/optimizeopt/intutils.py
+++ b/rpython/jit/metainterp/optimizeopt/intutils.py
@@ -309,6 +309,36 @@ class IntBound(AbstractInfo):
r.make_ge_const(0)
return r
+ def invert_bound(self):
+ res = self.clone()
+ res.has_upper = False
+ if self.has_lower:
+ res.upper = ~self.lower
+ res.has_upper = True
+ res.has_lower = False
+ if self.has_upper:
+ res.lower = ~self.upper
+ res.has_lower = True
+ return res
+
+ def neg_bound(self):
+ res = self.clone()
+ res.has_upper = False
+ if self.has_lower:
+ try:
+ res.upper = ovfcheck(-self.lower)
+ res.has_upper = True
+ except OverflowError:
+ pass
+ res.has_lower = False
+ if self.has_upper:
+ try:
+ res.lower = ovfcheck(-self.upper)
+ res.has_lower = True
+ except OverflowError:
+ pass
+ return res
+
def contains(self, val):
if not we_are_translated():
assert not isinstance(val, long)
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
index 61e4b5ce5c..abb5766fd3 100644
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -267,6 +267,9 @@ class OptRewrite(Optimization):
else:
return self.emit(op)
+ def postprocess_INT_INVERT(self, op):
+ self.optimizer.pure_from_args(rop.INT_INVERT, [op], op.getarg(0))
+
def optimize_FLOAT_MUL(self, op):
arg1 = op.getarg(0)
arg2 = op.getarg(1)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
index 45b1635136..0b782b4e60 100644
--- a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
@@ -371,6 +371,19 @@ def test_next_pow2_m1():
assert next_pow2_m1((1 << 32) - 5) == (1 << 32) - 1
assert next_pow2_m1((1 << 64) - 1) == (1 << 64) - 1
+def test_invert_bound():
+ for _, _, b1 in some_bounds():
+ b2 = b1.invert_bound()
+ for n1 in nbr:
+ if b1.contains(n1):
+ assert b2.contains(~n1)
+
+def test_neg_bound():
+ for _, _, b1 in some_bounds():
+ b2 = b1.neg_bound()
+ for n1 in nbr:
+ if b1.contains(n1):
+ assert b2.contains(-n1)
@given(bound_with_contained_number, bound_with_contained_number)
def test_make_random(t1, t2):
@@ -464,3 +477,18 @@ def test_or_bound_random(t1, t2):
assert b3.contains(r)
r = n1 ^ n2
assert b3.contains(r)
+
+@given(bound_with_contained_number)
+def test_invert_bound_random(t1):
+ b1, n1 = t1
+ b2 = b1.invert_bound()
+ assert b2.contains(~n1)
+
+@given(bound_with_contained_number)
+def test_neg_bound_random(t1):
+ b1, n1 = t1
+ b2 = b1.neg_bound()
+ if n1 != -sys.maxint - 1:
+ assert b2.contains(-n1)
+ else:
+ assert not b2.has_lower
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
index 4daf55065d..ac115639fc 100644
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -6325,3 +6325,81 @@ class TestOptimizeBasic(BaseTestBasic):
escape_i(i0)
"""
self.optimize_loop(ops, expected)
+
+ def test_int_invert(self):
+ ops = """
+ [p0]
+ i1 = arraylen_gc(p0, descr=arraydescr) # known >= 0
+ i2 = int_invert(i1)
+ i3 = int_lt(i2, 0)
+ guard_true(i3) []
+ """
+ expected = """
+ [p0]
+ i1 = arraylen_gc(p0, descr=arraydescr) # known >= 0
+ i2 = int_invert(i1)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_invert_invert(self):
+ ops = """
+ [i1]
+ i2 = int_invert(i1)
+ i3 = int_invert(i2)
+ escape_i(i3)
+ """
+ expected = """
+ [i1]
+ i2 = int_invert(i1)
+ escape_i(i1)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_invert_postprocess(self):
+ ops = """
+ [i1]
+ i2 = int_invert(i1)
+ i3 = int_lt(i2, 0)
+ guard_true(i3) []
+ i4 = int_ge(i1, 0)
+ guard_true(i4) []
+ """
+ expected = """
+ [i1]
+ i2 = int_invert(i1)
+ i3 = int_lt(i2, 0)
+ guard_true(i3) []
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_neg(self):
+ ops = """
+ [p0]
+ i1 = arraylen_gc(p0, descr=arraydescr) # known >= 0
+ i2 = int_neg(i1)
+ i3 = int_le(i2, 0)
+ guard_true(i3) []
+ """
+ expected = """
+ [p0]
+ i1 = arraylen_gc(p0, descr=arraydescr) # known >= 0
+ i2 = int_neg(i1)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_neg_postprocess(self):
+ ops = """
+ [i1]
+ i2 = int_neg(i1)
+ i3 = int_le(i2, 0)
+ guard_true(i3) []
+ i4 = int_ge(i1, 0)
+ guard_true(i4) []
+ """
+ expected = """
+ [i1]
+ i2 = int_neg(i1)
+ i3 = int_le(i2, 0)
+ guard_true(i3) []
+ """
+ self.optimize_loop(ops, expected)