Author: Armin Rigo <[email protected]>
Branch:
Changeset: r59951:02f2e74659ab
Date: 2013-01-11 15:35 +0100
http://bitbucket.org/pypy/pypy/changeset/02f2e74659ab/
Log: jitdriver(reds='auto'): fix it to only include the red vars that are
alive across the jitdriver. Test. Move the logic to support, too.
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -10,7 +10,7 @@
from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.translator.simplify import get_funcobj
from pypy.translator.unsimplify import split_block
-from pypy.objspace.flow.model import Constant
+from pypy.objspace.flow.model import Variable, Constant
from pypy.translator.translator import TranslationContext
from pypy.annotation.policy import AnnotatorPolicy
from pypy.annotation import model as annmodel
@@ -59,6 +59,45 @@
rtyper = annotate(func, values)
return rtyper.annotator.translator.graphs[0]
+def autodetect_jit_markers_redvars(graph):
+ # the idea is to find all the jit_merge_point and
+ # add all the variables across the links to the reds.
+ for block, op in graph.iterblockops():
+ if op.opname == 'jit_marker':
+ jitdriver = op.args[1].value
+ if not jitdriver.autoreds:
+ continue
+ # if we want to support also can_enter_jit, we should find a
+ # way to detect a consistent set of red vars to pass *both* to
+ # jit_merge_point and can_enter_jit. The current simple
+ # solution doesn't work because can_enter_jit might be in
+ # another block, so the set of alive_v will be different.
+ methname = op.args[0].value
+ assert methname == 'jit_merge_point', (
+ "reds='auto' is supported only for jit drivers which "
+ "calls only jit_merge_point. Found a call to %s" % methname)
+ #
+ # compute the set of live variables across the jit_marker
+ alive_v = set()
+ for link in block.exits:
+ alive_v.update(link.args)
+ alive_v.difference_update(link.getextravars())
+ for op1 in block.operations[::-1]:
+ if op1 is op:
+ break # stop when the meet the jit_marker
+ alive_v.discard(op1.result)
+ alive_v.update(op1.args)
+ greens_v = op.args[2:]
+ reds_v = alive_v - set(greens_v)
+ reds_v = [v for v in reds_v if isinstance(v, Variable) and
+ v.concretetype is not lltype.Void]
+ reds_v = sort_vars(reds_v)
+ op.args.extend(reds_v)
+ if jitdriver.numreds is None:
+ jitdriver.numreds = len(reds_v)
+ else:
+ assert jitdriver.numreds == len(reds_v), 'inconsistent number
of reds_v'
+
def split_before_jit_merge_point(graph, portalblock, portalopindex):
"""Split the block just before the 'jit_merge_point',
making sure the input args are in the canonical order.
diff --git a/pypy/jit/metainterp/test/test_warmspot.py
b/pypy/jit/metainterp/test/test_warmspot.py
--- a/pypy/jit/metainterp/test/test_warmspot.py
+++ b/pypy/jit/metainterp/test/test_warmspot.py
@@ -383,6 +383,23 @@
assert res == expected
self.check_resops(int_sub=2, int_mul=0, int_add=2)
+ def test_loop_automatic_reds_not_too_many_redvars(self):
+ myjitdriver = JitDriver(greens = ['m'], reds = 'auto')
+ def one():
+ return 1
+ def f(n, m):
+ res = 0
+ while n > 0:
+ n -= one()
+ myjitdriver.jit_merge_point(m=m)
+ res += m*2
+ return res
+ expected = f(21, 5)
+ res = self.meta_interp(f, [21, 5])
+ assert res == expected
+ oplabel = get_stats().loops[0].operations[0]
+ assert len(oplabel.getarglist()) == 2 # 'n', 'res' in some order
+
def test_inline_jit_merge_point(self):
# test that the machinery to inline jit_merge_points in callers
# works. The final user does not need to mess manually with the
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -347,49 +347,13 @@
self.jitdrivers_sd = []
graphs = self.translator.graphs
for graph, block, pos in find_jit_merge_points(graphs):
- self.autodetect_jit_markers_redvars(graph)
+ support.autodetect_jit_markers_redvars(graph)
self.split_graph_and_record_jitdriver(graph, block, pos)
#
assert (len(set([jd.jitdriver for jd in self.jitdrivers_sd])) ==
len(self.jitdrivers_sd)), \
"there are multiple jit_merge_points with the same jitdriver"
- def autodetect_jit_markers_redvars(self, graph):
- # the idea is to find all the jit_merge_point and can_enter_jit and
- # add all the variables across the links to the reds.
- for block, op in graph.iterblockops():
- if op.opname == 'jit_marker':
- jitdriver = op.args[1].value
- if not jitdriver.autoreds:
- continue
- # if we want to support also can_enter_jit, we should find a
- # way to detect a consistent set of red vars to pass *both* to
- # jit_merge_point and can_enter_jit. The current simple
- # solution doesn't work because can_enter_jit might be in
- # another block, so the set of alive_v will be different.
- methname = op.args[0].value
- assert methname == 'jit_merge_point', (
- "reds='auto' is supported only for jit drivers which "
- "calls only jit_merge_point. Found a call to %s" %
methname)
- #
- # compute the set of live variables before the jit_marker
- alive_v = set(block.inputargs)
- for op1 in block.operations:
- if op1 is op:
- break # stop when the meet the jit_marker
- if op1.result.concretetype != lltype.Void:
- alive_v.add(op1.result)
- greens_v = op.args[2:]
- reds_v = alive_v - set(greens_v)
- reds_v = [v for v in reds_v if v.concretetype is not
lltype.Void]
- reds_v = support.sort_vars(reds_v)
- op.args.extend(reds_v)
- if jitdriver.numreds is None:
- jitdriver.numreds = len(reds_v)
- else:
- assert jitdriver.numreds == len(reds_v), 'inconsistent
number of reds_v'
-
-
def split_graph_and_record_jitdriver(self, graph, block, pos):
op = block.operations[pos]
jd = JitDriverStaticData()
@@ -717,6 +681,9 @@
jitdriver = op.args[1].value
assert jitdriver in sublists, \
"can_enter_jit with no matching jit_merge_point"
+ assert not jitdriver.autoreds, (
+ "can_enter_jit not supported with a jitdriver that "
+ "has reds='auto'")
jd, sublist = sublists[jitdriver]
origportalgraph = jd._jit_merge_point_in
if graph is not origportalgraph:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit