[pypy-svn] r73764 - in pypy/branch/blackhole-improvement/pypy: jit/metainterp jit/metainterp/test tool/algo
arigo at codespeak.net
arigo at codespeak.net
Thu Apr 15 15:27:22 CEST 2010
Author: arigo
Date: Thu Apr 15 15:27:20 2010
New Revision: 73764
Added:
pypy/branch/blackhole-improvement/pypy/jit/metainterp/codewriter2.py (contents, props changed)
pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_codewriter2.py (contents, props changed)
Modified:
pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_codewriter.py
pypy/branch/blackhole-improvement/pypy/tool/algo/color.py
Log:
For now, start from scratch a codewriter2. The coloring tests
pass.
Added: pypy/branch/blackhole-improvement/pypy/jit/metainterp/codewriter2.py
==============================================================================
--- (empty file)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/codewriter2.py Thu Apr 15 15:27:20 2010
@@ -0,0 +1,77 @@
+import sys
+from pypy.tool.algo.color import DependencyGraph
+from pypy.tool.algo.unionfind import UnionFind
+from pypy.objspace.flow.model import Variable
+
+
+class BytecodeMaker(object):
+ DEBUG_REGALLOC = False
+
+ def __init__(self, graph):
+ self.graph = graph
+
+ def generate(self):
+ self.register_allocation()
+
+ def register_allocation(self):
+ dg = DependencyGraph()
+ #
+ pendingblocks = list(self.graph.iterblocks())
+ for block in pendingblocks:
+ # Compute die_at = {Variable: index_of_operation_with_last_usage}
+ die_at = dict.fromkeys(block.inputargs, 0)
+ for i, op in enumerate(block.operations):
+ for v in op.args:
+ if isinstance(v, Variable):
+ die_at[v] = i
+ if op.result is not None:
+ die_at[op.result] = i
+ die_at[block.exitswitch] = sys.maxint
+ for link in block.exits:
+ for v in link.args:
+ die_at[v] = sys.maxint
+ # Add the variables of this block to the dependency graph
+ for i, v in enumerate(block.inputargs):
+ dg.add_node(v)
+ for j in range(i):
+ dg.add_edge(block.inputargs[j], v)
+ livevars = set(block.inputargs)
+ die_at = [(value, key) for (key, value) in die_at.items()]
+ die_at.sort()
+ die_at.append((sys.maxint,))
+ die_index = 0
+ for i, op in enumerate(block.operations):
+ while die_at[die_index][0] == i:
+ livevars.remove(die_at[die_index][1])
+ die_index += 1
+ if op.result is not None:
+ livevars.add(op.result)
+ dg.add_node(op.result)
+ for v in livevars:
+ dg.add_edge(v, op.result)
+ #
+ uf = UnionFind()
+ while pendingblocks:
+ block = pendingblocks.pop()
+ # Aggressively try to coalesce each source variable with its target
+ for link in block.exits:
+ for i, v in enumerate(link.args):
+ if isinstance(v, Variable):
+ w = link.target.inputargs[i]
+ v0 = uf.find_rep(v)
+ w0 = uf.find_rep(w)
+ if v0 not in dg.neighbours[w0]:
+ _, rep, _ = uf.union(v0, w0)
+ assert rep is v0
+ dg.coalesce(w0, v0)
+ #
+ self._coloring = dg.find_node_coloring()
+ self._unionfind = uf
+ if self.DEBUG_REGALLOC:
+ for block in self.graph.iterblocks():
+ print block
+ for v in block.getvariables():
+ print '\t', v, '\t', self.getcolor(v)
+
+ def getcolor(self, v):
+ return self._coloring[self._unionfind.find_rep(v)]
Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_codewriter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_codewriter.py (original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_codewriter.py Thu Apr 15 15:27:20 2010
@@ -174,115 +174,6 @@
rtyper = self.metainterp_sd.cpu.rtyper
return graphof(rtyper.annotator.translator, func)
- def encoding_test(self, func, args, ...):
- graphs = self.make_graphs(func, args)
- cw = CodeWriter(self.rtyper)
- cw.candidate_graphs = graphs
- cw._start(self.metainterp_sd, None)
- maker = BytecodeMaker(cw, (graphs[0], None), False)
- maker.generate()
- ...
-
- def test_bytecodemaker_generate_simple(self):
- def f(n):
- return n + 10
- self.encoding_test(f, [5], """
- [%i0]
- int_add %i0 $10 %i0
- int_return %i0
- """)
-
- def test_bytecodemaker_generate_regs(self):
- def f(a, b, c):
- return (((a + 10) * 2) + (b - c)) * a
- self.encoding_test(f, [5, 6, 7], """
- [%i0, %i1, %i2]
- int_add %i0 $10 %i3
- int_mul %i3 $2 %i3
- int_sub %i1 %i2 %i1
- int_add %i3 %i1 %i1
- int_mul %i1 %i0 %i0
- int_return %i0
- """)
-
- def test_bytecodemaker_generate_loop(self):
- def f(a, b):
- while a > 0:
- b += a
- a -= 1
- return b
- self.encoding_test(f, [5, 6], """
- [%i0, %i1]
- L0:
- goto_if_not_int_gt %i0 $0 L1
- int_add %i1 %i0 %i1
- int_sub %i0 $1 %i0
- goto L0
- L1:
- int_return %i1
- """)
-
- def test_bytecodemaker_generate_swap(self):
- def f(a, b):
- while a > 0:
- a, b = b, b+a
- return b
- self.encoding_test(f, [5, 6], """
- [%i0, %i1]
- L0:
- goto_if_not_int_gt %i0 $0 L1
- int_add %i1 %i0 %i0
- int_swap %i0 %i1
- goto L0
- L1:
- int_return %i1
- """)
-
- def test_bytecodemaker_generate_cycle(self):
- def f(a, b, c):
- while a > 0:
- a, b, c = b, c, a
- return b
- self.encoding_test(f, [5, 6], """
- [%i0, %i1, %i2]
- L0:
- goto_if_not_int_gt %i0 $0 L1
- int_swap_cycle [%i0, %i2, %i1]
- goto L0
- L1:
- int_return %i1
- """)
-
- def test_bytecodemaker_generate_same_as_var(self):
- def f(a, b, c):
- while a > 0:
- b = c
- return b
- self.encoding_test(f, [5, 6], """
- [%i0, %i1, %i2]
- L0:
- goto_if_not_int_gt %i0 $0 L1
- int_same_as %i2 %i1
- goto L0
- L1:
- int_return %i1
- """)
-
- def test_bytecodemaker_generate_same_as_const(self):
- def f(a, b, c):
- while a > 0:
- b = -17
- return b
- self.encoding_test(f, [5, 6], """
- [%i0, %i1, %i2]
- L0:
- goto_if_not_int_gt %i0 $0 L1
- int_same_as $-17 %i1
- goto L0
- L1:
- int_return %i1
- """)
-
def test_basic(self):
def f(n):
return n + 10
Added: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_codewriter2.py
==============================================================================
--- (empty file)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_codewriter2.py Thu Apr 15 15:27:20 2010
@@ -0,0 +1,165 @@
+from pypy.jit.metainterp import support
+from pypy.jit.metainterp.codewriter2 import BytecodeMaker
+
+
+class TestBytecodeMaker:
+
+ 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 coloring_test(self, func, args, expected_lambda):
+ graphs = self.make_graphs(func, args)
+ maker = BytecodeMaker(graphs[0])
+ maker.register_allocation()
+ expected = expected_lambda(graphs[0].startblock)
+ for v, num in expected.items():
+ print '\t%s\tcolor %d\texpected %d' % (v, maker.getcolor(v), num)
+ for v, num in expected.items():
+ assert maker.getcolor(v) == num
+
+ def encoding_test(self, func, args, expected):
+ graphs = self.make_graphs(func, args)
+ maker = BytecodeMaker(graphs[0])
+ maker.generate()
+ asm = maker.format_assembler()
+ expected = str(py.code.Source(expected)).strip()
+ assert asm == expected + '\n'
+
+ def test_coloring_simple(self):
+ def f(n):
+ return n + 10
+ self.coloring_test(f, [5],
+ lambda startblock:
+ {startblock.inputargs[0]: 0,
+ startblock.operations[0].result: 0,
+ startblock.exits[0].target.inputargs[0]: 0})
+
+ def test_coloring_bigblock(self):
+ def f(a, b, c):
+ return (((a + 10) * 2) + (b - c)) * a
+ self.coloring_test(f, [5, 6, 7],
+ lambda startblock:
+ {startblock.inputargs[0]: 0,
+ startblock.inputargs[1]: 1,
+ startblock.inputargs[2]: 2,
+ startblock.operations[0].result: 3,
+ startblock.operations[1].result: 3,
+ startblock.operations[2].result: 1,
+ startblock.operations[3].result: 1,
+ startblock.operations[4].result: 0,
+ startblock.exits[0].target.inputargs[0]: 0})
+
+ def test_bytecodemaker_generate_simple(self):
+ def f(n):
+ return n + 10
+ self.encoding_test(f, [5], """
+ [%i0]
+ int_add %i0, $10, %i0
+ int_return %i0
+ """)
+
+ def test_bytecodemaker_generate_bigblock(self):
+ def f(a, b, c):
+ return (((a + 10) * 2) + (b - c)) * a
+ self.encoding_test(f, [5, 6, 7], """
+ [%i0, %i1, %i2]
+ int_add %i0, $10, %i3
+ int_mul %i3, $2, %i3
+ int_sub %i1, %i2, %i1
+ int_add %i3, %i1, %i1
+ int_mul %i1, %i0, %i0
+ int_return %i0
+ """)
+
+ def test_bytecodemaker_generate_loop(self):
+ def f(a, b):
+ while a > 0:
+ b += a
+ a -= 1
+ return b
+ self.encoding_test(f, [5, 6], """
+ [%i0, %i1]
+ L0:
+ goto_if_not_int_gt %i0, $0, L1
+ int_add %i1, %i0, %i1
+ int_sub %i0, $1, %i0
+ goto L0
+ L1:
+ int_return %i1
+ """)
+
+ def test_bytecodemaker_generate_swap(self):
+ def f(a, b):
+ while a > 0:
+ a, b = b, b+a
+ return b
+ self.encoding_test(f, [5, 6], """
+ [%i0, %i1]
+ L0:
+ goto_if_not_int_gt %i0, $0, L1
+ int_add %i1, %i0, %i0
+ int_swap %i0, %i1
+ goto L0
+ L1:
+ int_return %i1
+ """)
+
+ def test_bytecodemaker_generate_cycle(self):
+ def f(a, b, c):
+ while a > 0:
+ a, b, c = b, c, a
+ return b
+ self.encoding_test(f, [5, 6, 7], """
+ [%i0, %i1, %i2]
+ L0:
+ goto_if_not_int_gt %i0, $0, L1
+ int_swap_cycle [%i0, %i2, %i1]
+ goto L0
+ L1:
+ int_return %i1
+ """)
+
+ def test_bytecodemaker_generate_same_as_var(self):
+ def f(a, b, c):
+ while a > 0:
+ b = c
+ return b
+ self.encoding_test(f, [5, 6, 7], """
+ [%i0, %i1, %i2]
+ L0:
+ goto_if_not_int_gt %i0, $0, L1
+ int_same_as %i2, %i1
+ goto L0
+ L1:
+ int_return %i1
+ """)
+
+ def test_bytecodemaker_generate_same_as_const(self):
+ def f(a, b):
+ while a > 0:
+ b = -17
+ return b
+ self.encoding_test(f, [5, 6], """
+ [%i0, %i1]
+ L0:
+ goto_if_not_int_gt %i0, $0, L1
+ int_same_as $-17, %i1
+ goto L0
+ L1:
+ int_return %i1
+ """)
+
+ def test_bytecodemaker_generate_return_const(self):
+ def f(a, b):
+ if a > b:
+ b = -17
+ return 1 + b
+ self.encoding_test(f, [5, 6], """
+ [%i0, %i1]
+ goto_if_not_int_gt %i0, %i1, L1
+ int_return $-16
+ L1:
+ int_add $1, %i1, %i0
+ int_return %i0
+ """)
Modified: pypy/branch/blackhole-improvement/pypy/tool/algo/color.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/tool/algo/color.py (original)
+++ pypy/branch/blackhole-improvement/pypy/tool/algo/color.py Thu Apr 15 15:27:20 2010
@@ -2,21 +2,33 @@
class DependencyGraph(object):
def __init__(self):
- self.nodes = []
+ self._all_nodes = []
self.neighbours = {}
def add_node(self, v):
assert v not in self.neighbours, "duplicate vertex %r" % (v,)
- self.nodes.append(v)
+ self._all_nodes.append(v)
self.neighbours[v] = set()
def add_edge(self, v1, v2):
self.neighbours[v1].add(v2)
self.neighbours[v2].add(v1)
+ def coalesce(self, vold, vnew):
+ """Remove vold from the graph, and attach all its edges to vnew."""
+ for n in self.neighbours.pop(vold):
+ self.neighbours[n].remove(vold)
+ self.neighbours[n].add(vnew)
+ self.neighbours[vnew].add(n)
+ # we should remove vold from self._all_nodes, but it's too costly
+ # so we rely on getnodes() to filter self._all_nodes.
+
+ def getnodes(self):
+ return [v for v in self._all_nodes if v in self.neighbours]
+
def lexicographic_order(self):
"""Enumerate a lexicographic breath-first ordering of the nodes."""
- sigma = [self.nodes[:]]
+ sigma = [self.getnodes()[::-1]]
while sigma:
v = sigma[0].pop()
yield v
More information about the Pypy-commit
mailing list