[pypy-commit] pypy optresult-unroll: a first go at adding proper operations to label args, not sure what I think about this go

fijal noreply at buildbot.pypy.org
Sun Jul 12 20:23:11 CEST 2015


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult-unroll
Changeset: r78531:078fc2be0b85
Date: 2015-07-12 20:23 +0200
http://bitbucket.org/pypy/pypy/changeset/078fc2be0b85/

Log:	a first go at adding proper operations to label args, not sure what
	I think about this go

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
@@ -16,8 +16,8 @@
             ('rewrite', OptRewrite),
             ('virtualize', OptVirtualize),
             ('string', OptString),
-            ('earlyforce', OptEarlyForce),
             ('pure', OptPure),
+            #('earlyforce', OptEarlyForce), # XXX why do we have this hack?
             ('heap', OptHeap),
             ('unroll', None)]
 # no direct instantiation of unroll
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -58,7 +58,9 @@
             op = optimizer.get_box_replacement(op)
             opnum = OpHelpers.getfield_for_descr(descr)
             getfield_op = ResOperation(opnum, [structbox], descr=descr)
-            shortboxes.add_potential(op, getfield_op)
+            if not op.is_constant():
+                # XXXX why?
+                shortboxes.add_potential(op, getfield_op)
         return
         for structvalue in self._cached_fields_getfield_op.keys():
             op = self._cached_fields_getfield_op[structvalue]
@@ -151,7 +153,13 @@
         return op.getarg(1)
 
     def _getfield(self, opinfo, descr, optheap):
-        return opinfo.getfield(descr, optheap)
+        from rpython.jit.metainterp.optimizeopt.unroll import PreambleOp
+        
+        res = opinfo.getfield(descr, optheap)
+        if isinstance(res, PreambleOp):
+            res = optheap.optimizer.force_op_from_preamble(res)
+            opinfo._fields[descr.get_index()] == res
+        return res
 
     def force_lazy_setfield(self, optheap, descr, can_cache=True):
         op = self._lazy_setfield
@@ -180,7 +188,8 @@
 
     def _setfield(self, op, opinfo, optheap):
         arg = optheap.get_box_replacement(op.getarg(1))
-        opinfo.setfield(op.getdescr(), op, arg, optheap, self)
+        struct = optheap.get_box_replacement(op.getarg(0))
+        opinfo.setfield(op.getdescr(), struct, arg, optheap, self)
 
 class ArrayCachedField(CachedField):
     def __init__(self, index):
@@ -531,6 +540,7 @@
     optimize_GETFIELD_GC_PURE_F = optimize_GETFIELD_GC_PURE_I
 
     def optimize_SETFIELD_GC(self, op):
+        self.setfield(op)
         #opnum = OpHelpers.getfield_pure_for_descr(op.getdescr())
         #if self.has_pure_result(opnum, [op.getarg(0)],
         #                        op.getdescr()):
@@ -538,6 +548,8 @@
         #             (op.getdescr().repr_of_descr()))
         #    raise BogusImmutableField
         #
+
+    def setfield(self, op):
         cf = self.field_cache(op.getdescr())
         cf.do_setfield(self, op)
 
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
@@ -51,6 +51,9 @@
     def getstrlen(self, op, string_optimizer, mode, create_ops=True):
         return None
 
+    def make_guards(self, op, short):
+        pass # XXX
+
     
 class NonNullPtrInfo(PtrInfo):
     _attrs_ = ('last_guard_pos',)
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
@@ -302,6 +302,17 @@
     def force_box(self, op):
         op = self.get_box_replacement(op)
         info = op.get_forwarded()
+        if self.optunroll and self.optunroll.ops_to_import:
+            # XXX hack, use stuff on info somehow, a bit on the hard side
+            #     but doable :-)
+            try:
+                preamble_op = self.optunroll.ops_to_import[op]
+            except KeyError:
+                pass
+            else:
+                self.optunroll.short.append(preamble_op)
+                self.optunroll.extra_label_args.append(op)
+                del self.optunroll.ops_to_import[op]
         if info is not None:
             return info.force_box(op, self)
         return op
diff --git a/rpython/jit/metainterp/optimizeopt/shortpreamble.py b/rpython/jit/metainterp/optimizeopt/shortpreamble.py
--- a/rpython/jit/metainterp/optimizeopt/shortpreamble.py
+++ b/rpython/jit/metainterp/optimizeopt/shortpreamble.py
@@ -1,5 +1,6 @@
 
-from rpython.jit.metainterp.resoperation import ResOperation, OpHelpers
+from rpython.jit.metainterp.resoperation import ResOperation, OpHelpers,\
+     AbstractInputArg
 from rpython.jit.metainterp.history import Const
 
 
@@ -29,13 +30,17 @@
         self.short_boxes[op] = short_op
 
     def produce_short_preamble_op(self, op, preamble_op):
