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

arigo at codespeak.net arigo at codespeak.net
Sat Sep 24 13:36:31 CEST 2005


Author: arigo
Date: Sat Sep 24 13:36:27 2005
New Revision: 17822

Modified:
   pypy/dist/pypy/translator/backendopt/ssa.py
   pypy/dist/pypy/translator/backendopt/test/test_ssa.py
Log:
Rewrote the data_flow_families() algorithm, which seems to consume a lot of
time.

Made up a couple of tests for ssa.py.



Modified: pypy/dist/pypy/translator/backendopt/ssa.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/ssa.py	(original)
+++ pypy/dist/pypy/translator/backendopt/ssa.py	Sat Sep 24 13:36:27 2005
@@ -8,33 +8,47 @@
     all following variables where the value is just passed unmerged into the
     next block.
     """
-    entrymaplist = mkentrymap(graph).items()
+
+    # Build a list of "unification opportunities": for each block and each 'n',
+    # an "opportunity" is the list of the block's nth input variable plus
+    # the nth output variable from each of the incoming links.
+    opportunities = []
+    for block, links in mkentrymap(graph).items():
+        if block is graph.startblock:
+            continue
+        assert links
+        for n, inputvar in enumerate(block.inputargs):
+            vars = [inputvar]
+            for link in links:
+                var = link.args[n]
+                if not isinstance(var, Variable):
+                    break
+                vars.append(var)
+            else:
+                # if no Constant found in the incoming links
+                opportunities.append(vars)
+
+    # An "opportunitiy" that lists exactly two distinct variables means that
+    # the two variables can be unified.  We maintain the unification status in
+    # 'variable_families'.  When variables are unified, it might reduce the
+    # number of distinct variables and thus open other "opportunities" for
+    # unification.
     progress = True
     variable_families = UnionFind()
-
-    # group variables by families; a family of variables will be identified.
     while progress:
         progress = False
-        for block, links in entrymaplist:
-            if block is graph.startblock:
-                continue
-            assert links
-            for i in range(len(block.inputargs)):
-                # list of possible vars that can arrive in i'th position
-                v1 = block.inputargs[i]
-                v1 = variable_families.find_rep(v1)
-                inputs = {v1: True}
-                key = []
-                for link in links:
-                    v = link.args[i]
-                    if not isinstance(v, Variable):
-                        break
-                    v = variable_families.find_rep(v)
-                    inputs[v] = True
-                else:
-                    if len(inputs) == 2:
-                        variable_families.union(*inputs)
-                        progress = True
+        pending_opportunities = []
+        for vars in opportunities:
+            repvars = [variable_families.find_rep(v1) for v1 in vars]
+            repvars = dict.fromkeys(repvars).keys()
+            if len(repvars) > 2:
+                # cannot unify now, but maybe later?
+                pending_opportunities.append(repvars)
+            elif len(repvars) == 2:
+                # unify!
+                variable_families.union(*repvars)
+                progress = True
+        opportunities = pending_opportunities
     return variable_families
 
 def SSI_to_SSA(graph):

Modified: pypy/dist/pypy/translator/backendopt/test/test_ssa.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_ssa.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_ssa.py	Sat Sep 24 13:36:27 2005
@@ -1,2 +1,52 @@
+from pypy.translator.backendopt.ssa import *
+from pypy.translator.translator import Translator
+from pypy.objspace.flow.model import flatten, Block
 
-# XXX write a test!
+
+def test_data_flow_families():
+    def snippet_fn(xx, yy):
+        while yy > 0:
+            if 0 < xx:
+                yy = yy - xx
+            else:
+                yy = yy + xx
+        return yy
+    t = Translator(snippet_fn)
+    graph = t.getflowgraph()
+    operations = []
+    for block in flatten(graph):
+        if isinstance(block, Block):
+            operations += block.operations
+
+    variable_families = data_flow_families(graph)
+
+    # we expect to find xx only once:
+    v_xx = variable_families.find_rep(graph.getargs()[0])
+    found = 0
+    for op in operations:
+        if op.opname in ('add', 'sub', 'lt'):
+            assert variable_families.find_rep(op.args[1]) == v_xx
+            found += 1
+    assert found == 3
+
+
+def test_SSI_to_SSA():
+    def snippet_fn(v1, v2, v3):
+        if v1:                             # v4 = is_true(v1)
+            while v3:                      # v5 = is_true(v3)
+                pass
+            passed_over = 0
+        else:
+            v6 = snippet_fn(v3, v2, v1)    # v6 = simple_call(v3, v2, v1)
+            passed_over = v6
+        v7 = passed_over                   # v7 = inputarg
+        return v7+v1                       # v8 = add(v7, v1)
+
+    t = Translator(snippet_fn)
+    SSI_to_SSA(t.getflowgraph())
+    allvars = []
+    for block in flatten(t.getflowgraph()):
+        if isinstance(block, Block):
+            allvars += [v.name for v in block.getvariables()]
+    # see comments above for where the 8 remaining variables are expected to be
+    assert len(dict.fromkeys(allvars)) == 8



More information about the Pypy-commit mailing list