[pypy-svn] pypy jit-virtual_state: Stores the OptValue states of all arguments to the loop and use them to deciede which specialized version of the loop to jump to (work in progress, only non virtuals fully supoprted so far). The intbounds creates a lot of (most of the time) identical specialized version. We need to generalize that somehow.
hakanardo
commits-noreply at bitbucket.org
Thu Feb 3 21:42:15 CET 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-virtual_state
Changeset: r41587:057bd6a641f3
Date: 2011-02-03 21:40 +0100
http://bitbucket.org/pypy/pypy/changeset/057bd6a641f3/
Log: Stores the OptValue states of all arguments to the loop and use them
to deciede which specialized version of the loop to jump to (work in
progress, only non virtuals fully supoprted so far). The intbounds
creates a lot of (most of the time) identical specialized version.
We need to generalize that somehow.
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -125,6 +125,64 @@
self.snapshot_map[snapshot] = new_snapshot
return new_snapshot
+class VirtualStateAdder(resume.ResumeDataVirtualAdder):
+ def __init__(self, optimizer):
+ self.fieldboxes = {}
+ self.optimizer = optimizer
+ self.info = {}
+
+ def register_virtual_fields(self, keybox, fieldboxes):
+ self.fieldboxes[keybox] = fieldboxes
+
+ def already_seen_virtual(self, keybox):
+ return keybox in self.fieldboxes
+
+ def getvalue(self, box):
+ return self.optimizer.getvalue(box)
+
+ def state(self, box):
+ try:
+ info = self.info[box]
+ except KeyError:
+ value = self.getvalue(box)
+ self.info[box] = info = value.make_virtual_info(self, [])
+ if box in self.fieldboxes:
+ info.fieldstate = [self.state(b) for b in self.fieldboxes[box]]
+ # FIXME: Do we realy want to add fields to the VirtualInfo's?
+ return info
+
+ def get_virtual_state(self, jump_args):
+ for box in jump_args:
+ value = self.getvalue(box)
+ value.get_args_for_fail(self)
+ return [self.state(box) for box in jump_args]
+
+
+ def make_not_virtual(self, value):
+ return NotVirtualInfo(value)
+
+class NotVirtualInfo(resume.AbstractVirtualInfo):
+ def __init__(self, value):
+ self.known_class = value.known_class
+ self.level = value.level
+ self.intbound = value.intbound.clone()
+ if value.is_constant():
+ self.constbox = value.box.clonebox()
+ else:
+ self.constbox = None
+
+ def more_general_than(self, other):
+ # XXX This will always retrace instead of forcing anything which
+ # might be what we want sometimes?
+ if not isinstance(other, NotVirtualInfo):
+ return False
+ if self.constbox:
+ if not self.constbox.same_const(other):
+ return False
+ return (self.known_class == other.known_class and
+ self.level == other.level and
+ self.intbound.contains_bound(other.intbound))
+
class UnrollOptimizer(Optimization):
"""Unroll the loop into two iterations. The first one will
@@ -139,7 +197,6 @@
self.cloned_operations.append(newop)
def propagate_all_forward(self):
- self.make_short_preamble = True
loop = self.optimizer.loop
jumpop = loop.operations[-1]
if jumpop.getopnum() == rop.JUMP:
@@ -154,7 +211,9 @@
assert jumpop.getdescr() is loop.token
jump_args = jumpop.getarglist()
jumpop.initarglist([])
- virtual_state = [self.getvalue(a).is_virtual() for a in jump_args]
+ #virtual_state = [self.getvalue(a).is_virtual() for a in jump_args]
+ modifier = VirtualStateAdder(self.optimizer)
+ virtual_state = modifier.get_virtual_state(jump_args)
loop.preamble.operations = self.optimizer.newoperations
self.optimizer = self.optimizer.reconstruct_for_next_iteration()
@@ -221,7 +280,6 @@
if op.result:
op.result.forget_value()
-
def inline(self, loop_operations, loop_args, jump_args):
self.inliner = inliner = Inliner(loop_args, jump_args)
@@ -236,8 +294,6 @@
for a in boxes:
if not isinstance(a, Const):
inputargs.append(a)
- else:
- self.make_short_preamble = False
# This loop is equivalent to the main optimization loop in
# Optimizer.propagate_all_forward
@@ -304,8 +360,6 @@
return True
def create_short_preamble(self, preamble, loop):
- if not self.make_short_preamble:
- return None
#return None # Dissable
preamble_ops = preamble.operations
@@ -532,20 +586,15 @@
short = descr.short_preamble
if short:
args = op.getarglist()
- virtual_state = [self.getvalue(a).is_virtual() for a in args]
+ modifier = VirtualStateAdder(self.optimizer)
+ virtual_state = modifier.get_virtual_state(args)
+ print 'len', len(short)
for sh in short:
assert len(virtual_state) == len(sh.virtual_state)
+
for i in range(len(virtual_state)):
- if sh.virtual_state[i] and not virtual_state[i]:
+ if not sh.virtual_state[i].more_general_than(virtual_state[i]):
break
- elif not sh.virtual_state[i] and virtual_state[i]:
- # XXX Here, this bridge has made some box virtual
- # that is not virtual in the original loop. These
- # will be forced below. However we could choose
- # to raise RetraceLoop here to create a new
- # specialized version of the loop where more
- # boxes will be virtual.
- pass
else:
if self.inline(sh.operations, sh.inputargs,
op.getarglist(), dryrun=True):
diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -94,21 +94,27 @@
v2 = self.getvalue(op.getarg(1))
self.emit_operation(op)
r = self.getvalue(op.result)
- r.intbound.intersect(v1.intbound.sub_bound(v2.intbound))
+ b = v1.intbound.sub_bound(v2.intbound)
+ if b.bounded():
+ r.intbound.intersect(b)
def optimize_INT_ADD(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
self.emit_operation(op)
r = self.getvalue(op.result)
- r.intbound.intersect(v1.intbound.add_bound(v2.intbound))
+ b = v1.intbound.add_bound(v2.intbound)
+ if b.bounded():
+ r.intbound.intersect(b)
def optimize_INT_MUL(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
self.emit_operation(op)
r = self.getvalue(op.result)
- r.intbound.intersect(v1.intbound.mul_bound(v2.intbound))
+ b = v1.intbound.mul_bound(v2.intbound)
+ if b.bounded():
+ r.intbound.intersect(b)
def optimize_INT_FLOORDIV(self, op):
v1 = self.getvalue(op.getarg(0))
@@ -300,7 +306,7 @@
if r.box.same_constant(CONST_1):
self.make_int_gt(op.getarg(0), op.getarg(1))
else:
- self.make_int_le(op.getarg(0), op.getarg(1))
+ self.make_int_le(op.getarg(0), op.getarg(1))
def propagate_bounds_INT_LE(self, op):
r = self.getvalue(op.result)
diff --git a/pypy/jit/metainterp/optimizeopt/intutils.py b/pypy/jit/metainterp/optimizeopt/intutils.py
--- a/pypy/jit/metainterp/optimizeopt/intutils.py
+++ b/pypy/jit/metainterp/optimizeopt/intutils.py
@@ -42,6 +42,9 @@
self.has_lower = False
self.has_upper = False
+ def bounded(self):
+ return self.has_lower and self.has_upper
+
def known_lt(self, other):
if self.has_upper and other.has_lower and self.upper < other.lower:
return True
@@ -76,7 +79,7 @@
return r
def add(self, offset):
- res = self.copy()
+ res = self.clone()
try:
res.lower = ovfcheck(res.lower + offset)
except OverflowError:
@@ -91,7 +94,7 @@
return self.mul_bound(IntBound(value, value))
def add_bound(self, other):
- res = self.copy()
+ res = self.clone()
if other.has_upper:
try:
res.upper = ovfcheck(res.upper + other.upper)
@@ -109,7 +112,7 @@
return res
def sub_bound(self, other):
- res = self.copy()
+ res = self.clone()
if other.has_lower:
try:
res.upper = ovfcheck(res.upper - other.lower)
@@ -192,6 +195,19 @@
if self.has_upper and val > self.upper:
return False
return True
+
+ def contains_bound(self, other):
+ if other.has_lower:
+ if not self.contains(other.lower):
+ return False
+ elif self.has_lower:
+ return False
+ if other.has_upper:
+ if not self.contains(other.upper):
+ return False
+ elif self.has_upper:
+ return False
+ return True
def __repr__(self):
if self.has_lower:
@@ -204,7 +220,7 @@
u = 'Inf'
return '%s <= x <= %s' % (l, u)
- def copy(self):
+ def clone(self):
res = IntBound(self.lower, self.upper)
res.has_lower = self.has_lower
res.has_upper = self.has_upper
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -69,7 +69,8 @@
pass
def make_virtual_info(self, modifier, fieldnums):
- raise NotImplementedError # should not be called on this level
+ #raise NotImplementedError # should not be called on this level
+ return modifier.make_not_virtual(self)
def is_constant(self):
return self.level == LEVEL_CONSTANT
More information about the Pypy-commit
mailing list