[pypy-commit] pypy share-guard-info: an attempt at sharing guards

fijal noreply at buildbot.pypy.org
Thu Sep 17 19:14:24 CEST 2015


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: share-guard-info
Changeset: r79675:95a1828c06f1
Date: 2015-09-17 19:14 +0200
http://bitbucket.org/pypy/pypy/changeset/95a1828c06f1/

Log:	an attempt at sharing guards

diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -68,11 +68,13 @@
     the label
     """
     def __init__(self, start_label, operations, call_pure_results=None,
-                 enable_opts=None):
+                 enable_opts=None, origin_jitcode=None, origin_pc=0):
         self.start_label = start_label
         self.operations = operations
         self.call_pure_results = call_pure_results
         self.enable_opts = enable_opts
+        self.origin_jitcode = origin_jitcode
+        self.origin_pc = origin_pc
 
     def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
         from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer
@@ -80,19 +82,23 @@
         #assert not unroll
         opt = Optimizer(metainterp_sd, jitdriver_sd, optimizations)
         return opt.propagate_all_forward(self.start_label.getarglist(),
-            self.operations, self.call_pure_results)
+            self.operations, self.call_pure_results,
+            origin_jitcode=self.origin_jitcode, origin_pc=self.origin_pc)
 
 class BridgeCompileData(CompileData):
     """ This represents ops() with a jump at the end that goes to some
     loop, we need to deal with virtual state and inlining of short preamble
     """
     def __init__(self, start_label, operations, call_pure_results=None,
-                 enable_opts=None, inline_short_preamble=False):
+                 enable_opts=None, inline_short_preamble=False,
+                 origin_jitcode=None, origin_pc=0):
         self.start_label = start_label
         self.operations = operations
         self.call_pure_results = call_pure_results
         self.enable_opts = enable_opts
         self.inline_short_preamble = inline_short_preamble
+        self.origin_jitcode = origin_jitcode
+        self.origin_pc = origin_pc
 
     def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
         from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer
@@ -101,7 +107,8 @@
         return opt.optimize_bridge(self.start_label, self.operations,
                                    self.call_pure_results,
                                    self.inline_short_preamble,
-                                   self.box_names_memo)
+                                   self.box_names_memo,
+                                   self.origin_jitcode, self.origin_pc)
 
 class UnrolledLoopData(CompileData):
     """ This represents label() ops jump with extra info that's from the
@@ -675,10 +682,13 @@
 
 class ResumeGuardDescr(ResumeDescr):
     _attrs_ = ('rd_numb', 'rd_count', 'rd_consts', 'rd_virtuals',
-               'rd_frame_info_list', 'rd_pendingfields', 'status')
+               'rd_frame_info_list', 'rd_pendingfields', 'status',
+               'rd_origin_jitcode', 'rd_origin_pc')
     
     rd_numb = lltype.nullptr(NUMBERING)
     rd_count = 0
+    rd_origin_pc = 0
+    rd_origin_jitcode = None
     rd_consts = None
     rd_virtuals = None
     rd_frame_info_list = None
@@ -990,6 +1000,9 @@
     return resumedescr
 
 class ResumeFromInterpDescr(ResumeDescr):
+    rd_origin_jitcode = None
+    rd_origin_pc = 0
+    
     def __init__(self, original_greenkey):
         self.original_greenkey = original_greenkey
 
@@ -1042,11 +1055,15 @@
         data = BridgeCompileData(label, operations[:],
                                  call_pure_results=call_pure_results,
                                  enable_opts=enable_opts,
-                                 inline_short_preamble=inline_short_preamble)
+                                 inline_short_preamble=inline_short_preamble,
+                                 origin_jitcode=resumekey.rd_origin_jitcode,
+                                 origin_pc=resumekey.rd_origin_pc)
     else:
         data = SimpleCompileData(label, operations[:],
                                  call_pure_results=call_pure_results,
-                                 enable_opts=enable_opts)
+                                 enable_opts=enable_opts,
+                                 origin_jitcode=resumekey.rd_origin_jitcode,
+                                 origin_pc=resumekey.rd_origin_pc)
     try:
         info, newops = optimize_trace(metainterp_sd, jitdriver_sd,
                                       data, metainterp.box_names_memo)
diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -107,6 +107,8 @@
         self.last_guard_pos = -1
 
     def mark_last_guard(self, optimizer):
