[pypy-svn] pypy jit-short_from_state: emit guards from short_preamble with proper desc at end of loop in case the optimizer is not able to remove them

hakanardo commits-noreply at bitbucket.org
Fri May 6 12:50:17 CEST 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-short_from_state
Changeset: r43926:6db30e2775cc
Date: 2011-05-06 12:37 +0200
http://bitbucket.org/pypy/pypy/changeset/6db30e2775cc/

Log:	emit guards from short_preamble with proper desc at end of loop in
	case the optimizer is not able to remove them

diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -175,6 +175,23 @@
                     self.constant_inputargs[box] = const
         
             initial_inputargs_len = len(inputargs)
+            self.inliner = Inliner(loop.inputargs, jump_args)
+
+            start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable()
+            self.start_resumedescr = start_resumedescr
+            assert isinstance(start_resumedescr, ResumeGuardDescr)
+            snapshot = start_resumedescr.rd_snapshot
+            while snapshot is not None:
+                snapshot_args = snapshot.boxes 
+                new_snapshot_args = []
+                for a in snapshot_args:
+                    if not isinstance(a, Const):
+                        a = loop.preamble.inputargs[jump_args.index(a)]
+                    a = self.inliner.inline_arg(a)
+                    a = self.getvalue(a).get_key_box()
+                    new_snapshot_args.append(a)
+                snapshot.boxes = new_snapshot_args
+                snapshot = snapshot.prev
 
             inputargs, short_inputargs, short = self.inline(self.cloned_operations,
                                            loop.inputargs, jump_args,
@@ -192,21 +209,6 @@
 
             loop.operations = self.optimizer.newoperations
 
-            start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable()
-            assert isinstance(start_resumedescr, ResumeGuardDescr)
-            snapshot = start_resumedescr.rd_snapshot
-            while snapshot is not None:
-                snapshot_args = snapshot.boxes 
-                new_snapshot_args = []
-                for a in snapshot_args:
-                    if not isinstance(a, Const):
-                        a = loop.preamble.inputargs[jump_args.index(a)]
-                    a = self.inliner.inline_arg(a)
-                    a = self.getvalue(a).get_key_box()
-                    new_snapshot_args.append(a)
-                snapshot.boxes = new_snapshot_args
-                snapshot = snapshot.prev
-
             #short = self.create_short_preamble(loop.preamble, loop)
             if short:
                 assert short[-1].getopnum() == rop.JUMP
@@ -218,7 +220,7 @@
                     if op.is_guard():
                         op = op.clone()
                         op.setfailargs(None)
-                        descr = start_resumedescr.clone_if_mutable()
+                        descr = self.start_resumedescr.clone_if_mutable()
                         op.setdescr(descr)
                         short[i] = op
 
@@ -234,7 +236,7 @@
                 short_loop.inputargs = newargs
                 ops = [inliner.inline_op(op) for op in short_loop.operations]
                 short_loop.operations = ops
-                descr = start_resumedescr.clone_if_mutable()
+                descr = self.start_resumedescr.clone_if_mutable()
                 inliner.inline_descr_inplace(descr)
                 short_loop.start_resumedescr = descr
 
@@ -253,7 +255,7 @@
                         op.result.forget_value()
                 
     def inline(self, loop_operations, loop_args, jump_args, virtual_state):
-        self.inliner = inliner = Inliner(loop_args, jump_args)
+        inliner = self.inliner
 
         values = [self.getvalue(arg) for arg in jump_args]
         inputargs = virtual_state.make_inputargs(values)
@@ -320,29 +322,26 @@
 
     def add_op_to_short(self, op, short, short_seen):
         if op is None:
-            return 
+            return
         if op.result is not None and op.result in short_seen:
             return self.short_inliner.inline_arg(op.result)
         for a in op.getarglist():
             if not isinstance(a, Const) and a not in short_seen:
                 self.add_op_to_short(self.short_boxes[a], short, short_seen)
+        if op.is_guard():
+            descr = self.start_resumedescr.clone_if_mutable()
+            op.setdescr(descr)
+            
         short.append(op)
         short_seen[op.result] = True
         newop = self.short_inliner.inline_op(op)
-        newoplen = len(self.optimizer.newoperations)
         self.optimizer.send_extra_operation(newop)
-        assert len(self.optimizer.newoperations) == newoplen
 
         if op.is_ovf():
             # FIXME: ensure that GUARD_OVERFLOW:ed ops not end up here
             guard = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
-            short.append(guard)
-            newoplen = len(self.optimizer.newoperations)
-            self.optimizer.send_extra_operation(guard)
-            assert len(self.optimizer.newoperations) == newoplen
+            self.add_op_to_short(guard, short, short_seen)
 
-        # FIXME: Emit a proper guards here in case it is not
-        #        removed by the optimizer. Can that happen?
         return newop.result
         
     def import_box(self, box, inputargs, short, short_jumpargs,
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -2355,6 +2355,25 @@
             return f(n, A(5), A(10))
         assert self.meta_interp(g, [20]) == g(20)
 
+    def test_ovf_guard_in_short_preamble2(self):
+        class A(object):
+            def __init__(self, val):
+                self.val = val
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a', 'node1', 'node2'])
+        def f(n, a):
+            node1 = node2 = A(0)
+            sa = i = 0
+            while i < n:
+                myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a, node1=node1, node2=node2)
+                node2.val = 7
+                if a >= 100:
+                    sa += 1
+                sa += ovfcheck(i + i)
+                node1 = A(i)
+                i += 1
+        assert self.meta_interp(f, [20, 7]) == f(20, 7)
+            
+
 class TestOOtype(BasicTests, OOJitMixin):
 
     def test_oohash(self):
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
@@ -193,6 +193,8 @@
                 boxes = []
             def clone_if_mutable(self):
                 return self
+            def __eq__(self, other):
+                return isinstance(other, Storage) or isinstance(other, FakeDescr)
         loop.preamble.start_resumedescr = FakeDescr()
         optimize_loop_1(metainterp_sd, loop, ALL_OPTS_DICT)
         #
@@ -2990,8 +2992,20 @@
         jump(p8, p11, p26)
         """
         expected = """
-        [i34, i17, i22]
-        jump(i34, i17, i22)        
+        [p8, p11, i24, i19, p16, i21, i34]
+        i39 = getfield_gc(p8, descr=nextdescr)
+        i40 = int_ge(i39, i19)
+        guard_false(i40) []
+        i41 = getfield_gc(p16, descr=nextdescr)
+        i42 = int_mul(i39, i41)
+        i43 = int_add(i21, i42)
+        i44 = int_add(i39, 1)
+        setfield_gc(p8, i44, descr=nextdescr)
+        i45 = int_add_ovf(i34, i43)
+        guard_no_overflow() []
+        i46 = int_add_ovf(i34, i43)
+        guard_no_overflow() []
+        jump(p8, p11, i43, i19, p16, i21, i34)
         """
         self.optimize_loop(ops, expected)
 


More information about the Pypy-commit mailing list