[pypy-commit] pypy optresult-unroll: a completely different approach

fijal noreply at buildbot.pypy.org
Mon Jul 6 14:57:19 CEST 2015


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult-unroll
Changeset: r78456:cbf2d99e2ae8
Date: 2015-07-06 14:57 +0200
http://bitbucket.org/pypy/pypy/changeset/cbf2d99e2ae8/

Log:	a completely different approach

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
@@ -24,6 +24,37 @@
     raise SwitchToBlackhole(Counters.ABORT_BRIDGE)
 
 
+class LoopCompileData(object):
+    """ An object that accumulates all of the necessary info for
+    the optimization phase, but does not actually have any other state
+
+    This is the case of label() ops label()
+    """
+    def __init__(self, start_label, end_label, operations):
+        self.start_label = start_label
+        self.end_label = end_label
+        assert start_label.getopnum() == rop.LABEL
+        assert end_label.getopnum() == rop.LABEL
+        self.operations = operations
+
+    def forget_optimization_info(self):
+        for arg in self.start_label.getarglist():
+            arg.set_forwarded(None)
+        for op in self.operations:
+            op.set_forwarded(None)
+
+    def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll):
+        from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer
+
+        if unroll:
+            opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations)
+            return opt.optimize_preamble(self.start_label, self.end_label,
+                                         self.operations)
+            xxx
+        else:
+            xxx
+
+
 def show_procedures(metainterp_sd, procedure=None, error=None):
     # debugging
     if option and (option.view or option.viewloops):
@@ -104,10 +135,8 @@
 # ____________________________________________________________
 
 
-def compile_loop(metainterp, greenkey, start,
-                 inputargs, jumpargs,
-                 full_preamble_needed=True,
-                 try_disabling_unroll=False):
+def compile_loop(metainterp, greenkey, start, inputargs, jumpargs,
+                 full_preamble_needed=True, try_disabling_unroll=False):
     """Try to compile a new procedure by closing the current history back
     to the first operation.
     """
diff --git a/rpython/jit/metainterp/optimizeopt/__init__.py b/rpython/jit/metainterp/optimizeopt/__init__.py
--- a/rpython/jit/metainterp/optimizeopt/__init__.py
+++ b/rpython/jit/metainterp/optimizeopt/__init__.py
@@ -4,7 +4,6 @@
 from rpython.jit.metainterp.optimizeopt.virtualize import OptVirtualize
 from rpython.jit.metainterp.optimizeopt.heap import OptHeap
 from rpython.jit.metainterp.optimizeopt.vstring import OptString
-from rpython.jit.metainterp.optimizeopt.unroll import optimize_unroll
 from rpython.jit.metainterp.optimizeopt.simplify import OptSimplify
 from rpython.jit.metainterp.optimizeopt.pure import OptPure
 from rpython.jit.metainterp.optimizeopt.earlyforce import OptEarlyForce
@@ -47,26 +46,17 @@
 
     return optimizations, unroll
 
-def optimize_trace(metainterp_sd, jitdriver_sd, loop, enable_opts,
-                   inline_short_preamble=True, start_state=None,
-                   export_state=True):
+def optimize_trace(metainterp_sd, jitdriver_sd, compile_data):
     """Optimize loop.operations to remove internal overheadish operations.
     """
-
     debug_start("jit-optimize")
+    #inputargs = start_label.getarglist()
     try:
-        loop.logops = metainterp_sd.logger_noopt.log_loop(loop.inputargs,
-                                                          loop.operations)
-        optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts)
-        if unroll:
-            return optimize_unroll(metainterp_sd, jitdriver_sd, loop,
-                                   optimizations,
-                                   inline_short_preamble, start_state,
-                                   export_state)
-        else:
-            optimizer = Optimizer(metainterp_sd, jitdriver_sd, loop,
-                                  optimizations)
-            optimizer.propagate_all_forward()
+        #logops = metainterp_sd.logger_noopt.log_loop(inputargs, operations)
+        optimizations, unroll = build_opt_chain(metainterp_sd,
+                                                compile_data.enable_opts)
+        return compile_data.optimize(metainterp_sd, jitdriver_sd,
+                                     optimizations, unroll)
     finally:
         debug_stop("jit-optimize")
 
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
@@ -211,14 +211,10 @@
 
 class Optimizer(Optimization):
 
