Author: Maciej Fijalkowski <[email protected]>
Branch: optresult-unroll
Changeset: r78575:8a00142bfe8a
Date: 2015-07-17 11:45 +0200
http://bitbucket.org/pypy/pypy/changeset/8a00142bfe8a/

Log:    dance around to the music

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
@@ -30,6 +30,7 @@
 
 class Optimization(object):
     next_optimization = None
+    potential_extra_ops = None
 
     def __init__(self):
         pass # make rpython happy
@@ -302,16 +303,15 @@
     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 :-)
+        if self.optunroll and self.optunroll.potential_extra_ops:
+            # XXX hack
             try:
-                self.optunroll.ops_to_import[op]
+                 preamble_op = self.optunroll.potential_extra_ops.popitem(op)
             except KeyError:
                 pass
             else:
-                self.optunroll.extra_label_args.append(op)
-                del self.optunroll.ops_to_import[op]
+                sb = self.optunroll.short_preamble_producer
+                sb.add_preamble_op(op, preamble_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
@@ -33,8 +33,17 @@
         #
         for op, (getfield_op, preamble_op) in 
self.produced_short_boxes.iteritems():
             if getfield_op is not placeholder:
-                short_boxes.append((op, preamble_op))
-        return short_boxes + self.const_short_boxes
+                if getfield_op is None:
+                    short_boxes.append((op, None, preamble_op))
+                else:
+                    short_boxes.append((op, getfield_op.getarg(0), 
preamble_op))
+        for op, getfield_op in self.const_short_boxes:
+            preamble_arg = self.produce_arg(getfield_op.getarg(0))
+            if preamble_arg is not None:
+                short_boxes.append((op, getfield_op.getarg(0),
+                    getfield_op.copy_and_change(getfield_op.getopnum(),
+                                                [preamble_arg])))
+        return short_boxes
 
     def produce_short_inputargs(self):
         return self.short_inputargs
@@ -53,7 +62,7 @@
         if sop:
             preamble_arg = self.produce_arg(sop.getarg(0))
             if preamble_arg is None:
-                return False
+                return None
             preamble_op = ResOperation(sop.getopnum(), [preamble_arg],
                                        descr=sop.getdescr())
         else:
@@ -61,11 +70,11 @@
             for arg in op.getarglist():
                 newarg = self.produce_arg(arg)
                 if newarg is None:
-                    return False
+                    return None
                 arglist.append(newarg)
             preamble_op = op.copy_and_change(op.getopnum(), args=arglist)
         self.produced_short_boxes[op] = (sop, preamble_op)
-        return True
+        return preamble_op
 
     def add_pure_op(self, op):
         assert not self.potential_ops.get(op, None)
@@ -84,16 +93,24 @@
 empty_info = EmptyInfo()
 
 class ShortPreambleBuilder(object):
-    def __init__(self, short_boxes, short_inputargs, exported_infos):
+    def __init__(self, short_boxes, short_inputargs, exported_infos,
+                 optimizer=None):
         self.producable_ops = {}
-        for op, preamble_op in short_boxes:
+        for op, sop, preamble_op in short_boxes:
             self.producable_ops[op] = preamble_op
-            preamble_op.set_forwarded(exported_infos.get(op, empty_info))
+            if isinstance(op, Const):
+                info = optimizer.getinfo(op)
+            else:
+                info = exported_infos[op]
+                if info is None:
+                    info = empty_info
+            preamble_op.set_forwarded(info)
         self.short = []
         self.used_boxes = []
+        self.short_preamble_jump = []
         self.short_inputargs = short_inputargs
 
-    def use_box(self, box):
+    def use_box(self, box, optimizer=None):
         preamble_op = self.producable_ops.get(box, None)
         if preamble_op is None:
             return
@@ -104,16 +121,25 @@
             elif arg.get_forwarded() is None:
                 pass
             else:
-                xxx
+                self.short.append(arg)
+                info = arg.get_forwarded()
+                if info is not empty_info:
+                    info.make_guards(arg, self.short)
+                arg.set_forwarded(None)
+                self.force_info_from(arg)
         self.short.append(preamble_op)
         info = preamble_op.get_forwarded()
+        preamble_op.set_forwarded(None)
         if info is not empty_info:
             info.make_guards(preamble_op, self.short)
-            if info.is_constant():
-                return
-        self.used_boxes.append(preamble_op)
+        if optimizer is not None:
+            optimizer.setinfo_from_preamble(box, info)
+
+    def add_preamble_op(self, op, preamble_op):
+        self.used_boxes.append(op)
+        self.short_preamble_jump.append(preamble_op)        
 
     def build_short_preamble(self):
         label_op = ResOperation(rop.LABEL, self.short_inputargs[:])
-        jump_op = ResOperation(rop.JUMP, self.used_boxes)
+        jump_op = ResOperation(rop.JUMP, self.short_preamble_jump)
         return [label_op] + self.short + [jump_op]
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py 
b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -191,7 +191,7 @@
         short = """
         [i2]
         p3 = cast_int_to_ptr(i2)
-        #jump(i2) <- think about it
+        jump()
         """
         self.optimize_loop(ops, expected, expected_short=short)
 
@@ -450,7 +450,7 @@
         [i0]
         i1 = int_is_true(i0)
         guard_value(i1, 1) []
-        #jump(i0) <- xxx
+        jump()
         """
         self.optimize_loop(ops, expected, preamble, expected_short=short)
 
@@ -851,7 +851,8 @@
         p2sub = new_with_vtable(descr=nodesize2)
         setfield_gc(p2sub, i1, descr=valuedescr)
         setfield_gc(p2, p2sub, descr=nextdescr)
-        jump(i1, p2, p2sub)
+        i3 = same_as(i1)
+        jump(i1, p2, i3)
         """
         expected = """
         [i1, p2, i3]
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
@@ -214,3 +214,17 @@
         # both getfields are available as
         # well as getfield_gc_pure
         
+    def test_p123_anti_nested(self):
+        loop = """
+        [i1, p2, p3]
+        p3sub = getfield_gc_r(p3, descr=nextdescr)
+        i3 = getfield_gc_i(p3sub, descr=valuedescr)
+        escape_n(i3)
+        p1 = new_with_vtable(descr=nodesize)
+        p2sub = new_with_vtable(descr=nodesize2)
+        setfield_gc(p2sub, i1, descr=valuedescr)
+        setfield_gc(p2, p2sub, descr=nextdescr)
+        jump(i1, p1, p2)
+        """
+        es, loop, preamble = self.optimize(loop)
+        xxx
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
@@ -27,10 +27,9 @@
     See force_op_from_preamble for details how the extra things are put.
     """
     
-    def __init__(self, op, preamble_op, info):
+    def __init__(self, op, preamble_op):
         self.op = op
         self.preamble_op = preamble_op
-        self.info = info
 
     def getarg(self, i):
         return self.op.getarg(i)
@@ -42,10 +41,8 @@
 class UnrollableOptimizer(Optimizer):
     def force_op_from_preamble(self, preamble_op):
         op = preamble_op.op
-        self.optunroll.short.append(preamble_op.preamble_op)
-        if preamble_op.info:
-            self.setinfo_from_preamble(op, preamble_op.info)
-            preamble_op.info.make_guards(op, self.optunroll.short)
+        self.optunroll.short_preamble_producer.use_box(op, self)
+        self.potential_extra_ops[op] = preamble_op
         return op
 
     def setinfo_from_preamble(self, op, preamble_info):
@@ -108,29 +105,36 @@
         return exported_state, self.optimizer._newoperations
 
     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.potential_extra_ops = {}
         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) + args_from_extras
