Author: Maciej Fijalkowski <[email protected]>
Branch: optresult-unroll
Changeset: r78445:eeaaac148347
Date: 2015-07-06 10:07 +0200
http://bitbucket.org/pypy/pypy/changeset/eeaaac148347/

Log:    rework short boxes

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,118 +1,51 @@
 
-from rpython.jit.metainterp.resoperation import rop, ResOperation
+from rpython.jit.metainterp.resoperation import rop, ResOperation, OpHelpers
 from rpython.jit.metainterp.history import Const
 
-class BoxNotProducable(Exception):
-    pass
 
 
 class ShortBoxes(object):
     def __init__(self):
-        self.potential_ops = {}
-        self.inputarg_boxes = {}
-        self.synthetic = {}
-        self.alternatives = {}
+        self.potential_ops = []
+        self.ops_used = {}
         self.extra_same_as = []
 
     def create_short_boxes(self, optimizer, inputargs):
         for box in inputargs:
-            self.inputarg_boxes[box] = None
+            self.ops_used[box] = None
         optimizer.produce_potential_short_preamble_ops(self)
 
         self.short_boxes = {}
-        self.short_boxes_in_production = {}
+        # short boxes has a map of "op from preamble" ->
+        # "op going to short preamble", where "op from preamble" can be
+        # anything, but the one going to short_preamble has to be either pure
+        # or a heap cache op
 
-        for op in self.potential_ops.keys():
-            try:
-                self.produce_short_preamble_op(op)
-            except BoxNotProducable:
+        for op, preamble_op in self.potential_ops:
+            self.produce_short_preamble_op(op, preamble_op)
+
+    def add_to_short(self, op, short_op):
+        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 op in self.short_boxes:
+            opnum = OpHelpers.same_as_for_type(op.type)
+            same_as_op = ResOperation(opnum, [op])
+            self.extra_same_as.append(same_as_op)
+            self.add_to_short(same_as_op, preamble_op)
+        else:
+            self.add_to_short(op, preamble_op)
 
-        self.short_boxes_in_production = None # Not needed anymore
-
-    def prioritized_alternatives(self, box):
-        if box not in self.alternatives:
-            return [self.potential_ops[box]]
-        alts = self.alternatives[box]
-        hi, lo = 0, len(alts) - 1
-        while hi < lo:
-            if alts[lo] is None: # Inputarg, lowest priority
-                alts[lo], alts[-1] = alts[-1], alts[lo]
-                lo -= 1
-            elif alts[lo] not in self.synthetic: # Hi priority
-                alts[hi], alts[lo] = alts[lo], alts[hi]
-                hi += 1
-            else: # Low priority
-                lo -= 1
-        return alts
-
-    def add_to_short(self, op):
-        if op in self.short_boxes:
-            xxx
-            #if op is None:
-            #    xxx
-            #    oldop = self.short_boxes[box]
-            #    self.rename[op] = oldop
-            #    self.short_boxes[box] = None
-            #    self.short_boxes[oldop] = oldop
-            #else:
-            #    xxxx
-            #    newop = op.clone()
-            #    newbox = newop.result = op.result.clonebox()
-            #    self.short_boxes[newop.result] = newop
-            #xxx
-            #value = self.optimizer.getvalue(box)
-            #self.optimizer.emit_operation(ResOperation(rop.SAME_AS, [box], 
newbox))
-            #self.optimizer.make_equal_to(newbox, value)
-            #if op is None:
-            #    if self.short_boxes[box] is not box:
-            #        xxx
-            #else:
-            #    if self.short_boxes[box] is not op:
-            #        if self.short_boxes[box] is None:
-            #            self.short_boxes[box] = op
-            #        else:
-            #            xxx
+    def add_potential(self, op, short_preamble_op=None):
+        if short_preamble_op is None:
+            self.potential_ops.append((op, op))
         else:
-            self.short_boxes[op] = None
-
-    def produce_short_preamble_op(self, op):
-        if op in self.short_boxes:
-            return
-        if op in self.inputarg_boxes:
-            return
-        if isinstance(op, Const):
-            return
-        if op in self.short_boxes_in_production:
-            raise BoxNotProducable
-        self.short_boxes_in_production[op] = None
-
-        if op in self.potential_ops:
-            ops = self.prioritized_alternatives(op)
-            produced_one = False
-            for newop in ops:
-                try:
-                    if newop:
-                        for arg in newop.getarglist():
-                            self.produce_short_preamble_op(arg)
-                except BoxNotProducable:
-                    pass
-                else:
-                    produced_one = True
-                    self.add_to_short(newop)
-            if not produced_one:
-                raise BoxNotProducable
-        else:
-            raise BoxNotProducable
-
-    def add_potential(self, op, result=None, synthetic=False):
-        if result is None:
-            result = op
-        if result in self.potential_ops:
-            if result not in self.alternatives:
-                self.alternatives[result] = [self.potential_ops[result]]
-            self.alternatives[result].append(op)
-        else:
-            self.potential_ops[result] = op
-        if synthetic:
-            self.synthetic[result] = True
+            self.potential_ops.append((op, short_preamble_op))
+        self.ops_used[op] = None
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_short.py 
b/rpython/jit/metainterp/optimizeopt/test/test_short.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_short.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_short.py
@@ -28,7 +28,7 @@
         op = ResOperation(rop.INT_ADD, [i0, i1])
         sb = ShortBoxes()
         sb.create_short_boxes(Opt([op]), [i0, i1])
-        assert sb.short_boxes == {op: None}
+        assert sb.short_boxes == {op: op}
 
     def test_pure_ops_does_not_work(self):
         i0 = InputArgInt()
@@ -39,10 +39,26 @@
         assert sb.short_boxes == {}
 
     def test_multiple_similar_ops(self):
+        """ This can happen e.g. if heap cache and pure ops produce
+        the same thing. So let's say we have:
+
+        i0 = int_add(i0, 1)
+        setfield_gc(p0, i0)
+
+        now i0 can be gotten in two ways - from getfield or from int_add,
+        we store both in short preamble (in case someone else who inlines
+        the short preamble does not share them)
+        """
         i0 = InputArgInt()
         i1 = InputArgInt()
         op = ResOperation(rop.INT_ADD, [i0, i1])
         op1 = ResOperation(rop.GETFIELD_GC_I, [i0], descr=Descr())
         sb = ShortBoxes()
-        sb.create_short_boxes(Opt([op, (op1, op)]), [i0, i1])
-        
+        sb.create_short_boxes(Opt([op, (op, op1)]), [i0, i1])
+        assert len(sb.short_boxes) == 2
+        l = [x.getopnum() for x in sb.short_boxes.keys()]
+        l.sort()
+        assert l == [rop.INT_ADD, rop.SAME_AS_I]
+        assert op1 in sb.short_boxes.values()
+        assert op in sb.short_boxes.values()
+        assert op in sb.short_boxes.keys()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to