-    exporting_state = False
-    emitting_dissabled = False
-
-    def __init__(self, metainterp_sd, jitdriver_sd, loop, optimizations=None):
+    def __init__(self, metainterp_sd, jitdriver_sd, optimizations=None):
         self.metainterp_sd = metainterp_sd
         self.jitdriver_sd = jitdriver_sd
         self.cpu = metainterp_sd.cpu
-        self.loop = loop
         self.logops = LogOperations(metainterp_sd, False)
         self.interned_refs = self.cpu.ts.new_ref_dict()
         self.interned_ints = {}
@@ -234,14 +230,15 @@
         self.optheap = None
         self.optearlyforce = None
         self.optunroll = None
-        # the following two fields is the data kept for unrolling,
-        # those are the operations that can go to the short_preamble
-        if loop is not None:
-            self.call_pure_results = loop.call_pure_results
 
         self.set_optimizations(optimizations)
         self.setup()
 
+    def init_inparg_dict_from(self, lst):
+        self.inparg_dict = {}
+        for box in lst:
+            self.inparg_dict[box] = None
+
     def set_optimizations(self, optimizations):
         if optimizations:
             self.first_optimization = optimizations[0]
@@ -442,18 +439,13 @@
         else:
             return CONST_0
 
-    def propagate_all_forward(self, clear=True, create_inp_args=True):
-        if clear:
-            self.clear_newoperations()
-        if create_inp_args:
-            self.inparg_dict = {}
-            for op in self.loop.inputargs:
-                self.inparg_dict[op] = None
-        for op in self.loop.operations:
+    def propagate_all_forward(self, inputargs, ops, create_inp_args=True):
+        self.init_inparg_dict_from(inputargs)
+        for op in ops:
             self._really_emitted_operation = None
             self.first_optimization.propagate_forward(op)
-        self.loop.operations = self.get_newoperations()
-        self.loop.quasi_immutable_deps = self.quasi_immutable_deps
+        #self.loop.operations = self.get_newoperations()
+        #self.loop.quasi_immutable_deps = self.quasi_immutable_deps
         # accumulate counters
         self.resumedata_memo.update_counters(self.metainterp_sd.profiler)
 
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_unroll.py b/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
@@ -3,10 +3,11 @@
 """
 
 from rpython.jit.metainterp.optimizeopt.test.test_util import BaseTest,\
-     LLtypeMixin, FakeMetaInterpStaticData
-from rpython.jit.metainterp.history import (TreeLoop, AbstractDescr, ConstInt,
+     LLtypeMixin
+from rpython.jit.metainterp.history import (TreeLoop, ConstInt,
                                             JitCellToken, TargetToken)
 from rpython.jit.metainterp.resoperation import rop, ResOperation
+from rpython.jit.metainterp.compile import LoopCompileData
 from rpython.jit.metainterp.optimizeopt.virtualstate import \
      NotVirtualStateInfo, LEVEL_CONSTANT, LEVEL_UNKNOWN
 
@@ -18,7 +19,6 @@
     
     def optimize(self, ops):
         loop = self.parse(ops, postprocess=self.postprocess)
-        metainterp_sd = FakeMetaInterpStaticData(self.cpu)
         self.add_guard_future_condition(loop)
         operations =  loop.operations
         jumpop = operations[-1]
@@ -34,11 +34,10 @@
         token = JitCellToken()
         start_label = ResOperation(rop.LABEL, inputargs, descr=TargetToken(token))
         stop_label = ResOperation(rop.LABEL, jump_args, descr=token)
-        preamble.operations = [start_label] + operations + [stop_label]
-        start_state = self._do_optimize_loop(preamble, None,
-                                             export_state=True)
-        vs = preamble.operations[-1].getdescr().virtual_state
-        return start_state, vs, loop, preamble
+        compile_data = LoopCompileData(start_label, stop_label, operations)
+        start_state, newops = self._do_optimize_loop(compile_data)
+        preamble.operations = newops
+        return start_state, loop, preamble
 
 class TestUnroll(BaseTestUnroll):
     def test_simple(self):
@@ -48,7 +47,8 @@
         guard_value(i1, 1) []
         jump(i1)
         """
-        es, vs, loop, preamble = self.optimize(loop)
+        es, loop, preamble = self.optimize(loop)
+        vs = es.virtual_state
         assert isinstance(vs.state[0], NotVirtualStateInfo)
         # the virtual state is constant, so we don't need to have it in
         # inputargs
