[pypy-svn] pypy fold_intadd: First commit of optimization and test.

ademan commits-noreply at bitbucket.org
Wed Mar 16 08:27:01 CET 2011


Author: Daniel Roberts <Ademan555 at gmail.com>
Branch: fold_intadd
Changeset: r42692:a1e30d4f9658
Date: 2011-03-16 00:26 -0700
http://bitbucket.org/pypy/pypy/changeset/a1e30d4f9658/

Log:	First commit of optimization and test.

diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -2,67 +2,43 @@
 from pypy.jit.metainterp.optimizeopt.rewrite import OptRewrite
 from pypy.jit.metainterp.optimizeopt.intbounds import OptIntBounds
 from pypy.jit.metainterp.optimizeopt.virtualize import OptVirtualize
+from pypy.jit.metainterp.optimizeopt.fold_intadd import OptAddition
 from pypy.jit.metainterp.optimizeopt.heap import OptHeap
 from pypy.jit.metainterp.optimizeopt.string import OptString
 from pypy.jit.metainterp.optimizeopt.unroll import optimize_unroll, OptInlineShortPreamble
-from pypy.jit.metainterp.optimizeopt.fficall import OptFfiCall
-from pypy.jit.metainterp.optimizeopt.simplify import OptSimplify
-from pypy.rlib.jit import PARAMETERS
-from pypy.rlib.unroll import unrolling_iterable
 
-ALL_OPTS = [('intbounds', OptIntBounds),
-            ('rewrite', OptRewrite),
-            ('virtualize', OptVirtualize),
-            ('string', OptString),
-            ('heap', OptHeap),
-            ('ffi', OptFfiCall),
-            ('unroll', None)]
-# no direct instantiation of unroll
-unroll_all_opts = unrolling_iterable(ALL_OPTS)
-
-ALL_OPTS_DICT = dict.fromkeys([name for name, _ in ALL_OPTS])
-
-ALL_OPTS_NAMES = ':'.join([name for name, _ in ALL_OPTS])
-PARAMETERS['enable_opts'] = ALL_OPTS_NAMES
-
-def optimize_loop_1(metainterp_sd, loop, enable_opts,
+def optimize_loop_1(metainterp_sd, loop, unroll=True,
                     inline_short_preamble=True, retraced=False):
     """Optimize loop.operations to remove internal overheadish operations. 
     """
-    optimizations = []
-    unroll = 'unroll' in enable_opts
-    for name, opt in unroll_all_opts:
-        if name in enable_opts:
-            if opt is not None:
-                o = opt()
-                if unroll and name == 'string':
-                    o.enabled = False
-                # FIXME: Workaround to disable string optimisation
-                # during preamble but to keep it during the loop
-                optimizations.append(o)
-
-    if 'rewrite' not in enable_opts or 'virtualize' not in enable_opts:
-        optimizations.append(OptSimplify())
-    
+    opt_str = OptString()
+    optimizations = [
+                     OptAddition(),
+                     OptIntBounds(),
+                     OptRewrite(),
+                     OptVirtualize(),
+                     opt_str,
+                     OptHeap(),
+                    ]
     if inline_short_preamble:
-        optimizations = [OptInlineShortPreamble(retraced)] + optimizations
+        optimizations = [OptInlineShortPreamble(retraced)] +  optimizations
+        
+    if metainterp_sd.jit_ffi:
+        from pypy.jit.metainterp.optimizeopt.fficall import OptFfiCall
+        optimizations = optimizations + [
+                     OptFfiCall(),
+                    ]
 
     if unroll:
+        opt_str.enabled = False # FIXME: Workaround to disable string optimisation
+                                # during preamble but to keep it during the loop
         optimize_unroll(metainterp_sd, loop, optimizations)
     else:
         optimizer = Optimizer(metainterp_sd, loop, optimizations)
         optimizer.propagate_all_forward()
 
-def optimize_bridge_1(metainterp_sd, bridge, enable_opts,
-                      inline_short_preamble=True, retraced=False):
+def optimize_bridge_1(metainterp_sd, bridge, inline_short_preamble=True,
+                      retraced=False):
     """The same, but for a bridge. """
-    enable_opts = enable_opts.copy()
-    try:
-        del enable_opts['unroll']
-    except KeyError:
-        pass
-    optimize_loop_1(metainterp_sd, bridge, enable_opts,
-                    inline_short_preamble, retraced)
-
-if __name__ == '__main__':
-    print ALL_OPTS_NAMES
+    optimize_loop_1(metainterp_sd, bridge, False, inline_short_preamble,
+                    retraced)

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
@@ -5,7 +5,7 @@
                                                         BaseTest)
 import pypy.jit.metainterp.optimizeopt.optimizer as optimizeopt
 import pypy.jit.metainterp.optimizeopt.virtualize as virtualize
