[pypy-svn] r22221 - in pypy/dist/pypy/translator/backendopt: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Mon Jan 16 15:21:22 CET 2006


Author: cfbolz
Date: Mon Jan 16 15:21:21 2006
New Revision: 22221

Modified:
   pypy/dist/pypy/translator/backendopt/escape.py
   pypy/dist/pypy/translator/backendopt/test/test_escape.py
Log:
detect loops


Modified: pypy/dist/pypy/translator/backendopt/escape.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/escape.py	(original)
+++ pypy/dist/pypy/translator/backendopt/escape.py	Mon Jan 16 15:21:21 2006
@@ -338,6 +338,59 @@
             return False
     return True
 
+def find_backedges(graph):
+    """finds the backedges in the flow graph"""
+    scheduled = [graph.startblock]
+    seen = {}
+    backedges = []
+    while scheduled:
+        current = scheduled.pop()
+        seen[current] = True
+        for link in current.exits:
+            if link.target in seen:
+                backedges.append(link)
+            else:
+                scheduled.append(link.target)
+    return backedges
+
+def compute_reachability(graph):
+    reachable = {}
+    for block in graph.iterblocks():
+        reach = {}
+        scheduled = [block]
+        while scheduled:
+            current = scheduled.pop()
+            for link in current.exits:
+                if link.target in reachable:
+                    reach = setunion(reach, reachable[link.target])
+                    continue
+                if link.target not in reach:
+                    reach[link.target] = True
+        reachable[block] = reach
+    return reachable
+
+def find_loop_blocks(graph):
+    """find the blocks in a graph that are part of a loop"""
+    loop = {}
+    reachable = compute_reachability(graph)
+    for backedge in find_backedges(graph):
+        start = backedge.target
+        end = backedge.prevblock
+        loop[start] = start
+        loop[end] = start
+        scheduled = [start]
+        seen = {}
+        while scheduled:
+            current = scheduled.pop()
+            connects = end in reachable[current]
+            seen[current] = True
+            if connects:
+                loop[current] = start
+            for link in current.exits:
+                if link.target not in seen:
+                    scheduled.append(link.target)
+    return loop
+
 def malloc_to_stack(t):
     aib = AbstractDataFlowInterpreter(t)
     for graph in t.graphs:

Modified: pypy/dist/pypy/translator/backendopt/test/test_escape.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_escape.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_escape.py	Mon Jan 16 15:21:21 2006
@@ -1,5 +1,6 @@
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator.backendopt.escape import AbstractDataFlowInterpreter, malloc_to_stack
+from pypy.translator.backendopt.escape import find_backedges, find_loop_blocks
 from pypy.rpython.llinterp import LLInterpreter
 
 def build_adi(function, types):
@@ -346,6 +347,33 @@
     assert not state.does_escape()
 
 #__________________________________________________________
+# test loop detection
+
+def test_find_backedges():
+    def f(k):
+        result = 0
+        for i in range(k):
+            result += 1
+        for j in range(k):
+            result += 1
+        return result
+    t, adi, graph = build_adi(f, [int])
+    backedges = find_backedges(graph)
+    assert len(backedges) == 2
+
+def test_find_loop_blocks():
+    def f(k):
+        result = 0
+        for i in range(k):
+            result += 1
+        for j in range(k):
+            result += 1
+        return result
+    t, adi, graph = build_adi(f, [int])
+    loop_blocks = find_loop_blocks(graph)
+    assert len(loop_blocks) == 4
+
+#__________________________________________________________
 # malloc removal tests
 
 def test_remove_simple():



More information about the Pypy-commit mailing list