@@ -65,8 +65,9 @@
         i1 = int_add(i0, 1)
         jump(i0)
         """
-        es, vs, loop, preamble = self.optimize(loop)
+        es, loop, preamble = self.optimize(loop)
+        vs = es.virtual_state
         assert isinstance(vs.state[0], NotVirtualStateInfo)
         assert vs.state[0].level == LEVEL_UNKNOWN
-        op = preamble.operations[1]
+        op = preamble.operations[0]
         assert es.short_boxes == {op: op}
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -405,15 +405,11 @@
         assert equaloplists(optimized.operations,
                             expected.operations, False, remap, text_right)
 
-    def _do_optimize_loop(self, loop, call_pure_results, start_state=None,
-                          export_state=False):
+    def _do_optimize_loop(self, compile_data, call_pure_results=None):
         from rpython.jit.metainterp.optimizeopt import optimize_trace
         from rpython.jit.metainterp.optimizeopt.util import args_dict
 
-        self.loop = loop
-        operations = loop.operations
-        inputargs = loop.inputargs
-        loop.call_pure_results = args_dict()
+        # XXX
         if call_pure_results is not None:
             for k, v in call_pure_results.items():
                 loop.call_pure_results[list(k)] = v
@@ -423,17 +419,14 @@
         if hasattr(self, 'callinfocollection'):
             metainterp_sd.callinfocollection = self.callinfocollection
         #
-        state = optimize_trace(metainterp_sd, None, loop,
-                              self.enable_opts,
-                              start_state=start_state,
-                              export_state=export_state)
-        compile.forget_optimization_info(operations)
-        compile.forget_optimization_info(inputargs)
+        compile_data.enable_opts = self.enable_opts
+        state = optimize_trace(metainterp_sd, None, compile_data)
+        compile_data.forget_optimization_info()
         return state
 
     def unroll_and_optimize(self, loop, call_pure_results=None):
+        xxx
         metainterp_sd = FakeMetaInterpStaticData(self.cpu)
-        logops = LogOperations(metainterp_sd, False)
         self.add_guard_future_condition(loop)
         operations =  loop.operations
         jumpop = operations[-1]
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
@@ -13,15 +13,6 @@
 from rpython.rlib.debug import debug_print, debug_start, debug_stop
 
 
-# FIXME: Introduce some VirtualOptimizer super class instead
-
-def optimize_unroll(metainterp_sd, jitdriver_sd, loop, optimizations,
-                    inline_short_preamble=True, start_state=None,
-                    export_state=True):
-    opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, loop, optimizations)
-    opt.inline_short_preamble = inline_short_preamble
-    return opt.propagate_all_forward(start_state, export_state)
-
 
 class PreambleOp(AbstractResOp):
     def __init__(self, op, info):
@@ -36,18 +27,6 @@
 
 
 class UnrollableOptimizer(Optimizer):
-    def setup(self):
-        self.importable_values = {}
-        self.emitting_dissabled = False
-        self.emitted_guards = 0
-
-    def emit_operation(self, op):
-        if self.emitting_dissabled:
-            return
-        if op.is_guard():
-            self.emitted_guards += 1 # FIXME: can we use counter in self._emit_operation?
-        self._emit_operation(op)
-
     def force_op_from_preamble(self, preamble_op):
         op = preamble_op.op
         self.optunroll.short.append(op)
@@ -63,52 +42,27 @@
 
     inline_short_preamble = True
 
-    def __init__(self, metainterp_sd, jitdriver_sd, loop, optimizations):
+    def __init__(self, metainterp_sd, jitdriver_sd, optimizations):
         self.optimizer = UnrollableOptimizer(metainterp_sd, jitdriver_sd,
-                                             loop, optimizations)
+                                             optimizations)
         self.optimizer.optunroll = self
-        self.boxes_created_this_iteration = None
 
     def get_virtual_state(self, args):
         modifier = VirtualStateConstructor(self.optimizer)
         return modifier.get_virtual_state(args)
 
-    def propagate_all_forward(self, starting_state, export_state=True):
-        self.optimizer.exporting_state = export_state
-        loop = self.optimizer.loop
-        self.optimizer.clear_newoperations()
-        for op in loop.operations:
-            assert op.get_forwarded() is None
-        for op in loop.inputargs:
-            assert op.get_forwarded() is None
-
-        start_label = loop.operations[0]
-        if start_label.getopnum() == rop.LABEL:
-            loop.operations = loop.operations[1:]
-            # We need to emit the label op before import_state() as emitting it
-            # will clear heap caches
-            self.optimizer.send_extra_operation(start_label)
-        else:
-            start_label = None
-
-        patchguardop = None
-        if len(loop.operations) > 1:
-            patchguardop = loop.operations[-2]
-            if patchguardop.getopnum() != rop.GUARD_FUTURE_CONDITION:
-                patchguardop = None
-
-        jumpop = loop.operations[-1]
-        if jumpop.getopnum() == rop.JUMP or jumpop.getopnum() == rop.LABEL:
-            loop.operations = loop.operations[:-1]
-        else:
-            jumpop = None
-
-        self.import_state(start_label, starting_state)
-        self.optimizer.inparg_dict = {}
-        for box in start_label.getarglist():
-            self.optimizer.inparg_dict[box] = None
-        self.optimizer.propagate_all_forward(clear=False, create_inp_args=False)
-
+    def _check_no_forwarding(self, lsts):
+        for lst in lsts:
+            for op in lst:
+                assert op.get_forwarded() is None
+        assert not self.optimizer._newoperations
+    
+    def optimize_preamble(self, start_label, end_label, ops):
+        self._check_no_forwarding([[start_label, end_label], ops])
+        self.optimizer.propagate_all_forward(start_label.getarglist(), ops)
+        exported_state = self.export_state(start_label, end_label)
+        return exported_state, self.optimizer._newoperations
+        # WTF is the rest of this function
         if not jumpop:
             return
 
@@ -183,7 +137,7 @@
                     self.optimizer.send_extra_operation(stop_label)
                     loop.operations = self.optimizer.get_newoperations()
                     return None
-            final_state = self.export_state(stop_label)
+            final_state = self.export_state(start_label, stop_label)
         else:
             final_state = None
         loop.operations.append(stop_label)
@@ -200,19 +154,16 @@
         return stop_target.targeting_jitcell_token is start_target.targeting_jitcell_token
 
 
-    def export_state(self, targetop):
-        original_jump_args = targetop.getarglist()
-        label_op = self.optimizer.loop.operations[0]
-        jump_args = [self.get_box_replacement(a) for a in original_jump_args]
-        virtual_state = self.get_virtual_state(jump_args)
-        target_token = targetop.getdescr()
-        assert isinstance(target_token, TargetToken)
-        target_token.virtual_state = virtual_state
+    def export_state(self, start_label, end_label):
+        original_label_args = end_label.getarglist()
+        end_args = [self.get_box_replacement(a) for a in original_label_args]
+        virtual_state = self.get_virtual_state(end_args)
         sb = ShortBoxes()
-        sb.create_short_boxes(self.optimizer, jump_args)
-        inparg_mapping = [(label_op.getarg(i), jump_args[i])
-                          for i in range(len(jump_args))]
-        return ExportedState(inparg_mapping, [], sb.short_boxes)
+        sb.create_short_boxes(self.optimizer, end_args)
+        inparg_mapping = [(start_label.getarg(i), end_args[i])
+                          for i in range(len(end_args)) if
+                          start_label.getarg(i) is not end_args[i]]
+        return ExportedState(inparg_mapping, virtual_state, [], sb.short_boxes)
 
 
         inputargs = virtual_state.make_inputargs(jump_args, self.optimizer)
@@ -297,6 +248,8 @@
         # think about it, it seems to be just for consts
         #for source, target in exported_state.inputarg_setup_ops:
         #    source.set_forwarded(target)
+        for source, target in exported_state.inputarg_mapping:
+            source.set_forwarded(target)
 
         for op, preamble_op in exported_state.short_boxes.iteritems():
             if preamble_op.is_always_pure():
@@ -709,7 +662,9 @@
     * short boxes - a mapping op -> preamble_op
     """
     
-    def __init__(self, inputarg_mapping, exported_infos, short_boxes):
+    def __init__(self, inputarg_mapping, virtual_state, exported_infos,
+                 short_boxes):
         self.inputarg_mapping = inputarg_mapping
+        self.virtual_state = virtual_state
         self.exported_infos = exported_infos
         self.short_boxes = short_boxes


More information about the pypy-commit mailing list