-from pypy.jit.metainterp.optimizeopt import optimize_loop_1, ALL_OPTS_DICT
+from pypy.jit.metainterp.optimizeopt import optimize_loop_1
 from pypy.jit.metainterp.optimizeutil import InvalidLoop
 from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt
 from pypy.jit.metainterp.history import TreeLoop, LoopToken
@@ -163,10 +163,7 @@
 
     def optimize_loop(self, ops, optops, expected_preamble=None):
         loop = self.parse(ops)
-        if optops != "crash!":
-            expected = self.parse(optops)
-        else:
-            expected = "crash!"
+        expected = self.parse(optops)
         if expected_preamble:
             expected_preamble = self.parse(expected_preamble)
         #
@@ -188,18 +185,17 @@
             def clone_if_mutable(self):
                 return self
         loop.preamble.start_resumedescr = FakeDescr()
-        optimize_loop_1(metainterp_sd, loop, ALL_OPTS_DICT)
+        optimize_loop_1(metainterp_sd, loop)
         #
 
         print
         print loop.preamble.inputargs
         print '\n'.join([str(o) for o in loop.preamble.operations])
-        print
+        print 
         print loop.inputargs
         print '\n'.join([str(o) for o in loop.operations])
         print
-
-        assert expected != "crash!", "should have raised an exception"
+        
         self.assert_equal(loop, expected)
         if expected_preamble:
             self.assert_equal(loop.preamble, expected_preamble,
@@ -833,7 +829,7 @@
         i3 = getfield_gc(p2, descr=valuedescr)
         escape(i3)
         p3 = new_with_vtable(ConstClass(node_vtable))
-        setfield_gc(p3, i1, descr=valuedescr)
+        setfield_gc(p3, i1, descr=valuedescr)        
         jump(i1, p3)
         """
         # We cannot track virtuals that survive for more than two iterations.
@@ -893,7 +889,7 @@
         escape(i3)
         p2sub = new_with_vtable(ConstClass(node_vtable2))
         setfield_gc(p2sub, i1, descr=valuedescr)
-        setfield_gc(p2, p2sub, descr=nextdescr)
+        setfield_gc(p2, p2sub, descr=nextdescr)        
         jump(i1, p2, p2sub)
         """
         expected = """
@@ -1018,7 +1014,7 @@
         """
         preamble = """
         [i, p0]
-        i0 = getfield_gc(p0, descr=valuedescr)
+        i0 = getfield_gc(p0, descr=valuedescr)        
         i1 = int_add(i0, i)
         jump(i, i1)
         """
@@ -1350,26 +1346,6 @@
         self.node.value = 5
         self.optimize_loop(ops, expected)
 
-    def test_getfield_gc_pure_3(self):
-        ops = """
-        []
-        p1 = escape()
-        p2 = getfield_gc_pure(p1, descr=nextdescr)
-        escape(p2)
-        p3 = getfield_gc_pure(p1, descr=nextdescr)
-        escape(p3)
-        jump()
-        """
-        expected = """
-        []
-        p1 = escape()
-        p2 = getfield_gc_pure(p1, descr=nextdescr)
-        escape(p2)
-        escape(p2)
-        jump()
-        """
-        self.optimize_loop(ops, expected)
-
     def test_getfield_gc_nonpure_2(self):
         ops = """
         [i]
@@ -3464,7 +3440,7 @@
         guard_true(i1) []
         i2 = int_sub(i0, 10)
         i3 = int_lt(i2, -5)
-        guard_true(i3) []
+        guard_true(i3) []        
         jump(i0)
         """
         expected = """
@@ -3490,7 +3466,7 @@
         i1 = int_lt(i0, 4)
         guard_true(i1) []
         i1p = int_gt(i0, -4)
-        guard_true(i1p) []
+        guard_true(i1p) []        
         i2 = int_sub(i0, 10)
         jump(i0)
         """
@@ -3773,7 +3749,7 @@
         ops = """
         [p4, p7, i30]
         p16 = getfield_gc(p4, descr=valuedescr)
-        p17 = getarrayitem_gc(p4, 1, descr=arraydescr)
+        p17 = getarrayitem_gc(p4, 1, descr=arraydescr)        
         guard_value(p16, ConstPtr(myptr), descr=<Guard3>) []
         i1 = getfield_raw(p7, descr=nextdescr)
         i2 = int_add(i1, i30)
@@ -3830,47 +3806,6 @@
         self.node.value = 5
         self.optimize_loop(ops, expected)
 
-    def test_complains_getfieldpure_setfield(self):
-        from pypy.jit.metainterp.optimizeopt.heap import BogusPureField
-        ops = """
-        [p3]
-        p1 = escape()
-        p2 = getfield_gc_pure(p1, descr=nextdescr)
-        setfield_gc(p1, p3, descr=nextdescr)
-        jump(p3)
-        """
-        py.test.raises(BogusPureField, self.optimize_loop, ops, "crash!")
-
-    def test_dont_complains_different_field(self):
-        ops = """
-        [p3]
-        p1 = escape()
-        p2 = getfield_gc_pure(p1, descr=nextdescr)
-        setfield_gc(p1, p3, descr=otherdescr)
-        escape(p2)
-        jump(p3)
-        """
-        expected = """
-        [p3]
-        p1 = escape()
-        p2 = getfield_gc_pure(p1, descr=nextdescr)
-        setfield_gc(p1, p3, descr=otherdescr)
-        escape(p2)
-        jump(p3)
-        """
-        self.optimize_loop(ops, expected)
-
-    def test_dont_complains_different_object(self):
-        ops = """
-        []
-        p1 = escape()
-        p2 = getfield_gc_pure(p1, descr=nextdescr)
-        p3 = escape()
-        setfield_gc(p3, p1, descr=nextdescr)
-        jump()
-        """
-        self.optimize_loop(ops, ops)
-
     def test_getfield_guard_const(self):
         ops = """
         [p0]
@@ -3940,7 +3875,7 @@
         jump(p0)
         """
         self.optimize_loop(ops, expected, expected)
-
+        
     def test_addsub_ovf(self):
         ops = """
         [i0]
@@ -4060,7 +3995,7 @@
         """
         expected = """
         [i0, i1, i2]
-        jump(i0, i1, i2)
+        jump(i0, i1, i2)        
         """
         self.optimize_loop(ops, expected, preamble)
 
@@ -4099,7 +4034,7 @@
         """
         expected = """
         [i0, i1, i2]
-        jump(i0, i1, i2)
+        jump(i0, i1, i2)        
         """
         self.optimize_loop(ops, expected, preamble)
 
@@ -4117,7 +4052,7 @@
         guard_false(i7) []
         i8 = int_gt(i2c, -7)
         guard_true(i8) []
-        i9 = int_is_zero(i2c)
+        i9 = int_is_zero(i2c)        
         jump(i1, i2a, i2b, i2c)
         """
         preamble = """
@@ -4129,12 +4064,12 @@
         guard_true(i6) []
         i8 = int_gt(i2c, -7)
         guard_true(i8) []
-        i9 = int_is_zero(i2c)
+        i9 = int_is_zero(i2c)        
         jump(i1, i2a, i2b, i2c)
         """
         expected = """
         [i0, i1, i2, i3]
-        jump(i0, i1, i2, i3)
+        jump(i0, i1, i2, i3)        
         """
         self.optimize_loop(ops, expected, preamble)
 
@@ -4192,7 +4127,7 @@
     def test_division_to_rshift(self):
         ops = """
         [i1, i2]
-        it = int_gt(i1, 0)
+        it = int_gt(i1, 0) 
         guard_true(it)[]
         i3 = int_floordiv(i1, i2)
         i4 = int_floordiv(2, i2)
@@ -4210,15 +4145,15 @@
         """
         expected = """
         [i1, i2]
-        it = int_gt(i1, 0)
-        guard_true(it)[]
+        it = int_gt(i1, 0) 
+        guard_true(it)[]        
         i3 = int_floordiv(i1, i2)
         i4 = int_floordiv(2, i2)
         i5 = int_rshift(i1, 1)
         i6 = int_floordiv(3, i2)
         i7 = int_floordiv(i1, 3)
         i8 = int_floordiv(4, i2)
-        i9 = int_rshift(i1, 2)
+        i9 = int_rshift(i1, 2)        
         i10 = int_floordiv(i1, 0)
         i11 = int_rshift(i1, 0)
         i12 = int_floordiv(i2, 2)
@@ -4259,7 +4194,7 @@
         i9 = int_lt(i1b, 100)
         guard_true(i9) []
         i10 = int_gt(i1b, -100)
-        guard_true(i10) []
+        guard_true(i10) []        
         i13 = int_lshift(i1b, i2)
         i14 = int_rshift(i13, i2)
         i15 = int_lshift(i1b, 2)
@@ -4283,19 +4218,16 @@
         i9 = int_lt(i1b, 100)
         guard_true(i9) []
         i10 = int_gt(i1b, -100)
-        guard_true(i10) []
+        guard_true(i10) []        
         i13 = int_lshift(i1b, i2)
         i14 = int_rshift(i13, i2)
         i15 = int_lshift(i1b, 2)
-        i16 = int_rshift(i15, 2)
         i17 = int_lshift(i1b, 100)
         i18 = int_rshift(i17, 100)
-        i19 = int_eq(i1b, i16)
-        guard_true(i19) []
         jump(i2, i3, i1b, i2b)
         """
         self.optimize_loop(ops, expected)
-
+        
     def test_subsub_ovf(self):
         ops = """
         [i0]
@@ -4479,7 +4411,7 @@
         jump(i0, i1, i1b, i2, i3)
         """
         preamble = """
-        [i0, i1, i1b, i2, i3]
+        [i0, i1, i1b, i2, i3]        
         i4 = int_lt(i1, 7)
         guard_true(i4) []
         i4b = int_lt(i1b, 7)
@@ -4507,9 +4439,9 @@
         """
         expected = """
         [i0, i1, i1b, i2, i3]
-        jump(i0, i1, i1b, i2, i3)
-        """
-        self.optimize_loop(ops, expected, preamble)
+        jump(i0, i1, i1b, i2, i3)        
+        """
+        self.optimize_loop(ops, expected, preamble)        
 
     def test_bound_rshift(self):
         ops = """
@@ -4544,7 +4476,7 @@
         jump(i0, i1, i1b, i2, i3)
         """
         preamble = """
-        [i0, i1, i1b, i2, i3]
+        [i0, i1, i1b, i2, i3]        
         i4 = int_lt(i1, 7)
         guard_true(i4) []
         i4b = int_lt(i1b, 7)
@@ -4572,9 +4504,9 @@
         """
         expected = """
         [i0, i1, i1b, i2, i3]
-        jump(i0, i1, i1b, i2, i3)
-        """
-        self.optimize_loop(ops, expected, preamble)
+        jump(i0, i1, i1b, i2, i3)        
+        """
+        self.optimize_loop(ops, expected, preamble)        
 
     def test_bound_dont_backpropagate_rshift(self):
         ops = """
@@ -4587,7 +4519,7 @@
         """
         self.optimize_loop(ops, ops, ops)
 
-
+        
     def test_mul_ovf(self):
         ops = """
         [i0, i1]
@@ -4726,7 +4658,7 @@
             def sort_key(self):
                 return id(self)
 
-
+                
         for n in ('inst_w_seq', 'inst_index', 'inst_w_list', 'inst_length',
                   'inst_start', 'inst_step'):
             self.namespace[n] = FakeDescr(n)
@@ -4768,7 +4700,7 @@
         i87 = int_add(i84, i86)
         i91 = int_add(i80, 1)
         setfield_gc(p75, i91, descr=inst_index)
-
+        
         p110 = same_as(ConstPtr(myptr))
         i112 = same_as(3)
         i114 = same_as(39)
@@ -4788,13 +4720,13 @@
         p1 = getfield_gc(p0, descr=valuedescr)
         setfield_gc(p0, p1, descr=valuedescr)
         setfield_gc(p0, p1, descr=valuedescr)
-        setfield_gc(p0, p0, descr=valuedescr)
+        setfield_gc(p0, p0, descr=valuedescr)        
         jump(p0)
         """
         preamble = """
         [p0]
         p1 = getfield_gc(p0, descr=valuedescr)
-        setfield_gc(p0, p0, descr=valuedescr)
+        setfield_gc(p0, p0, descr=valuedescr)                
         jump(p0)
         """
         expected = """
@@ -4807,7 +4739,7 @@
         ops = """
         [p0]
         p1 = getfield_gc(p0, descr=valuedescr)
-        setfield_gc(p0, p0, descr=valuedescr)
+        setfield_gc(p0, p0, descr=valuedescr)        
         setfield_gc(p0, p1, descr=valuedescr)
         setfield_gc(p0, p1, descr=valuedescr)
         jump(p0)
@@ -4831,7 +4763,7 @@
         p2 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p2, i1, descr=nextdescr)
         """
-
+        
     # ----------
     def optimize_strunicode_loop(self, ops, optops, preamble=None):
         if not preamble:
@@ -5113,40 +5045,6 @@
         """
         self.optimize_strunicode_loop(ops, expected)
 
-    def test_strgetitem_small(self):
-        ops = """
-        [p0, i0]
-        i1 = strgetitem(p0, i0)
-        i2 = int_lt(i1, 256)
-        guard_true(i2) []
-        i3 = int_ge(i1, 0)
-        guard_true(i3) []
-        jump(p0, i0)
-        """
-        expected = """
-        [p0, i0]
-        i1 = strgetitem(p0, i0)
-        jump(p0, i0)
-        """
-        self.optimize_loop(ops, expected)
-
-    def test_strlen_positive(self):
-        ops = """
-        [p0]
-        i0 = strlen(p0)
-        i1 = int_ge(i0, 0)
-        guard_true(i1) []
-        i2 = int_gt(i0, -1)
-        guard_true(i2) []
-        jump(p0)
-        """
-        expected = """
-        [p0]
-        i0 = strlen(p0)
-        jump(p0)
-        """
-        self.optimize_loop(ops, expected)
-
     # ----------
     def optimize_strunicode_loop_extradescrs(self, ops, optops, preamble=None):
         from pypy.jit.metainterp.optimizeopt import string
@@ -5506,9 +5404,24 @@
         # more generally, supporting non-constant but virtual cases is
         # not obvious, because of the exception UnicodeDecodeError that
         # can be raised by ll_str2unicode()
-
-
-
+        
+
+class TestFoldIntAdds(OptimizeOptTest, LLtypeMixin):
+    def test_fold(self):
+        ops = """
+        [i0]
+        i1 = int_add(i0, 3)
+        i2 = int_add(i1, 16)
+        i3 = int_add(i2, 9)
+        jump(i3)
+        """
+
+        expected = """
+        [i0]
+        i3 = int_add(i0, 28)
+        jump(i3)
+        """
+        self.optimize_loop(ops, expected)
 
 ##class TestOOtype(OptimizeOptTest, OOtypeMixin):
 

diff --git a/pypy/jit/metainterp/optimizeopt/fold_intadd.py b/pypy/jit/metainterp/optimizeopt/fold_intadd.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/metainterp/optimizeopt/fold_intadd.py
@@ -0,0 +1,77 @@
+from pypy.jit.metainterp.optimizeopt.optimizer import *
+from pypy.jit.metainterp.resoperation import opboolinvers, opboolreflex
+from pypy.jit.metainterp.history import ConstInt
+from pypy.jit.metainterp.optimizeutil import _findall
+from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.codewriter.effectinfo import EffectInfo
+from pypy.jit.metainterp.optimizeopt.intutils import IntBound
+from pypy.rlib.rarithmetic import highest_bit
+
+class OptAddition(Optimization):
+    def __init__(self):
+        self.args = {}
+
+    def reconstruct_for_next_iteration(self, optimizer, valuemap):
+        return OptAddition()
+
+    def propagate_forward(self, op):
+        opnum = op.getopnum()
+        for value, func in optimize_ops:
+            if opnum == value:
+                func(self, op)
+                break
+        else:
+            self.optimize_default(op)
+
+    def _int_add(self, variable, constant, result):
+        return ResOperation(rop.INT_ADD, [variable, constant], result)
+
+    def _store_add(self, variable, constant, result):
+        try:
+            root, stored_constant = self.args[variable]
+            constant = constant + stored_constant
+        except KeyError:
+            root = variable
+
+        self.args[result] = root, constant
+
+    def optimize_INT_ADD(self, op):
+        lv = self.getvalue(op.getarg(0))
+        rv = self.getvalue(op.getarg(1))
+        print "lv = %s rv = %s" % (lv.box, rv.box)
+        result = op.result
+        if lv.is_constant() and rv.is_constant():
+            self.emit_operation(op) # XXX: there's support for optimizing this elsewhere, right?
+        elif lv.is_constant():
+            constant = lv.box.getint()
+            self._store_add(op.getarg(1), constant, result)
+        elif rv.is_constant():
+            constant = rv.box.getint()
+            self._store_add(op.getarg(0), constant, result)
+        else:
+            self.emit_operation(op)
+
+    def optimize_default(self, op):
+        for i in range(op.numargs()):
+            arg = self.getvalue(op.getarg(i))
+            print 'type(%s) = %s' % (arg.box, type(arg))
+            if arg.is_constant():
+                continue
+
+            try:
+                variable = op.getarg(i)
+                root, constant = self.args[variable]
+                del self.args[variable] # TODO: mark as used instead of deleting
+
+                constant = ConstInt(constant)
+                new_op = self._int_add(root, constant, variable)
+                print new_op
+                self.emit_operation(new_op)
+            except KeyError:
+                pass
+        print op
+        self.emit_operation(op)
+
+    #def optimize_INT_SUB(self, op): pass
+
+optimize_ops = _findall(OptAddition, 'optimize_')


More information about the Pypy-commit mailing list