[pypy-svn] r74604 - in pypy/branch/blackhole-improvement/pypy/jit/codewriter: . test
arigo at codespeak.net
arigo at codespeak.net
Thu May 20 19:30:52 CEST 2010
Author: arigo
Date: Thu May 20 19:30:50 2010
New Revision: 74604
Modified:
pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_format.py
pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_liveness.py
Log:
Change the way I would like liveness.py to be.
Breaks all other code for now.
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/flatten.py Thu May 20 19:30:50 2010
@@ -40,11 +40,14 @@
self.kind = kind
self.content = tuple(content)
def __repr__(self):
- return '%s%s' % (self.kind[0], self.content)
+ return '%s%s' % (self.kind[0].upper(), list(self.content))
def __iter__(self):
return iter(self.content)
def __nonzero__(self):
return bool(self.content)
+ def __eq__(self, other):
+ return (isinstance(other, ListOfKind) and
+ self.kind == other.kind and self.content == other.content)
class IndirectCallTargets(object):
def __init__(self, lst):
@@ -146,9 +149,11 @@
self.emitline("reraise")
return # done
if link.last_exception in link.args:
- self.emitline("last_exception", self.getcolor(link.last_exception))
+ self.emitline("last_exception",
+ "->", self.getcolor(link.last_exception))
if link.last_exc_value in link.args:
- self.emitline("last_exc_value", self.getcolor(link.last_exc_value))
+ self.emitline("last_exc_value",
+ "->", self.getcolor(link.last_exc_value))
self.make_link(link)
def insert_exits(self, block):
@@ -292,9 +297,9 @@
if w is None:
self.emitline('%s_push' % kind, v)
elif v is None:
- self.emitline('%s_pop' % kind, w)
+ self.emitline('%s_pop' % kind, "->", w)
else:
- self.emitline('%s_copy' % kind, v, w)
+ self.emitline('%s_copy' % kind, v, "->", w)
def emitline(self, *line):
self.ssarepr.insns.append(line)
@@ -322,6 +327,7 @@
if op.result is not None:
kind = getkind(op.result.concretetype)
if kind != 'void':
+ args.append("->")
args.append(self.getcolor(op.result))
self.emitline(op.opname, *args)
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/format.py Thu May 20 19:30:50 2010
@@ -56,9 +56,16 @@
else:
print >> output, asm[0],
if len(asm) > 1:
- lst = map(repr, asm[1:])
- if asm[0] == '-live-': lst.sort()
- print >> output, ', '.join(lst)
+ if asm[-2] == '->':
+ if len(asm) == 3:
+ print >> output, '->', repr(asm[-1])
+ else:
+ lst = map(repr, asm[1:-2])
+ print >> output, ', '.join(lst), '->', repr(asm[-1])
+ else:
+ lst = map(repr, asm[1:])
+ if asm[0] == '-live-': lst.sort()
+ print >> output, ', '.join(lst)
else:
print >> output
res = output.getvalue()
@@ -71,23 +78,25 @@
explines = expected.split("\n")
for asm, exp in zip(asmlines, explines):
if asm != exp:
- print
- print "Got: " + asm
- print "Expected: " + exp
+ msg = [""]
+ msg.append("Got: " + asm)
+ msg.append("Expected: " + exp)
lgt = 0
for i in range(min(len(asm), len(exp))):
if exp[i] == asm[i]:
lgt += 1
else:
break
- print " " + " " * lgt + "^^^^"
- raise AssertionError
+ msg.append(" " + " " * lgt + "^^^^")
+ raise AssertionError('\n'.join(msg))
assert len(asmlines) == len(explines)
def unformat_assembler(text, registers=None):
# XXX limited to simple assembler right now
#
def unformat_arg(s):
+ if s.endswith(','):
+ s = s[:-1].rstrip()
if s[0] == '%':
try:
return registers[s]
@@ -104,6 +113,21 @@
return Constant(intvalue, lltype.Signed)
elif s[0] == 'L':
return TLabel(s)
+ elif s[0] in 'IRF' and s[1] == '[' and s[-1] == ']':
+ items = split_words(s[2:-1])
+ items = map(unformat_arg, items)
+ return ListOfKind({'I': 'int', 'R': 'ref', 'F': 'float'}[s[0]],
+ items)
+ elif s.startswith('<SwitchDictDescr '):
+ assert s.endswith('>')
+ switchdict = SwitchDictDescr()
+ switchdict._labels = []
+ items = split_words(s[len('<SwitchDictDescr '):-1])
+ for item in items:
+ key, value = item.split(':')
+ value = value.rstrip(',')
+ switchdict._labels.append((int(key), TLabel(value)))
+ return switchdict
else:
raise AssertionError("unsupported argument: %r" % (s,))
#
@@ -121,7 +145,33 @@
opname, line = line.split(None, 1)
except ValueError:
opname, line = line, ''
- line = [s.strip() for s in line.split(',')]
- insn = [opname] + [unformat_arg(s) for s in line if s]
+ words = list(split_words(line))
+ if '->' in words:
+ assert words.index('->') == len(words) - 2
+ extra = ['->', unformat_arg(words[-1])]
+ del words[-2:]
+ else:
+ extra = []
+ insn = [opname] + [unformat_arg(s) for s in words] + extra
ssarepr.insns.append(tuple(insn))
return ssarepr
+
+
+def split_words(line):
+ word = ''
+ nested = 0
+ for i, c in enumerate(line):
+ if c == ' ' and nested == 0:
+ if word:
+ yield word
+ word = ''
+ else:
+ word += c
+ if c in '<([':
+ nested += 1
+ if c in '])>' and line[i-2:i+2] != ' -> ':
+ nested -= 1
+ assert nested >= 0
+ if word:
+ yield word
+ assert nested == 0
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/liveness.py Thu May 20 19:30:50 2010
@@ -1,45 +1,79 @@
-from pypy.objspace.flow.model import Variable, SpaceOperation, c_last_exception
-from pypy.jit.codewriter.flatten import ListOfKind
+from pypy.jit.codewriter.flatten import Register, ListOfKind, Label, TLabel
+from pypy.jit.codewriter.jitcode import SwitchDictDescr
-# Some instruction require liveness information (the ones that can end up
-# in generate_guard() in pyjitpl.py); jtransform.py prefixes these opnames
-# with a 'G_'. Additionally, boolean and general switches in the flow graph
-# will turn in 'goto_if_not_*' operations, which also require liveness info.
+# Some instructions require liveness information (the ones that can end up
+# in generate_guard() in pyjitpl.py). This is done by putting special
+# space operations called '-live-' in the graph. They turn into '-live-'
+# operation in the ssarepr. Then this module expands the arguments of
+# the '-live-' operations to also include all values that are alive at
+# this point: more precisely, all values that are created before the
+# '-live-' operation and that are needed afterwards, with the exception
+# of the values that are needed only in the very next instruction. These
+# are not considered alive any more. You can force them to be alive by
+# putting them as args of the '-live-' operation in the first place.
+
+# For this to work properly, a special operation called '---' must be
+# used to mark unreachable places (e.g. just after a 'goto').
# ____________________________________________________________
-def compute_liveness(graph, switches_require_liveness=True):
- for block in graph.iterblocks():
- num_operations = len(block.operations)
- alive = set()
- for link in block.exits:
- for v in link.args:
- if (v is not link.last_exception and
- v is not link.last_exc_value):
- alive.add(v)
- if switches_require_liveness:
- if len(block.exits) > 1 and block.exitswitch != c_last_exception:
- block.operations.append(_livespaceop(alive))
- if isinstance(block.exitswitch, tuple):
- for v in block.exitswitch[1:]:
- alive.add(v)
- else:
- alive.add(block.exitswitch)
- for i in range(num_operations-1, -1, -1):
- op = block.operations[i]
- try:
- alive.remove(op.result)
- except KeyError:
- pass
- if op.opname.startswith('G_'):
- block.operations.insert(i, _livespaceop(alive))
- for v in op.args:
- if isinstance(v, ListOfKind):
- alive.update(v)
- else:
- alive.add(v)
-
-def _livespaceop(alive):
- livevars = [v for v in alive if isinstance(v, Variable)]
- return SpaceOperation('-live-', livevars, None)
+def compute_liveness(ssarepr):
+ label2alive = {}
+ while _compute_liveness_must_continue(ssarepr, label2alive):
+ pass
+
+def _compute_liveness_must_continue(ssarepr, label2alive):
+ alive = set()
+ prevalive = None
+ must_continue = False
+
+ for i in range(len(ssarepr.insns)-1, -1, -1):
+ insn = ssarepr.insns[i]
+
+ if isinstance(insn[0], Label):
+ alive_at_point = label2alive.setdefault(insn[0].name, set())
+ prevlength = len(alive_at_point)
+ alive_at_point.update(alive)
+ if prevlength != len(alive_at_point):
+ must_continue = True
+ prevalive = None
+ continue
+
+ if insn[0] == '-live-':
+ assert prevalive is not None
+ for x in insn[1:]:
+ prevalive.discard(x)
+ ssarepr.insns[i] = insn + tuple(prevalive)
+ prevalive = None
+ continue
+
+ if insn[0] == '---':
+ alive = set()
+ prevalive = None
+ continue
+
+ args = insn[1:]
+ #
+ if len(args) >= 2 and args[-2] == '->':
+ reg = args[-1]
+ assert isinstance(reg, Register)
+ alive.discard(reg)
+ args = args[:-2]
+ #
+ prevalive = alive.copy()
+ #
+ for x in args:
+ if isinstance(x, Register):
+ alive.add(x)
+ elif isinstance(x, ListOfKind):
+ alive.update(x)
+ elif isinstance(x, TLabel):
+ alive_at_point = label2alive.get(x.name, ())
+ alive.update(alive_at_point)
+ elif isinstance(x, SwitchDictDescr):
+ for key, label in x._labels:
+ alive_at_point = label2alive.get(label.name, ())
+ alive.update(alive_at_point)
+
+ return must_continue
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_format.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_format.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_format.py Thu May 20 19:30:50 2010
@@ -4,6 +4,7 @@
from pypy.jit.codewriter.flatten import Label, TLabel, SSARepr, Register
from pypy.jit.codewriter.flatten import ListOfKind
from pypy.jit.metainterp.history import AbstractDescr
+from pypy.jit.codewriter.jitcode import SwitchDictDescr
from pypy.rpython.lltypesystem import lltype
@@ -11,12 +12,12 @@
ssarepr = SSARepr("test")
i0, i1, i2 = Register('int', 0), Register('int', 1), Register('int', 2)
ssarepr.insns = [
- ('int_add', i0, i1, i2),
+ ('int_add', i0, i1, '->', i2),
('int_return', i2),
]
asm = format_assembler(ssarepr)
expected = """
- int_add %i0, %i1, %i2
+ int_add %i0, %i1 -> %i2
int_return %i2
"""
assert asm == str(py.code.Source(expected)).strip() + '\n'
@@ -39,11 +40,11 @@
s.x = 123
ssarepr = SSARepr("test")
ssarepr.insns = [
- ('foobar', Constant(s, lltype.typeOf(s))),
+ ('foobar', '->', Constant(s, lltype.typeOf(s))),
]
asm = format_assembler(ssarepr)
expected = """
- foobar $<* struct S>
+ foobar -> $<* struct S>
"""
assert asm == str(py.code.Source(expected)).strip() + '\n'
@@ -53,8 +54,8 @@
ssarepr.insns = [
(Label('L1'),),
('goto_if_not_int_gt', i0, Constant(0, lltype.Signed), TLabel('L2')),
- ('int_add', i1, i0, i1),
- ('int_sub', i0, Constant(1, lltype.Signed), i0),
+ ('int_add', i1, i0, '->', i1),
+ ('int_sub', i0, Constant(1, lltype.Signed), '->', i0),
('goto', TLabel('L1')),
(Label('L2'),),
('int_return', i1),
@@ -63,8 +64,8 @@
expected = """
L1:
goto_if_not_int_gt %i0, $0, L2
- int_add %i1, %i0, %i1
- int_sub %i0, $1, %i0
+ int_add %i1, %i0 -> %i1
+ int_sub %i0, $1 -> %i0
goto L1
L2:
int_return %i1
@@ -99,7 +100,7 @@
def test_unformat_assembler_simple():
input = """
- int_add %i0, %i1, %i2
+ int_add %i0, %i1 -> %i2
int_return %i2
"""
regs = {}
@@ -107,7 +108,7 @@
assert regs['%i2'].kind == 'int'
assert regs['%i2'].index == 2
assert ssarepr.insns == [
- ('int_add', regs['%i0'], regs['%i1'], regs['%i2']),
+ ('int_add', regs['%i0'], regs['%i1'], '->', regs['%i2']),
('int_return', regs['%i2']),
]
@@ -134,3 +135,30 @@
(Label('L2'),),
('bar', TLabel('L1')),
]
+
+def test_unformat_assembler_lists():
+ input = """
+ foo F[%f0, %f3]
+ """
+ regs = {}
+ ssarepr = unformat_assembler(input, regs)
+ assert ssarepr.insns == [
+ ('foo', ListOfKind('float', [regs['%f0'], regs['%f3']]))
+ ]
+
+def test_unformat_switchdictdescr():
+ input = """
+ foo <SwitchDictDescr 4:L2, 5:L1>
+ L1:
+ L2:
+ """
+ regs = {}
+ ssarepr = unformat_assembler(input, regs)
+ sdd = ssarepr.insns[0][1]
+ assert ssarepr.insns == [
+ ('foo', sdd),
+ (Label('L1'),),
+ (Label('L2'),),
+ ]
+ assert isinstance(sdd, SwitchDictDescr)
+ assert sdd._labels == [(4, TLabel('L2')), (5, TLabel('L1'))]
Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_liveness.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_liveness.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_liveness.py Thu May 20 19:30:50 2010
@@ -1,153 +1,189 @@
-from pypy.jit.codewriter import support
from pypy.jit.codewriter.liveness import compute_liveness
-from pypy.jit.codewriter.test.test_flatten import fake_regallocs
-from pypy.jit.codewriter.flatten import flatten_graph, ListOfKind
-from pypy.jit.codewriter.format import assert_format
-from pypy.objspace.flow.model import SpaceOperation
+from pypy.jit.codewriter.format import unformat_assembler, assert_format
class TestFlatten:
- def make_graphs(self, func, values, type_system='lltype'):
- self.rtyper = support.annotate(func, values, type_system=type_system)
- return self.rtyper.annotator.translator.graphs
-
- def add_G_prefix(self, graph):
- """Add a 'G_' prefix to the opnames 'int_add' and 'int_mul'.
- Turn the arguments of float_add into a ListOfKind()."""
- def with_prefix(op):
- if op.opname in ('int_add', 'int_mul'):
- return SpaceOperation('G_' + op.opname, op.args, op.result)
- if op.opname == 'float_add':
- return SpaceOperation(op.opname,
- [ListOfKind('float', op.args)],
- op.result)
- return op
- #
- for block in graph.iterblocks():
- if block.operations:
- block.operations = map(with_prefix, block.operations)
-
- def encoding_test(self, func, args, expected,
- switches_require_liveness=False):
- graphs = self.make_graphs(func, args)
- self.add_G_prefix(graphs[0])
- compute_liveness(graphs[0], switches_require_liveness)
- ssarepr = flatten_graph(graphs[0], fake_regallocs())
- assert_format(ssarepr, expected)
+ def liveness_test(self, input, output):
+ ssarepr = unformat_assembler(input)
+ compute_liveness(ssarepr)
+ assert_format(ssarepr, output)
def test_simple_no_live(self):
- def f(n):
- return n + 10
- self.encoding_test(f, [5], """
+ self.liveness_test("""
-live-
- G_int_add %i0, $10, %i1
- int_return %i1
+ int_add %i0, $10 -> %i1
+ """, """
+ -live-
+ int_add %i0, $10 -> %i1
""")
def test_simple(self):
- def f(n):
- return (n + 10) * (n + 3) * (n + 6)
- self.encoding_test(f, [5], """
+ self.liveness_test("""
+ -live-
+ int_add %i0, $10 -> %i1
+ -live-
+ int_add %i0, $3 -> %i2
+ -live-
+ int_mul %i1, %i2 -> %i3
+ -live-
+ int_add %i0, $6 -> %i4
+ -live-
+ int_mul %i3, %i4 -> %i5
+ int_return %i5
+ """, """
-live- %i0
- G_int_add %i0, $10, %i1
+ int_add %i0, $10 -> %i1
-live- %i0, %i1
- G_int_add %i0, $3, %i2
+ int_add %i0, $3 -> %i2
-live- %i0
- G_int_mul %i1, %i2, %i3
+ int_mul %i1, %i2 -> %i3
-live- %i3
- G_int_add %i0, $6, %i4
+ int_add %i0, $6 -> %i4
-live-
- G_int_mul %i3, %i4, %i5
+ int_mul %i3, %i4 -> %i5
int_return %i5
""")
def test_one_path(self):
- def f(x, y):
- if x+5:
- return x+1
- return y+2
- self.encoding_test(f, [5, 6], """
+ self.liveness_test("""
+ -live-
+ int_add %i0, $5 -> %i2
+ int_is_true %i2 -> %i3
+ goto_if_not %i3, L1
+ int_copy %i0 -> %i4
+ -live-
+ int_add %i4, $1 -> %i5
+ int_return %i5
+ ---
+ L1:
+ int_copy %i1 -> %i6
+ -live-
+ int_add %i6, $2 -> %i7
+ int_return %i7
+ """, """
-live- %i0, %i1
- G_int_add %i0, $5, %i2
- int_is_true %i2, %i3
+ int_add %i0, $5 -> %i2
+ int_is_true %i2 -> %i3
goto_if_not %i3, L1
- int_copy %i0, %i4
+ int_copy %i0 -> %i4
-live-
- G_int_add %i4, $1, %i5
+ int_add %i4, $1 -> %i5
int_return %i5
+ ---
L1:
- int_copy %i1, %i6
+ int_copy %i1 -> %i6
-live-
- G_int_add %i6, $2, %i7
+ int_add %i6, $2 -> %i7
int_return %i7
""")
def test_other_path(self):
- def f(x, y):
- if x+5:
- return x+y
- return x+2
- self.encoding_test(f, [5, 6], """
+ self.liveness_test("""
+ -live-
+ int_add %i0, $5 -> %i2
+ int_is_true %i2 -> %i3
+ goto_if_not %i3, L1
+ int_copy %i0 -> %i4
+ int_copy %i1 -> %i5
+ -live-
+ int_add %i4, %i5 -> %i6
+ int_return %i6
+ ---
+ L1:
+ int_copy %i0 -> %i7
+ -live-
+ int_add %i7, $2 -> %i8
+ int_return %i8
+ """, """
-live- %i0, %i1
- G_int_add %i0, $5, %i2
- int_is_true %i2, %i3
+ int_add %i0, $5 -> %i2
+ int_is_true %i2 -> %i3
goto_if_not %i3, L1
- int_copy %i0, %i4
- int_copy %i1, %i5
+ int_copy %i0 -> %i4
+ int_copy %i1 -> %i5
-live-
- G_int_add %i4, %i5, %i6
+ int_add %i4, %i5 -> %i6
int_return %i6
+ ---
L1:
- int_copy %i0, %i7
+ int_copy %i0 -> %i7
-live-
- G_int_add %i7, $2, %i8
+ int_add %i7, $2 -> %i8
int_return %i8
""")
def test_no_path(self):
- def f(x, y):
- if x+y:
- return x+5
- return x+2
- self.encoding_test(f, [5, 6], """
+ self.liveness_test("""
+ -live-
+ int_add %i0, %i1 -> %i2
+ int_is_true %i2 -> %i3
+ goto_if_not %i3, L1
+ int_copy %i0 -> %i4
+ -live-
+ int_add %i4, $5 -> %i5
+ int_return %i5
+ ---
+ L1:
+ int_copy %i0 -> %i6
+ -live-
+ int_add %i6, $2 -> %i7
+ int_return %i7
+ """, """
-live- %i0
- G_int_add %i0, %i1, %i2
- int_is_true %i2, %i3
+ int_add %i0, %i1 -> %i2
+ int_is_true %i2 -> %i3
goto_if_not %i3, L1
- int_copy %i0, %i4
+ int_copy %i0 -> %i4
-live-
- G_int_add %i4, $5, %i5
+ int_add %i4, $5 -> %i5
int_return %i5
+ ---
L1:
- int_copy %i0, %i6
+ int_copy %i0 -> %i6
-live-
- G_int_add %i6, $2, %i7
+ int_add %i6, $2 -> %i7
int_return %i7
""")
- def test_switch_require_liveness(self):
- def f(x, y):
- if x:
- return x
- return y
- self.encoding_test(f, [5, 6], """
- int_is_true %i0, %i2
- -live- %i0, %i1
- goto_if_not %i2, L1
- int_return %i0
- L1:
- int_return %i1
- """, switches_require_liveness=True)
-
def test_list_of_kind(self):
- def f(x, y, z, t):
- return (x + y) * (z + t)
- self.encoding_test(f, [5, 6, 3.2, 4.3], """
- -live- %f0, %f1
- G_int_add %i0, %i1, %i2
- float_add F[%f0, %f1], %f2
- cast_int_to_float %i2, %f3
- float_mul %f3, %f2, %f4
- float_return %f4
+ self.liveness_test("""
+ -live-
+ stub
+ foobar F[%f0]
+ """, """
+ -live- %f0
+ stub
+ foobar F[%f0]
+ """)
+
+ def test_switch(self):
+ self.liveness_test("""
+ goto_maybe L1
+ -live-
+ stub
+ fooswitch <SwitchDictDescr 4:L2, 5:L3>
+ ---
+ L3:
+ int_return %i7
+ ---
+ L1:
+ int_return %i4
+ ---
+ L2:
+ int_return %i3
+ """, """
+ goto_maybe L1
+ -live- %i3, %i7
+ stub
+ fooswitch <SwitchDictDescr 4:L2, 5:L3>
+ ---
+ L3:
+ int_return %i7
+ ---
+ L1:
+ int_return %i4
+ ---
+ L2:
+ int_return %i3
""")
More information about the Pypy-commit
mailing list