[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