Author: Armin Rigo <ar...@tunes.org>
Branch: remove-raisingops
Changeset: r84291:f69d3f2271bd
Date: 2016-05-08 18:59 +0200
http://bitbucket.org/pypy/pypy/changeset/f69d3f2271bd/

Log:    fix fix fix

diff --git a/rpython/jit/metainterp/optimizeopt/dependency.py 
b/rpython/jit/metainterp/optimizeopt/dependency.py
--- a/rpython/jit/metainterp/optimizeopt/dependency.py
+++ b/rpython/jit/metainterp/optimizeopt/dependency.py
@@ -930,7 +930,7 @@
     exec py.code.Source(multiplicative_func_source
             .format(name='INT_MUL', op='*', tgt='mul', cop='*')).compile()
     exec py.code.Source(multiplicative_func_source
-            .format(name='INT_FLOORDIV', op='*', tgt='div', cop='/')).compile()
+            .format(name='INT_PY_DIV', op='*', tgt='div', cop='/')).compile()
     exec py.code.Source(multiplicative_func_source
             .format(name='UINT_FLOORDIV', op='*', tgt='div', 
cop='/')).compile()
     del multiplicative_func_source
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py 
b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -172,22 +172,21 @@
         if b.bounded():
             r.intersect(b)
 
-    def optimize_INT_FLOORDIV(self, op):
+    def optimize_INT_PY_DIV(self, op):
         b1 = self.getintbound(op.getarg(0))
         b2 = self.getintbound(op.getarg(1))
         self.emit_operation(op)
         r = self.getintbound(op)
-        r.intersect(b1.div_bound(b2))
+        r.intersect(b1.py_div_bound(b2))
 
-    def optimize_INT_MOD(self, op):
+    def optimize_INT_PY_MOD(self, op):
         b1 = self.getintbound(op.getarg(0))
         b2 = self.getintbound(op.getarg(1))
-        known_nonneg = (b1.known_ge(IntBound(0, 0)) and
-                        b2.known_ge(IntBound(0, 0)))
-        if known_nonneg and b2.is_constant():
+        if b2.is_constant():
             val = b2.getint()
