From 7d4aa7a6f9cea93c50ad7c7b3fbb201154ae69dc Mon Sep 17 00:00:00 2001 From: Carl Friedrich Bolz-Tereick Date: Sun, 26 Apr 2020 17:37:20 +0200 Subject: make the JIT reason about int_invert and int_neg --- rpython/jit/metainterp/optimizeopt/intbounds.py | 24 +++++++ rpython/jit/metainterp/optimizeopt/intutils.py | 30 +++++++++ rpython/jit/metainterp/optimizeopt/rewrite.py | 3 + .../metainterp/optimizeopt/test/test_intbound.py | 28 ++++++++ .../optimizeopt/test/test_optimizebasic.py | 78 ++++++++++++++++++++++ 5 files changed, 163 insertions(+) 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) -- cgit v1.2.3-65-gdbad