[pypy-svn] pypy jit-unroll-loops: Allow integer divisions to be optimized somewhat if the arguments are known to be possitive. The last 3 ops after int_floordiv should be removed by the backend since their results are never used, right? Where does the "(i8 & i6) == -1" opps come from?

hakanardo commits-noreply at bitbucket.org
Tue Jan 4 20:02:05 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-unroll-loops
Changeset: r40395:7269121d3536
Date: 2011-01-04 20:01 +0100
http://bitbucket.org/pypy/pypy/changeset/7269121d3536/

Log:	Allow integer divisions to be optimized somewhat if the arguments
	are known to be possitive. The last 3 ops after int_floordiv should
	be removed by the backend since their results are never used, right?
	Where does the "(i8 & i6) == -1" opps come from?

diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -3868,6 +3868,136 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_bound_xor(self):
+        ops = """
+        [i0, i1, i2]
+        it1 = int_ge(i1, 0)
+        guard_true(it1) []
+        it2 = int_gt(i2, 0)
+        guard_true(it2) []
+        ix1 = int_xor(i0, i0)
+        ix1t = int_ge(ix1, 0)
+        guard_true(ix1t) []
+        ix2 = int_xor(i0, i1)
+        ix2t = int_ge(ix2, 0)
+        guard_true(ix2t) []
+        ix3 = int_xor(i1, i0)
+        ix3t = int_ge(ix3, 0)
+        guard_true(ix3t) []
+        ix4 = int_xor(i1, i2)
+        ix4t = int_ge(ix4, 0)
+        guard_true(ix4t) []
+        jump(i0, i1, i2)
+        """
+        preamble = """
+        [i0, i1, i2]
+        it1 = int_ge(i1, 0)
+        guard_true(it1) []
+        it2 = int_gt(i2, 0)
+        guard_true(it2) []
+        ix2 = int_xor(i0, i1)
+        ix2t = int_ge(ix2, 0)
+        guard_true(ix2t) []
+        ix3 = int_xor(i1, i0)
+        ix3t = int_ge(ix3, 0)
+        guard_true(ix3t) []
+        ix4 = int_xor(i1, i2)
+        jump(i0, i1, i2)
+        """
+        expected = """
+        [i0, i1, i2]
+        jump(i0, i1, i2)        
+        """
+        self.optimize_loop(ops, expected, preamble)
+
+    def test_bound_int_is_zero(self):
+        ops = """
+        [i1, i2a, i2b, i2c]
+        i3 = int_is_zero(i1)
+        i4 = int_gt(i2a, 7)
+        guard_true(i4) []
+        i5 = int_is_zero(i2a)
+        guard_false(i5) []
+        i6 = int_le(i2b, -7)
+        guard_true(i6) []
+        i7 = int_is_zero(i2b)
+        guard_false(i7) []
+        i8 = int_gt(i2c, -7)
+        guard_true(i8) []
+        i9 = int_is_zero(i2c)        
+        jump(i1, i2a, i2b, i2c)
+        """
+        preamble = """
+        [i1, i2a, i2b, i2c]
+        i3 = int_is_zero(i1)
+        i4 = int_gt(i2a, 7)
+        guard_true(i4) []
+        i6 = int_le(i2b, -7)
+        guard_true(i6) []
+        i8 = int_gt(i2c, -7)
+        guard_true(i8) []
+        i9 = int_is_zero(i2c)        
+        jump(i1, i2a, i2b, i2c)
+        """
+        expected = """
+        [i0, i1, i2, i3]
+        jump(i0, i1, i2, i3)        
+        """
+        self.optimize_loop(ops, expected, preamble)
+
+    def test_division(self):
+        ops = """
+        [i7, i6, i8]
+        it1 = int_gt(i7, 0)
+        guard_true(it1) []
+        it2 = int_gt(i6, 0)
+        guard_true(it2) []
+        i13 = int_is_zero(i6)
+        guard_false(i13) []
+        i15 = int_and(i8, i6)
+        i17 = int_eq(i15, -1)
+        guard_false(i17) []
+        i18 = int_floordiv(i7, i6)
+        i19 = int_xor(i7, i6)
+        i21 = int_lt(i19, 0)
+        i22 = int_mod(i7, i6)
+        i23 = int_is_true(i22)
+        i24 = int_and(i21, i23)
+        i25 = int_sub(i18, i24)
+        jump(i7, i25, i8)
+        """
+        preamble = """
+        [i7, i6, i8]
+        it1 = int_gt(i7, 0)
+        guard_true(it1) []
+        it2 = int_gt(i6, 0)
+        guard_true(it2) []
+        i15 = int_and(i8, i6)
+        i17 = int_eq(i15, -1)
+        guard_false(i17) []
+        i18 = int_floordiv(i7, i6)
+        i19 = int_xor(i7, i6)
+        i22 = int_mod(i7, i6)
+        i23 = int_is_true(i22)
+        jump(i7, i18, i8)
+        """
+        expected = """
+        [i7, i6, i8]
+        it2 = int_gt(i6, 0)
+        guard_true(it2) []
+        i15 = int_and(i8, i6)
+        i17 = int_eq(i15, -1)
+        guard_false(i17) []
+        i18 = int_floordiv(i7, i6)
+        i19 = int_xor(i7, i6)
+        i22 = int_mod(i7, i6)
+        i23 = int_is_true(i22)
+        jump(i7, i18, i8)
+        """
+        self.optimize_loop(ops, expected, preamble)
+
+
+
     def test_subsub_ovf(self):
         ops = """
         [i0]

diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -62,6 +62,18 @@
     optimize_GUARD_FALSE = optimize_GUARD_TRUE
     optimize_GUARD_VALUE = optimize_GUARD_TRUE
 
+    def optimize_INT_XOR(self, op):
+        v1 = self.getvalue(op.getarg(0))
+        v2 = self.getvalue(op.getarg(1))
+        if v1 is v2:
+            self.make_constant_int(op.result, 0)
+            return
+        self.emit_operation(op)
+        if v1.intbound.known_ge(IntBound(0, 0)) and \
+           v2.intbound.known_ge(IntBound(0, 0)):
+            r = self.getvalue(op.result)
+            r.intbound.make_ge(IntLowerBound(0))
+
     def optimize_INT_AND(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))

diff --git a/pypy/rpython/rint.py b/pypy/rpython/rint.py
--- a/pypy/rpython/rint.py
+++ b/pypy/rpython/rint.py
@@ -222,7 +222,7 @@
             # return (x/y) - (((x^y)<0)&((x%y)!=0));
             v_xor = hop.genop(prefix + 'xor', vlist,
                             resulttype=repr)
-            v_xor_le = hop.genop(prefix + 'le', [v_xor, c_zero],
+            v_xor_le = hop.genop(prefix + 'lt', [v_xor, c_zero],
                                  resulttype=Bool)
             v_xor_le = hop.llops.convertvar(v_xor_le, bool_repr, repr)
             v_mod = hop.genop(prefix + 'mod', vlist,

diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -120,6 +120,9 @@
             box = self.box
             assert isinstance(box, Const)
             return box.nonnull()
+        elif self.intbound.known_gt(IntBound(0, 0)) or \
+             self.intbound.known_lt(IntBound(0, 0)):
+            return True
         else:
             return False
 

diff --git a/pypy/module/pypyjit/test/test_pypy_c.py b/pypy/module/pypyjit/test/test_pypy_c.py
--- a/pypy/module/pypyjit/test/test_pypy_c.py
+++ b/pypy/module/pypyjit/test/test_pypy_c.py
@@ -1320,7 +1320,33 @@
         assert call.getarg(1).value == 2.0
         assert call.getarg(2).value == 3.0
 
-    # test_circular
+    def test_xor(self):
+        values = (-4, -3, -2, -1, 0, 1, 2, 3, 4)
+        for a in values:
+            for b in values:
+                if a^b >= 0:
+                    r = 2000
+                else:
+                    r = 0
+                if a > 0 and b > 1:
+                    ops = 0
+                else:
+                    ops = 0
+                
+                self.run_source('''
+                def main(a, b):
+                    i = sa = 0
+                    while i < 2000:
+                        if a > 0: # Specialises the loop
+                            pass
+                        if b > 1:
+                            pass
+                        if a^b >= 0:
+                            sa += 1
+                        i += 1
+                    return sa
+                ''', ops, ([a, b], r))
+        
 
 class AppTestJIT(PyPyCJITTests):
     def setup_class(cls):


More information about the Pypy-commit mailing list