[pypy-svn] r50878 - pypy/branch/loops-for-gcc/pypy/translator/c

arigo at codespeak.net arigo at codespeak.net
Tue Jan 22 14:13:45 CET 2008


Author: arigo
Date: Tue Jan 22 14:13:44 2008
New Revision: 50878

Modified:
   pypy/branch/loops-for-gcc/pypy/translator/c/funcgen.py
Log:
Obscure and not really tested logic.


Modified: pypy/branch/loops-for-gcc/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/loops-for-gcc/pypy/translator/c/funcgen.py	(original)
+++ pypy/branch/loops-for-gcc/pypy/translator/c/funcgen.py	Tue Jan 22 14:13:44 2008
@@ -34,6 +34,7 @@
                        functionname
                        currentblock
                        blocknum
+                       backlinks
                        oldgraph""".split()
 
     def __init__(self, graph, db, exception_policy=None, functionname=None):
@@ -112,14 +113,58 @@
             self.db.gctransformer.inline_helpers(graph)
         return graph
 
+    def order_blocks(self):
+        from pypy.tool.algo import graphlib
+        self.blocknum = {}
+        self.backlinks = {}
+        vertices = {}
+        edge_list = []
+        for index, block in enumerate(self.graph.iterblocks()):
+            self.blocknum[block] = index
+            vertices[block] = True
+            for link in block.exits:
+                edge_list.append(graphlib.Edge(block, link.target))
+        edges = graphlib.make_edge_dict(edge_list)
+        cycles = graphlib.all_cycles(self.graph.startblock, vertices, edges)
+        cycles.sort(key=len)
+        for cycle in cycles:
+            for edge in cycle:
+                if edge.source not in vertices:
+                    break    # cycle overlaps already-seen blocks
+            else:
+                # make this cycle a C-level loop
+                def edge2link(edge):
+                    for link in edge.source.exits:
+                        if link.target is edge.target:
+                            return link
+                    raise AssertionError("an edge's link has gone missing")
+
+                edges = []
+                for i, edge in enumerate(cycle):
+                    v = edge.source.exitswitch
+                    if isinstance(v, Variable) and len(edge.source.exits) == 2:
+                        TYPE = self.lltypemap(v)
+                        if TYPE in (Bool, PyObjPtr):
+                            edges.append((self.blocknum[edge.source], i))
+                if not edges:
+                    continue
+                _, i = min(edges)
+                backedge = cycle[i-1]
+                forwardedge = cycle[i]
+                headblock = backedge.target
+                assert headblock is forwardedge.source
+                self.backlinks[edge2link(backedge)] = None
+                exitcase = edge2link(forwardedge).exitcase
+                assert exitcase in (False, True)
+                self.backlinks[headblock] = exitcase
+                for edge in cycle:
+                    del vertices[edge.target]
+
     def implementation_begin(self):
         self.oldgraph = self.graph
         self.graph = self.patch_graph(copy_graph=True)
         SSI_to_SSA(self.graph)
         self.collect_var_and_types()
-        self.blocknum = {}
-        for block in self.graph.iterblocks():
-            self.blocknum[block] = len(self.blocknum)
         db = self.db
         lltypes = {}
         for v in self.vars:
@@ -127,6 +172,7 @@
             typename = db.gettype(T)
             lltypes[id(v)] = T, typename
         self.lltypes = lltypes
+        self.order_blocks()
 
     def graphs_to_patch(self):
         yield self.graph
@@ -135,6 +181,7 @@
         self.lltypes = None
         self.vars = None
         self.blocknum = None
+        self.backlinks = None
         self.currentblock = None
         self.graph = self.oldgraph
         del self.oldgraph
@@ -204,9 +251,10 @@
         graph = self.graph
 
         # generate the body of each block
-        for block in graph.iterblocks():
+        allblocks = [(num, block) for (block, num) in self.blocknum.items()]
+        allblocks.sort()
+        for myblocknum, block in allblocks:
             self.currentblock = block
-            myblocknum = self.blocknum[block]
             yield ''
             yield 'block%d:' % myblocknum
             for i, op in enumerate(block.operations):
@@ -231,6 +279,25 @@
                 assert len(block.exits) == 1
                 for op in self.gen_link(block.exits[0]):
                     yield op
+            elif block in self.backlinks:
+                looplink, exitlink = block.exits
+                if looplink.exitcase != self.backlinks[block]:
+                    looplink, exitlink = exitlink, looplink
+                assert looplink.exitcase == self.backlinks[block]
+                assert exitlink.exitcase == (not self.backlinks[block])
+                expr = self.expr(block.exitswitch)
+                if not looplink.exitcase:
+                    expr = '!' + expr
+                yield 'while (%s) {' % expr
+                for op in self.gen_link(looplink):
+                    yield '\t' + op
+                yield '\t  block%d_back:' % myblocknum
+                for i, op in enumerate(block.operations):
+                    for line in self.gen_op(op):
+                        yield '\t' + line
+                yield '}'
+                for op in self.gen_link(exitlink):
+                    yield op
             else:
                 assert block.exitswitch != c_last_exception
                 # block ending in a switch on a value
@@ -303,7 +370,10 @@
             assignments.append((a2typename, dest, src))
         for line in gen_assignments(assignments):
             yield line
-        yield 'goto block%d;' % self.blocknum[link.target]
+        label = 'block%d' % self.blocknum[link.target]
+        if link in self.backlinks:
+            label += '_back'
+        yield 'goto %s;' % label
 
     def gen_op(self, op):
         macro = 'OP_%s' % op.opname.upper()



More information about the Pypy-commit mailing list