[pypy-svn] rev 1512 - in pypy/trunk/src/pypy/translator: . test
hpk at codespeak.net
hpk at codespeak.net
Wed Oct 1 21:11:48 CEST 2003
Author: hpk
Date: Wed Oct 1 21:11:47 2003
New Revision: 1512
Added:
pypy/trunk/src/pypy/translator/simplify.py
pypy/trunk/src/pypy/translator/test/test_simplify.py
Modified:
pypy/trunk/src/pypy/translator/flowmodel.py
Log:
added jonathan's eliminate_empty_blocks function
+ some tests we came up with (which are hard to read)
Modified: pypy/trunk/src/pypy/translator/flowmodel.py
==============================================================================
--- pypy/trunk/src/pypy/translator/flowmodel.py (original)
+++ pypy/trunk/src/pypy/translator/flowmodel.py Wed Oct 1 21:11:47 2003
@@ -117,7 +117,7 @@
def mkentrymap(self):
"""Create a map from nodes in the graph to back edge lists"""
- entrymap = {}
+ entrymap = { self.startblock: []}
for node in self.flatten():
for edge in node.getedges():
entrymap.setdefault(edge, []).append(node)
Added: pypy/trunk/src/pypy/translator/simplify.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/translator/simplify.py Wed Oct 1 21:11:47 2003
@@ -0,0 +1,55 @@
+"""
+generate Pyrex files from the flowmodel.
+
+"""
+import autopath
+from pypy.tool import test
+from pypy.interpreter.baseobjspace import ObjSpace
+from pypy.translator.flowmodel import *
+
+
+def eliminate_empty_blocks(graph):
+ """simplify_vars()
+ Things we know we can remove:
+ 1. Basic blocks that do not contain any operations.
+ When this happens, we need to replace the preceeding branch with the
+ following branch. Arguments of the following branch should be
+ overwritten with the arguments of the preceeding branch, but any
+ additional arguments should be kept.
+ 2. Branches into basic blocks that have a single entry point.
+ At this point, we can append all the operations of the following basic
+ block to the preceeding basic block (but renaming variables with the
+ appropriate arguments.)
+ """
+ nodelist = graph.flatten()
+ entrymap = graph.mkentrymap()
+ victims = True
+ while victims:
+ victims = False
+ victimlist = []
+ entrymap = graph.mkentrymap()
+ for node in graph.flatten():
+ if node in victimlist:
+ continue
+ if isinstance(node, BasicBlock) and len(node.operations) == 0:
+ prevnodes = entrymap[node]
+ if len(prevnodes) != 1:
+ continue
+ prevbranch = prevnodes[0]
+ nextbranch = node.branch
+ if not isinstance(prevbranch, Branch) or isinstance(nextbranch, EndBranch):
+ continue
+ #
+ if len(prevbranch.args) > len(nextbranch.args):
+ prevbranch.args = prevbranch.args[:len(nextbranch.args)]
+ else:
+ prevbranch.args.extend(nextbranch.args[len(prevbranch.args):])
+ prevbranch.target = nextbranch.target
+ targetentrylist = entrymap[nextbranch.target]
+ targetentrylist.remove(nextbranch)
+ targetentrylist.append(prevbranch)
+ victimlist.append(node)
+ victimlist.append(nextbranch)
+ victims = len(victimlist) > 0
+ return graph
+
Added: pypy/trunk/src/pypy/translator/test/test_simplify.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/translator/test/test_simplify.py Wed Oct 1 21:11:47 2003
@@ -0,0 +1,121 @@
+import autopath
+from pypy.tool import test
+from pypy.tool.udir import udir
+from pypy.translator.genpyrex import GenPyrex
+from pypy.translator.flowmodel import *
+from pypy.translator.test.buildpyxmodule import make_module_from_pyxstring
+from pypy.translator.simplify import eliminate_empty_blocks
+
+make_dot = 1
+
+if make_dot:
+ from pypy.translator.test.make_dot import make_dot
+else:
+ def make_dot(*args): pass
+
+class SimplifyTestCase(test.IntTestCase):
+ def setUp(self):
+ self.space = test.objspace('flow')
+
+ def make_graph(self, func):
+ """ make a pyrex-generated cfunction from the given func """
+ import inspect
+ try:
+ func = func.im_func
+ except AttributeError:
+ pass
+ name = func.func_name
+ funcgraph = self.space.build_flow(func)
+ funcgraph.source = inspect.getsource(func)
+ result = GenPyrex(funcgraph).emitcode()
+ return funcgraph
+
+ def xxxmake_cfunc(self, func):
+ """ make a pyrex-generated cfunction from the given func """
+ import inspect
+ try:
+ func = func.im_func
+ except AttributeError:
+ pass
+ name = func.func_name
+ funcgraph = self.space.build_flow(func)
+ funcgraph.source = inspect.getsource(func)
+ result = GenPyrex(funcgraph).emitcode()
+ make_dot(funcgraph, udir, 'ps')
+ mod = make_module_from_pyxstring(name, udir, result)
+ return getattr(mod, name)
+
+ def make_cfunc_from_graph (self, graph):
+ name = graph.functionname
+ result = GenPyrex(graph).emitcode()
+ make_dot(graph, udir, 'ps')
+ mod = make_module_from_pyxstring(name, udir, result)
+ return getattr(mod, name)
+
+ #____________________________________________________
+ def simple_while(i):
+ j = 0
+ while j < i:
+ j = j + 1
+ return j
+
+ def test_simple_func_identical_results(self):
+ graph = self.make_graph(self.simple_while)
+ f0 = self.make_cfunc_from_graph(graph)
+ newgraph = eliminate_empty_blocks(graph)
+ newgraph.functionname = 'simple_while_optimized'
+ f1 = self.make_cfunc_from_graph(newgraph)
+ self.assertEquals(f0(3), f1(3))
+ self.assertEquals(f1(3), self.simple_while.im_func(3))
+
+class TestFlowModelSimplification(test.IntTestCase):
+ def test_eliminate_empty_block_simple(self):
+ result = Variable("result")
+ endbranch = EndBranch(result)
+ op = SpaceOperation('',[],[])
+ block2 = BasicBlock([result], [result], [op], endbranch)
+ branch2 = Branch([result], block2)
+ block1 = BasicBlock([result], [result], [], branch2)
+ branch1 = Branch([result], block1)
+ startblock = BasicBlock([result], [result], [], branch1)
+ fun = FunctionGraph(startblock, "f")
+
+ eliminate_empty_blocks(fun)
+ nodelist = fun.flatten()
+
+ self.assert_(startblock in nodelist)
+ self.assert_(block1 not in nodelist)
+
+ def test_eliminate_empty_block_renaming(self):
+ result = Variable("result")
+ x = Variable("x")
+ y = Variable("y")
+ zero = Constant(0)
+ endbranch = EndBranch(result)
+ op = SpaceOperation('',[],[])
+
+ block2 = BasicBlock([result], [], [op], endbranch)
+
+ branch2 = Branch([y,zero], block2)
+
+ block1 = BasicBlock([x], [], [], branch2)
+
+ branch1 = Branch([x], block1)
+
+ startblock = BasicBlock([x], [], [], branch1)
+ fun = FunctionGraph(startblock, "f")
+ make_dot(fun, udir, 'ps')
+ eliminate_empty_blocks(fun)
+ fun.functionname = 'f_optimized'
+ make_dot(fun, udir, 'ps')
+ nodelist = fun.flatten()
+
+ self.assert_(startblock in nodelist)
+ self.assert_(block1 not in nodelist)
+ self.assert_(block1 not in nodelist)
+ self.assertEquals(startblock.branch.args[0], x)
+ self.assertEquals(startblock.branch.args[1], zero)
+
+
+if __name__ == '__main__':
+ test.main()
More information about the Pypy-commit
mailing list