[pypy-commit] pypy jit-limit_peeling: Only unrol if the peeled loop is shorter than the preamble. Add a limit_peeling parameter to control how much shorter.

hakanardo noreply at buildbot.pypy.org
Fri Aug 19 19:16:14 CEST 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-limit_peeling
Changeset: r46646:7fc5d9611d13
Date: 2011-08-19 19:20 +0200
http://bitbucket.org/pypy/pypy/changeset/7fc5d9611d13/

Log:	Only unrol if the peeled loop is shorter than the preamble. Add a
	limit_peeling parameter to control how much shorter.

diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -324,6 +324,7 @@
         class memory_manager:
             retrace_limit = 5
             max_retrace_guards = 15
+            limit_peeling = 0
 
 class Storage(compile.ResumeGuardDescr):
     "for tests."
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
@@ -205,6 +205,17 @@
             short = self.inline(inputargs, self.cloned_operations,
                                 loop.inputargs, short_inputargs,
                                 virtual_state)
+            if not virtual_state.contains_virtuals():
+                ops_in_loop = len(self.optimizer.newoperations)
+                ops_in_preamble = len(loop.preamble.operations) + 1
+                amount_saved = ((ops_in_preamble - ops_in_loop) * 100) / ops_in_preamble
+                th = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.limit_peeling
+                if amount_saved <= th:
+                    jumpop.initarglist(jump_args)
+                    loop.preamble.operations.append(jumpop)
+                    loop.operations = loop.preamble.operations
+                    loop.preamble.operations = None
+                    return
             
             loop.inputargs = inputargs
             args = [preamble_optimizer.getvalue(self.short_boxes.original(a)).force_box()\
diff --git a/pypy/jit/metainterp/optimizeopt/virtualstate.py b/pypy/jit/metainterp/optimizeopt/virtualstate.py
--- a/pypy/jit/metainterp/optimizeopt/virtualstate.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualstate.py
@@ -401,6 +401,12 @@
         for s in self.state:
             s.debug_print("    ", seen, bad)
 
+    def contains_virtuals(self):
+        for s in self.state:
+            if not isinstance(s, NotVirtualStateInfo):
+                return True
+        return False
+
 class VirtualStateAdder(resume.ResumeDataVirtualAdder):
     def __init__(self, optimizer):
         self.fieldboxes = {}
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
@@ -2637,6 +2637,25 @@
         assert self.meta_interp(f, [20, 10]) == f(20, 10)
         self.check_tree_loop_count(5)
 
+    def test_limit_peeling(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a'])
+
+        def f(n, limit):
+            myjitdriver.set_param('limit_peeling', limit)
+            sa = i = 0
+            a = n + 1
+            while i < n:
+                myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a)
+                sa += a * a
+                i += 1
+            return sa
+        assert self.meta_interp(f, [20, 0]) == f(20, 0)
+        self.check_tree_loop_count(2)
+        assert self.meta_interp(f, [20, 10]) == f(20, 10)
+        self.check_tree_loop_count(2)
+        assert self.meta_interp(f, [20, 20]) == f(20, 20)
+        self.check_tree_loop_count(1)
+
 
     def test_retrace_limit_with_extra_guards(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a',
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -63,7 +63,8 @@
                     backendopt=False, trace_limit=sys.maxint,
                     inline=False, loop_longevity=0, retrace_limit=5,
                     function_threshold=4,
-                    enable_opts=ALL_OPTS_NAMES, max_retrace_guards=15, **kwds):
+                    enable_opts=ALL_OPTS_NAMES, max_retrace_guards=15,
+                    limit_peeling=0, **kwds):
     from pypy.config.config import ConfigError
     translator = interp.typer.annotator.translator
     try:
@@ -87,6 +88,7 @@
         jd.warmstate.set_param_inlining(inline)
         jd.warmstate.set_param_loop_longevity(loop_longevity)
         jd.warmstate.set_param_retrace_limit(retrace_limit)
+        jd.warmstate.set_param_limit_peeling(limit_peeling)
         jd.warmstate.set_param_max_retrace_guards(max_retrace_guards)
         jd.warmstate.set_param_enable_opts(enable_opts)
     warmrunnerdesc.finish()
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -275,6 +275,11 @@
             if self.warmrunnerdesc.memory_manager:
                 self.warmrunnerdesc.memory_manager.max_retrace_guards = value
 
+    def set_param_limit_peeling(self, value):
+        if self.warmrunnerdesc:
+            if self.warmrunnerdesc.memory_manager:
+                self.warmrunnerdesc.memory_manager.limit_peeling = value
+
     def disable_noninlinable_function(self, greenkey):
         cell = self.jit_cell_at_key(greenkey)
         cell.dont_trace_here = True
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -299,6 +299,7 @@
               'loop_longevity': 1000,
               'retrace_limit': 5,
               'max_retrace_guards': 15,
+              'limit_peeling': 0,
               'enable_opts': 'all',
               }
 unroll_parameters = unrolling_iterable(PARAMETERS.items())


More information about the pypy-commit mailing list