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