-        for arg in op.getarglist():
-            if isinstance(arg, Const):
-                pass
-            elif arg in self.ops_used:
-                pass
-            else:
-                return # can't produce
+        if isinstance(op, AbstractInputArg):
+            if op not in self.ops_used:
+                return
+        else:
+            for arg in op.getarglist():
+                if isinstance(arg, Const):
+                    pass
+                elif arg in self.ops_used:
+                    pass
+                else:
+                    return # can't produce
         if op in self.short_boxes:
             opnum = OpHelpers.same_as_for_type(op.type)
             same_as_op = ResOperation(opnum, [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
@@ -450,8 +450,9 @@
         preamble.inputargs = start_state.renamed_inputargs
         start_label = ResOperation(rop.LABEL, start_state.renamed_inputargs)
         preamble.operations = [start_label] + preamble_ops
-        emit_end_label = ResOperation(rop.LABEL, start_state.end_args)
-        loop.inputargs = start_state.end_args
+        inputargs = start_state.end_args + loop_info.extra_label_args
+        emit_end_label = ResOperation(rop.LABEL, inputargs)
+        loop.inputargs = inputargs
         loop.operations = [emit_end_label] + ops
         return Info(preamble, loop_info.short_preamble)
 
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
@@ -16,6 +16,16 @@
 
 
 class PreambleOp(AbstractResOp):
+    """ An operations that's only found in preamble and not
+    in the list of constructed operations. When encountered (can be found
+    either in pure ops or heap ops), it must be put in inputargs as well
+    as short preamble (together with corresponding guards). Extra_ops is
+    for extra things to be found in the label, for now only inputargs
+    of the preamble that have to be propagated further.
+
+    See force_op_from_preamble for details how the extra things are put.
+    """
+    
     def __init__(self, op, preamble_op, info):
         self.op = op
         self.preamble_op = preamble_op
@@ -57,6 +67,7 @@
     distinction anymore)"""
 
     inline_short_preamble = True
+    ops_to_import = None
 
     def __init__(self, metainterp_sd, jitdriver_sd, optimizations):
         self.optimizer = UnrollableOptimizer(metainterp_sd, jitdriver_sd,
@@ -84,19 +95,23 @@
 
     def optimize_peeled_loop(self, start_label, end_jump, ops, state):
         self.short = []
+        self.extra_label_args = []
         self._check_no_forwarding([[start_label, end_jump], ops])
         self.import_state(start_label, state)
         self.optimizer.propagate_all_forward(start_label.getarglist()[:], ops,
                                              rename_inputargs=False)
         jump_args = [self.get_box_replacement(op)
                      for op in end_jump.getarglist()]
+        args_from_extras = [self.get_box_replacement(op) for op in
+                            self.extra_label_args]
         jump_args = state.virtual_state.make_inputargs(jump_args,
-                                                       self.optimizer,
-                                                       force_boxes=True)
+                    self.optimizer, force_boxes=True) + args_from_extras
+        
         self.flush()
         jump_op = ResOperation(rop.JUMP, jump_args)
         self.optimizer._newoperations.append(jump_op)
-        return (UnrollInfo(self.make_short_preamble(start_label.getarglist())),
+        return (UnrollInfo(self.make_short_preamble(start_label.getarglist()),
+                           self.extra_label_args),
                 self.optimizer._newoperations)
 
     def make_short_preamble(self, args):
@@ -264,17 +279,24 @@
     def import_state(self, targetop, exported_state):
         # the mapping between input args (from old label) and what we need
         # to actually emit
+        self.ops_to_import = {}
         for source, target in exported_state.inputarg_mapping:
             if source is not target:
                 source.set_forwarded(target)
         # import the optimizer state, starting from boxes that can be produced
         # by short preamble
         for op, preamble_op in exported_state.short_boxes.items():
+            self.ops_to_import[op] = preamble_op
             if preamble_op.is_always_pure():
-                self.pure(op.getopnum(), PreambleOp(op, preamble_op,
-                                                self.optimizer.getinfo(op)))
+                self.pure(op.getopnum(), op)
             else:
-                yyy
+                assert preamble_op.is_getfield()
+                optheap = self.optimizer.optheap
+                if optheap is None:
+                    continue
+                opinfo = self.optimizer.ensure_ptr_info_arg0(preamble_op)
+                assert not opinfo.is_virtual()
+                opinfo._fields[preamble_op.getdescr().get_index()] = op
 
         for op, info in exported_state.exported_infos.iteritems():
             self.optimizer.setinfo_from_preamble(op, info)
@@ -714,9 +736,11 @@
     """ A state after optimizing the peeled loop, contains the following:
 
     * short_preamble - list of operations that go into short preamble
+    * extra_label_args - list of extra operations that go into the label
     """
-    def __init__(self, short_preamble):
+    def __init__(self, short_preamble, extra_label_args):
         self.short_preamble = short_preamble
+        self.extra_label_args = extra_label_args
             
 class ExportedState(LoopInfo):
     """ Exported state consists of a few pieces of information:
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -535,8 +535,9 @@
 class JitHintError(Exception):
     """Inconsistency in the JIT hints."""
 
+# XXX earlyforce before pure
 ENABLE_ALL_OPTS = (
-    'intbounds:rewrite:virtualize:string:earlyforce:pure:heap:unroll')
+    'intbounds:rewrite:virtualize:string:pure:heap:unroll')
 
 PARAMETER_DOCS = {
     'threshold': 'number of times a loop has to run for it to become hot',


More information about the pypy-commit mailing list