-            if (val & (val-1)) == 0:
-                # nonneg % power-of-two ==> nonneg & (power-of-two - 1)
+            if val > 0 and (val & (val-1)) == 0:
+                # x % power-of-two ==> x & (power-of-two - 1)
+                # with Python's modulo, this is valid even if 'x' is negative.
                 arg1 = op.getarg(0)
                 arg2 = ConstInt(val-1)
                 op = self.replace_op_with(op, rop.INT_AND,
@@ -196,15 +195,12 @@
         if b2.is_constant():
             val = b2.getint()
             r = self.getintbound(op)
-            if val < 0:
-                if val == -sys.maxint-1:
-                    return     # give up
-                val = -val
-            if known_nonneg:
+            if val >= 0:        # with Python's modulo:  0 <= (x % pos) < pos
                 r.make_ge(IntBound(0, 0))
-            else:
-                r.make_gt(IntBound(-val, -val))
-            r.make_lt(IntBound(val, val))
+                r.make_lt(IntBound(val, val))
+            else:               # with Python's modulo:  neg < (x % neg) <= 0
+                r.make_gt(IntBound(val, val))
+                r.make_le(IntBound(0, 0))
 
     def optimize_INT_LSHIFT(self, op):
         arg0 = self.get_box_replacement(op.getarg(0))
@@ -613,10 +609,10 @@
         b1 = self.getintbound(op.getarg(0))
         b2 = self.getintbound(op.getarg(1))
         r = self.getintbound(op)
-        b = r.div_bound(b2)
+        b = r.py_div_bound(b2)
         if b1.intersect(b):
             self.propagate_bounds_backward(op.getarg(0))
-        b = r.div_bound(b1)
+        b = r.py_div_bound(b1)
         if b2.intersect(b):
             self.propagate_bounds_backward(op.getarg(1))
 
diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py 
b/rpython/jit/metainterp/optimizeopt/intutils.py
--- a/rpython/jit/metainterp/optimizeopt/intutils.py
+++ b/rpython/jit/metainterp/optimizeopt/intutils.py
@@ -171,11 +171,14 @@
         else:
             return IntUnbounded()
 
-    def div_bound(self, other):
+    def py_div_bound(self, other):
         if self.has_upper and self.has_lower and \
            other.has_upper and other.has_lower and \
            not other.contains(0):
             try:
+                # this gives the bounds for 'int_py_div', so use the
+                # Python-style handling of negative numbers and not
+                # the C-style one
                 vals = (ovfcheck(self.upper / other.upper),
                         ovfcheck(self.upper / other.lower),
                         ovfcheck(self.lower / other.upper),
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py 
b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -678,21 +678,23 @@
     def optimize_GUARD_FUTURE_CONDITION(self, op):
         self.optimizer.notice_guard_future_condition(op)
 
-    def optimize_INT_FLOORDIV(self, op):
+    def optimize_INT_PY_DIV(self, op):
         arg0 = op.getarg(0)
         b1 = self.getintbound(arg0)
         arg1 = op.getarg(1)
         b2 = self.getintbound(arg1)
 
-        if b2.is_constant() and b2.getint() == 1:
-            self.make_equal_to(op, arg0)
-            return
-        elif b1.is_constant() and b1.getint() == 0:
+        if b1.is_constant() and b1.getint() == 0:
             self.make_constant_int(op, 0)
             return
-        if b1.known_ge(IntBound(0, 0)) and b2.is_constant():
+        # This is Python's integer division: 'x // (2**shift)' can always
+        # be replaced with 'x >> shift', even for negative values of x
+        if b2.is_constant():
             val = b2.getint()
-            if val & (val - 1) == 0 and val > 0: # val == 2**shift
+            if val == 1:
+                self.make_equal_to(op, arg0)
+                return
+            elif val > 0 and val & (val - 1) == 0:   # val == 2**shift
                 op = self.replace_op_with(op, rop.INT_RSHIFT,
                             args = [op.getarg(0), ConstInt(highest_bit(val))])
         self.emit_operation(op)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py 
b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
@@ -242,18 +242,18 @@
 def test_div_bound():
     for _, _, b1 in some_bounds():
         for _, _, b2 in some_bounds():
-            b3 = b1.div_bound(b2)
+            b3 = b1.py_div_bound(b2)
             for n1 in nbr:
                 for n2 in nbr:
                     if b1.contains(n1) and b2.contains(n2):
                         if n2 != 0:
-                            assert b3.contains(n1 / n2)
+                            assert b3.contains(n1 / n2)   # Python-style div
 
-    a=bound(2, 4).div_bound(bound(1, 2))
+    a=bound(2, 4).py_div_bound(bound(1, 2))
     assert not a.contains(0)
     assert not a.contains(5)
 
-    a=bound(-3, 2).div_bound(bound(1, 2))
+    a=bound(-3, 2).py_div_bound(bound(1, 2))
     assert not a.contains(-4)
     assert not a.contains(3)
     assert a.contains(-3)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py 
b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -1849,7 +1849,7 @@
 
         ops = """
         [i0]
-        i1 = int_floordiv(0, i0)
+        i1 = int_py_div(0, i0)
         jump(i1)
         """
         expected = """
@@ -4645,94 +4645,63 @@
     def test_intmod_bounds(self):
         ops = """
         [i0, i1]
-        i2 = int_mod(i0, 12)
-        i3 = int_gt(i2, 12)
+        i2 = int_py_mod(i0, 12)
+        i3 = int_ge(i2, 12)
         guard_false(i3) []
-        i4 = int_lt(i2, -12)
+        i4 = int_lt(i2, 0)
         guard_false(i4) []
-        i5 = int_mod(i1, -12)
-        i6 = int_lt(i5, -12)
+        i5 = int_py_mod(i1, -12)
+        i6 = int_le(i5, -12)
         guard_false(i6) []
-        i7 = int_gt(i5, 12)
+        i7 = int_gt(i5, 0)
         guard_false(i7) []
         jump(i2, i5)
         """
         expected = """
         [i0, i1]
-        i2 = int_mod(i0, 12)
-        i5 = int_mod(i1, -12)
+        i2 = int_py_mod(i0, 12)
+        i5 = int_py_mod(i1, -12)
         jump(i2, i5)
         """
         self.optimize_loop(ops, expected)
 
-        # This the sequence of resoperations that is generated for a Python
-        # app-level int % int.  When the modulus is constant and when i0
-        # is known non-negative it should be optimized to a single int_mod.
+        # same as above, but all guards are shifted by one so that they
+        # must stay
+        ops = """
+        [i8, i9]
+        i0 = escape_i()
+        i2 = int_py_mod(i0, 12)
+        i3 = int_ge(i2, 11)
+        guard_false(i3) []
+        i4 = int_lt(i2, 1)
+        guard_false(i4) []
+        i1 = escape_i()
+        i5 = int_py_mod(i1, -12)
+        i6 = int_le(i5, -11)
+        guard_false(i6) []
+        i7 = int_gt(i5, -1)
+        guard_false(i7) []
+        jump(i2, i5)
+        """
+        self.optimize_loop(ops, ops)
+
+        # 'n % power-of-two' can always be turned into int_and()
         ops = """
         [i0]
-        i5 = int_ge(i0, 0)
-        guard_true(i5) []
-        i1 = int_mod(i0, 42)
-        i2 = int_rshift(i1, %d)
-        i3 = int_and(42, i2)
-        i4 = int_add(i1, i3)
-        finish(i4)
-        """ % (LONG_BIT-1)
+        i1 = int_py_mod(i0, 8)
+        finish(i1)
+        """
         expected = """
         [i0]
-        i5 = int_ge(i0, 0)
-        guard_true(i5) []
-        i1 = int_mod(i0, 42)
-        finish(i1)
-        """
-        self.optimize_loop(ops, expected)
-
-        # 'n % power-of-two' can be turned into int_and(); at least that's
-        # easy to do now if n is known to be non-negative.
-        ops = """
-        [i0]
-        i5 = int_ge(i0, 0)
-        guard_true(i5) []
-        i1 = int_mod(i0, 8)
-        i2 = int_rshift(i1, %d)
-        i3 = int_and(42, i2)
-        i4 = int_add(i1, i3)
-        finish(i4)
-        """ % (LONG_BIT-1)
-        expected = """
-        [i0]
-        i5 = int_ge(i0, 0)
-        guard_true(i5) []
         i1 = int_and(i0, 7)
         finish(i1)
         """
         self.optimize_loop(ops, expected)
 
-    def test_intmod_bounds_harder(self):
-        py.test.skip("harder")
-        # Of course any 'maybe-negative % power-of-two' can be turned into
-        # int_and(), but that's a bit harder to detect here because it turns
-        # into several operations, and of course it is wrong to just turn
-        # int_mod(i0, 16) into int_and(i0, 15).
+    def test_intmod_bounds_bug1(self):
         ops = """
         [i0]
-        i1 = int_mod(i0, 16)
-        i2 = int_rshift(i1, %d)
-        i3 = int_and(16, i2)
-        i4 = int_add(i1, i3)
-        finish(i4)
-        """ % (LONG_BIT-1)
-        expected = """
-        [i0]
-        i4 = int_and(i0, 15)
-        finish(i4)
-        """
-        self.optimize_loop(ops, expected)
-
-    def test_intmod_bounds_bug1(self):
-        ops = """
-        [i0]
-        i1 = int_mod(i0, %d)
+        i1 = int_py_mod(i0, %d)
         i2 = int_eq(i1, 0)
         guard_false(i2) []
         finish()
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to