+                                    self.optimizer, force_boxes=True)
+        jump_args += self.inline_short_preamble(jump_args)
         
         jump_op = ResOperation(rop.JUMP, jump_args)
         self.optimizer._newoperations.append(jump_op)
-        return (UnrollInfo(self.make_short_preamble(start_label.getarglist()),
-                           self.extra_label_args),
+        return (UnrollInfo(self.short_preamble_producer.build_short_preamble(),
+                           self.short_preamble_producer.used_boxes),
                 self.optimizer._newoperations)
 
-    def make_short_preamble(self, args):
-        label = ResOperation(rop.LABEL, args)
-        short = [label] + self.short
-        return short
+    def inline_short_preamble(self, jump_args):
+        sb = self.short_preamble_producer
+        assert len(sb.short_inputargs) == len(jump_args)
+        for i in range(len(jump_args)):
+            sb.short_inputargs[i].set_forwarded(None)
+            self.make_equal_to(sb.short_inputargs[i], jump_args[i])
+        for op in sb.short:
+            self.optimizer.send_extra_operation(op)
+        res = [self.optimizer.get_box_replacement(op) for op in
+                sb.short_preamble_jump]
+        for op in sb.short_inputargs:
+            op.set_forwarded(None)
+        return res
 
     def random_garbage(self):
         # WTF is the rest of this function
@@ -236,7 +240,7 @@
         infos = {}
         for arg in end_args:
             infos[arg] = self.optimizer.getinfo(arg)
-        for box, _ in short_boxes:
+        for box, _, _ in short_boxes:
             if not isinstance(box, Const):
                 infos[box] = self.optimizer.getinfo(box)
         label_args = virtual_state.make_inputargs(end_args, self.optimizer)
@@ -295,7 +299,8 @@
     def import_state(self, targetop, exported_state):
         # the mapping between input args (from old label) and what we need
         # to actually emit. Update the info
-        self.ops_to_import = {}
+        #self.ops_to_import = {}
+        virtual_state = exported_state.virtual_state
         for source, target in exported_state.inputarg_mapping:
             if source is not target:
                 source.set_forwarded(target)
@@ -304,23 +309,27 @@
                 self.optimizer.setinfo_from_preamble(source, info)
         # import the optimizer state, starting from boxes that can be produced
         # by short preamble
-        self.short_preamble_producer = ShortPreambleProducer()
-        for op, getfield_op in exported_state.short_boxes:
-            if getfield_op is None:
+        short_inpargs = virtual_state.make_inputargs(
+            exported_state.short_inputargs, None)
+        self.short_preamble_producer = ShortPreambleBuilder(
+            exported_state.short_boxes, short_inpargs,
+            exported_state.exported_infos, self.optimizer)
+        for op, structop, preamble_op in exported_state.short_boxes:
+            if structop is None:
                 optpure = self.optimizer.optpure
                 if optpure is None:
                     continue
-                self.pure(op.getopnum(), PreambleOp(op, None,
-                                exported_state.exported_infos.get(op, None)))
+                self.pure(op.getopnum(), PreambleOp(op, preamble_op))
             else:
                 optheap = self.optimizer.optheap
                 if optheap is None:
                     continue
-                opinfo = self.optimizer.ensure_ptr_info_arg0(getfield_op)
-                pre_info = exported_state.exported_infos.get(op, None)
-                pop = PreambleOp(op, None, pre_info)
+                g = preamble_op.copy_and_change(preamble_op.getopnum(),
+                                                args=[structop])
+                opinfo = self.optimizer.ensure_ptr_info_arg0(g)
+                pop = PreambleOp(op, preamble_op)
                 assert not opinfo.is_virtual()
-                opinfo._fields[getfield_op.getdescr().get_index()] = pop
+                opinfo._fields[preamble_op.getdescr().get_index()] = pop
             #if not isinstance(op, Const):
             #    self.ops_to_import[op] = None
             # XXX think later about the short preamble
@@ -776,7 +785,7 @@
     """ 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
+    * extra_label_args - additional things to put in the label
     """
     def __init__(self, short_preamble, extra_label_args):
         self.short_preamble = short_preamble
diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py 
b/rpython/jit/metainterp/optimizeopt/virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py
@@ -133,10 +133,11 @@
         raise NotImplementedError
 
     def enum_forced_boxes(self, boxes, box, optimizer, force_boxes=False):
-        info = optimizer.getptrinfo(box)
-        box = optimizer.get_box_replacement(box)
-        if info is None or not info.is_virtual():
-            raise BadVirtualState()
+        if optimizer is not None:
+            info = optimizer.getptrinfo(box)
+            box = optimizer.get_box_replacement(box)
+            if info is None or not info.is_virtual():
+                raise BadVirtualState()
         for i in range(len(self.fielddescrs)):
             state = self.fieldstate[i]
             if not state:
@@ -427,14 +428,15 @@
         if self.level == LEVEL_CONSTANT:
             return
         assert 0 <= self.position_in_notvirtuals
-        box = optimizer.get_box_replacement(box)
-        if box.type == 'r':
-            info = optimizer.getptrinfo(box)
-            if info and info.is_virtual():
-                if force_boxes:
-                    info.force_box(box, optimizer)
-                else:
-                    raise BadVirtualState
+        if optimizer is not None:
+            box = optimizer.get_box_replacement(box)
+            if box.type == 'r':
+                info = optimizer.getptrinfo(box)
+                if info and info.is_virtual():
+                    if force_boxes:
+                        info.force_box(box, optimizer)
+                    else:
+                        raise BadVirtualState
         boxes[self.position_in_notvirtuals] = box
 
     def _enum(self, virtual_state):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to