+        if optimizer.getlastop() is None:
+            return
         self.last_guard_pos = len(optimizer._newoperations) - 1
         assert self.get_last_guard(optimizer).is_guard()
 
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -497,7 +497,10 @@
             return CONST_0
 
     def propagate_all_forward(self, inputargs, ops, call_pure_results=None,
-                              rename_inputargs=True, flush=True):
+                              rename_inputargs=True, flush=True,
+                              origin_jitcode=None, origin_pc=0):
+        self.origin_jitcode = origin_jitcode
+        self.origin_pc = origin_pc
         if rename_inputargs:
             newargs = []
             for inparg in inputargs:
@@ -563,6 +566,14 @@
             op.setarg(i, arg)
         self.metainterp_sd.profiler.count(jitprof.Counters.OPT_OPS)
         if op.is_guard():
+            assert isinstance(op, GuardResOp)
+            if self.origin_jitcode is not None:
+                if (self.origin_jitcode is op.rd_frame_info_list.jitcode and
+                    self.origin_pc is op.rd_frame_info_list.pc):
+                    self.origin_jitcode = None
+                    self.origin_pc = 0
+                else:
+                    return # we optimize the guard
             self.metainterp_sd.profiler.count(jitprof.Counters.OPT_GUARDS)
             pendingfields = self.pendingfields
             self.pendingfields = None
@@ -573,7 +584,8 @@
             else:
                 guard_op = self.replace_op_with(op, op.getopnum())
                 if (self._last_guard_op and guard_op.getdescr() is None and
-                    guard_op.getopnum() != rop.GUARD_VALUE):
+                    guard_op.getopnum() != rop.GUARD_VALUE and
+                    not guard_op.same_guard_position(self._last_guard_op)):
                     op = self._copy_resume_data_from(guard_op,
                                                      self._last_guard_op)
                 else:
@@ -599,6 +611,8 @@
         guard_op.setdescr(descr)
         descr.store_final_boxes(guard_op, last_guard_op.getfailargs(),
                                 self.metainterp_sd)
+        descr.rd_origin_jitcode = guard_op.rd_frame_info_list.jitcode
+        descr.rd_origin_pc = guard_op.rd_frame_info_list.pc
         if guard_op.getopnum() == rop.GUARD_VALUE:
             guard_op = self._maybe_replace_guard_value(guard_op, descr)
         return guard_op
diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -223,12 +223,14 @@
         return label_vs
 
     def optimize_bridge(self, start_label, operations, call_pure_results,
-                        inline_short_preamble, box_names_memo):
+                        inline_short_preamble, box_names_memo,
+                        origin_jitcode=None, origin_pc=0):
         self._check_no_forwarding([start_label.getarglist(),
                                     operations])
         info, ops = self.optimizer.propagate_all_forward(
             start_label.getarglist()[:], operations[:-1],
-            call_pure_results, True)
+            call_pure_results, True, origin_jitcode=origin_jitcode,
+            origin_pc=origin_pc)
         jump_op = operations[-1]
         cell_token = jump_op.getdescr()
         assert isinstance(cell_token, JitCellToken)
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -378,6 +378,13 @@
         newop.rd_frame_info_list = self.rd_frame_info_list
         return newop
 
+    def same_guard_position(self, other):
+        assert isinstance(other, GuardResOp)
+        frame_info1 = self.rd_frame_info_list
+        frame_info2 = other.rd_frame_info_list
+        return (frame_info1.jitcode is frame_info2.jitcode and
+                frame_info1.pc == frame_info2.pc)
+
 # ===========
 # type mixins
 # ===========
diff --git a/rpython/jit/metainterp/test/test_loop.py b/rpython/jit/metainterp/test/test_loop.py
--- a/rpython/jit/metainterp/test/test_loop.py
+++ b/rpython/jit/metainterp/test/test_loop.py
@@ -1090,5 +1090,23 @@
         self.meta_interp(f, [30])
         self.check_trace_count(3)
 
+    def test_sharing_guards(self):
+        driver = JitDriver(greens = [], reds = 'auto')
+        
+        def f(i):
+            s = 0
+            while i > 0:
+                driver.jit_merge_point()
+                if s > 100:
+                    raise Exception
+                if s > 9:
+                    s += 1 # bridge
+                s += 1
+                i -= 1
+
+        self.meta_interp(f, [15])
+        # one guard_false got removed
+        self.check_resops(guard_false=4, guard_true=5)
+
 class TestLLtype(LoopTest, LLJitMixin):
     pass


More information about the pypy-commit mailing list