Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: better-storesink
Changeset: r87235:c701f3c76e7c
Date: 2016-09-19 21:53 +0200
http://bitbucket.org/pypy/pypy/changeset/c701f3c76e7c/

Log:    loop_blocks was broken in complex cases

diff --git a/rpython/translator/backendopt/cse.py 
b/rpython/translator/backendopt/cse.py
--- a/rpython/translator/backendopt/cse.py
+++ b/rpython/translator/backendopt/cse.py
@@ -304,7 +304,46 @@
         result._clear_heapcache_for_loop_blocks(loop_blocks)
     return result
 
-def loop_blocks(graph):
+def compute_reachability_no_backedges(graph, backedges):
+    reachable = {}
+    blocks = list(graph.iterblocks())
+    # Reversed order should make the reuse path more likely.
+    for block in reversed(blocks):
+        reach = set()
+        scheduled = [block]
+        while scheduled:
+            current = scheduled.pop()
+            for link in current.exits:
+                if link in backedges:
+                    continue
+                if link.target in reachable:
+                    reach.add(link.target)
+                    reach = reach | reachable[link.target]
+                    continue
+                if link.target not in reach:
+                    reach.add(link.target)
+                    scheduled.append(link.target)
+        reachable[block] = reach
+    return reachable
+
+def loop_blocks(graph, backedges, entrymap):
+    reachable_no_backedges = compute_reachability_no_backedges(graph, 
backedges)
+    reachable = support.compute_reachability(graph)
+    result = {}
+    for block in graph.iterblocks():
+        entering_backedges = [link for link in entrymap[block]
+                if link in backedges]
+        if not entering_backedges:
+            # no backedge entries
+            continue
+        loop_blocks = {block}
+        for target in reachable_no_backedges[block]:
+            if any(link.prevblock in reachable[target]
+                       for link in entering_backedges):
+                loop_blocks.add(target)
+        result[block] = loop_blocks
+    return result
+
     loop_blocks = support.find_loop_blocks(graph)
     result = {}
     for loop_block, start in loop_blocks.iteritems():
@@ -319,8 +358,8 @@
     def transform(self, graph):
         variable_families = 
ssa.DataFlowFamilyBuilder(graph).get_variable_families()
         entrymap = mkentrymap(graph)
-        loops = loop_blocks(graph)
         backedges = support.find_backedges(graph)
+        loops = loop_blocks(graph, backedges, entrymap)
         todo = collections.deque([graph.startblock])
         caches_to_merge = collections.defaultdict(list)
         done = set()
diff --git a/rpython/translator/backendopt/test/test_cse.py 
b/rpython/translator/backendopt/test/test_cse.py
--- a/rpython/translator/backendopt/test/test_cse.py
+++ b/rpython/translator/backendopt/test/test_cse.py
@@ -1,6 +1,6 @@
 import pytest
 from rpython.translator.translator import TranslationContext, graphof
-from rpython.translator.backendopt.cse import CSE, Cache
+from rpython.translator.backendopt.cse import CSE, Cache, loop_blocks
 from rpython.flowspace.model import Variable, Constant
 from rpython.translator.backendopt import removenoops
 from rpython.flowspace.model import checkgraph, summary
@@ -354,6 +354,28 @@
             return res
         self.check(f, [int], getfield=1)
 
+    def test_loopinvariant_heap_merge_nested(self):
+        class A(object):
+            pass
+        def f(i):
+            res = 0
+            y = 0
+            while y < i:
+                y += 1
+                x = i
+                a = A()
+                if i == 0:
+                    a.x = 1
+                else:
+                    a.x = i
+                while x:
+                    x -= 1
+                    res += a.x
+                    if x % 1000 == 1:
+                        a.x = 5
+            return res
+        self.check(f, [int], getfield=1)
+
     def test_direct_merge(self):
         def f(i):
             a = i + 1
@@ -567,3 +589,45 @@
     assert not needs_adding
     assert res is v2
 
+
+def test_loop_blocks():
+    from rpython.flowspace.model import mkentrymap
+    from rpython.translator.backendopt import support
+    class A(object): pass
+    def f(i):
+        res = 0
+        y = 0
+        while y < i: # block1
+            y += 1 # block2
+            x = i
+            a = A()
+            if i == 0:
+                a.x = 1 # block3
+            else:
+                a.x = i # block4
+            while x: # block5
+                x -= 1 # block6
+                res += a.x
+                if x % 1000 == 1:
+                    a.x = 5 # block7
+        return res # block8
+
+    t = TranslationContext()
+    t.buildannotator().build_types(f, [int])
+    t.buildrtyper().specialize()
+    graph = graphof(t, f)
+    startblock = graph.startblock
+    block1 = startblock.exits[0].target
+    block2 = block1.exits[1].target
+    block3 = block2.exits[0].target
+    block4 = block2.exits[1].target
+    block5 = block4.exits[0].target
+    block6 = block5.exits[1].target
+    block7 = block6.exits[1].target
+
+    loops = loop_blocks(graph, support.find_backedges(graph),
+                        mkentrymap(graph))
+    assert loops == {
+        block1: {block1, block2, block3, block4, block5, block6, block7},
+        block5: {block5, block6, block7},
+    }
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to