Author: Antonio Cuni <[email protected]>
Branch: autoreds
Changeset: r58838:4c87f9b67a7f
Date: 2012-11-12 12:46 +0100
http://bitbucket.org/pypy/pypy/changeset/4c87f9b67a7f/
Log: it took 2 days of experiments, playing around and understand JIT
details I never knew about :), but I finally managed to find a
simple way to have red variables automatically detected by the JIT;
still in-progress, but the basic idea should work
diff --git a/pypy/jit/codewriter/jtransform.py
b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -1317,7 +1317,7 @@
def promote_greens(self, args, jitdriver):
ops = []
num_green_args = len(jitdriver.greens)
- assert len(args) == num_green_args + len(jitdriver.reds)
+ assert len(args) == num_green_args + jitdriver.numreds
for v in args[:num_green_args]:
if isinstance(v, Variable) and v.concretetype is not lltype.Void:
kind = getkind(v.concretetype)
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
@@ -84,7 +84,8 @@
assert op.opname == 'jit_marker'
jitdriver = op.args[1].value
numgreens = len(jitdriver.greens)
- numreds = len(jitdriver.reds)
+ assert jitdriver.numreds is not None
+ numreds = jitdriver.numreds
greens_v = op.args[2:2+numgreens]
reds_v = op.args[2+numgreens:]
assert len(reds_v) == numreds
diff --git a/pypy/jit/metainterp/test/test_ajit.py
b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -95,6 +95,30 @@
found += 1
assert found == 2
+ def test_loop_automatic_reds(self):
+ myjitdriver = JitDriver(greens = ['m'], reds = 'auto')
+ def f(n, m):
+ res = 0
+ # try to have lots of red vars, so that if there is an error in
+ # the ordering of reds, there are low chances that the test passes
+ # by chance
+ a = b = c = d = n
+ while n > 0:
+ myjitdriver.can_enter_jit(m=m)
+ myjitdriver.jit_merge_point(m=m)
+ n -= 1
+ a += 1 # dummy unused red
+ b += 2 # dummy unused red
+ c += 3 # dummy unused red
+ d += 4 # dummy unused red
+ res += m*2
+ return res
+ expected = f(21, 5)
+ res = self.meta_interp(f, [21, 5])
+ assert res == expected
+ self.check_resops(int_sub=2, int_mul=0, int_add=10)
+
+
def test_loop_variant_mul1(self):
myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
def f(x, y):
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
@@ -251,6 +251,22 @@
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
+ greens_v = op.args[2:]
+ alive_v = set(block.inputargs) # XXX: there might be more
+ # alive vars?
+ reds_v = alive_v - set(greens_v)
+ reds_v = list(reds_v) # XXX: order the reds by type (INT, REF,
FLOAT)
+ op.args.extend(reds_v)
+ assert jitdriver.autoreds
+ #assert jitdriver.numreds is None,
'autodetect_jit_markers_redvars called twice?!?'
+ jitdriver.numreds = len(reds_v)
+
def split_graph_and_record_jitdriver(self, graph, block, pos):
op = block.operations[pos]
jd = JitDriverStaticData()
@@ -258,6 +274,7 @@
args = op.args[2:]
s_binding = self.translator.annotator.binding
jd._portal_args_s = [s_binding(v) for v in args]
+ self.autodetect_jit_markers_redvars(graph)
graph = copygraph(graph)
[jmpp] = find_jit_merge_points([graph])
graph.startblock = support.split_before_jit_merge_point(*jmpp)
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -452,16 +452,26 @@
if greens is not None:
self.greens = greens
self.name = name
- if reds is not None:
+ if reds == 'auto':
+ self.autoreds = True
+ self.reds = []
+ self.numreds = None # see warmspot.autodetect_jit_markers_redvars
+ elif reds is not None:
+ self.autoreds = False
self.reds = reds
+ self.numreds = len(reds)
if not hasattr(self, 'greens') or not hasattr(self, 'reds'):
raise AttributeError("no 'greens' or 'reds' supplied")
if virtualizables is not None:
self.virtualizables = virtualizables
for v in self.virtualizables:
assert v in self.reds
- self._alllivevars = dict.fromkeys(
- [name for name in self.greens + self.reds if '.' not in name])
+ # if reds are automatic, they won't be passed to jit_merge_point, so
+ # _check_arguments will receive only the green ones (i.e., the ones
+ # which are listed explicitly). So, it is fine to just ignore reds
+ self._somelivevars = set([name for name in
+ self.greens + (self.reds or [])
+ if '.' not in name])
self._heuristic_order = {} # check if 'reds' and 'greens' are ordered
self._make_extregistryentries()
self.get_jitcell_at = get_jitcell_at
@@ -475,7 +485,7 @@
return True
def _check_arguments(self, livevars):
- assert dict.fromkeys(livevars) == self._alllivevars
+ assert set(livevars) == self._somelivevars
# check heuristically that 'reds' and 'greens' are ordered as
# the JIT will need them to be: first INTs, then REFs, then
# FLOATs.
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit