[pypy-svn] r31509 - in pypy/dist/pypy/translator/c: . test

arigo at codespeak.net arigo at codespeak.net
Tue Aug 22 21:19:45 CEST 2006


Author: arigo
Date: Tue Aug 22 21:19:42 2006
New Revision: 31509

Modified:
   pypy/dist/pypy/translator/c/support.py
   pypy/dist/pypy/translator/c/test/test_support.py
Log:
(pedronis, arigo)

gen_assignments() was completely broken, but you need completely obscure
graphs to see the difference anyway.  Fixed.



Modified: pypy/dist/pypy/translator/c/support.py
==============================================================================
--- pypy/dist/pypy/translator/c/support.py	(original)
+++ pypy/dist/pypy/translator/c/support.py	Tue Aug 22 21:19:42 2006
@@ -111,44 +111,79 @@
             return '{%s}' % ', '.join(lines)
 
 
+##def gen_assignments(assignments):
+##    # Generate a sequence of assignments that is possibly reordered
+##    # to avoid clashes -- i.e. do the equivalent of a tuple assignment,
+##    # reading all sources first, writing all targets next, but optimized
+
+##    allsources = []
+##    src2dest = {}
+##    types = {}
+##    for typename, dest, src in assignments:
+##        if src != dest:   # ignore 'v=v;'
+##            allsources.append(src)
+##            src2dest.setdefault(src, []).append(dest)
+##            types[dest] = typename
+
+##    for starting in allsources:
+##        # starting from some starting variable, follow a chain of assignments
+##        #     'vn=vn-1; ...; v3=v2; v2=v1; v1=starting;'
+##        v = starting
+##        srcchain = []
+##        while src2dest.get(v):
+##            srcchain.append(v)
+##            v = src2dest[v].pop(0)
+##            if v == starting:
+##                break    # loop
+##        if not srcchain:
+##            continue   # already done in a previous chain
+##        srcchain.reverse()   # ['vn-1', ..., 'v2', 'v1', 'starting']
+##        code = []
+##        for pair in zip([v] + srcchain[:-1], srcchain):
+##            code.append('%s = %s;' % pair)
+##        if v == starting:
+##            # assignment loop 'starting=vn-1; ...; v2=v1; v1=starting;'
+##            typename = types[starting]
+##            tmpdecl = cdecl(typename, 'tmp')
+##            code.insert(0, '{ %s = %s;' % (tmpdecl, starting))
+##            code[-1] = '%s = tmp; }' % (srcchain[-2],)
+##        yield ' '.join(code)
+
 def gen_assignments(assignments):
     # Generate a sequence of assignments that is possibly reordered
     # to avoid clashes -- i.e. do the equivalent of a tuple assignment,
     # reading all sources first, writing all targets next, but optimized
 
-    allsources = []
-    src2dest = {}
-    types = {}
-    assignments = list(assignments)
+    srccount = {}
+    dest2src = {}
     for typename, dest, src in assignments:
         if src != dest:   # ignore 'v=v;'
-            allsources.append(src)
-            src2dest.setdefault(src, []).append(dest)
-            types[dest] = typename
-
-    for starting in allsources:
-        # starting from some starting variable, follow a chain of assignments
-        #     'vn=vn-1; ...; v3=v2; v2=v1; v1=starting;'
-        v = starting
-        srcchain = []
-        while src2dest.get(v):
-            srcchain.append(v)
-            v = src2dest[v].pop(0)
-            if v == starting:
-                break    # loop
-        if not srcchain:
-            continue   # already done in a previous chain
-        srcchain.reverse()   # ['vn-1', ..., 'v2', 'v1', 'starting']
-        code = []
-        for pair in zip([v] + srcchain[:-1], srcchain):
-            code.append('%s = %s;' % pair)
-        if v == starting:
-            # assignment loop 'starting=vn-1; ...; v2=v1; v1=starting;'
-            typename = types[starting]
-            tmpdecl = cdecl(typename, 'tmp')
-            code.insert(0, '{ %s = %s;' % (tmpdecl, starting))
-            code[-1] = '%s = tmp; }' % (srcchain[-2],)
-        yield ' '.join(code)
+            srccount[src] = srccount.get(src, 0) + 1
+            dest2src[dest] = src, typename
+
+    while dest2src:
+        progress = False
+        for dst in dest2src.keys():
+            if dst not in srccount:
+                src, typename = dest2src.pop(dst)
+                yield '%s = %s;' % (dst, src)
+                srccount[src] -= 1
+                if not srccount[src]:
+                    del srccount[src]
+                progress = True
+        if not progress:
+            # we are left with only pure disjoint cycles; break them
+            while dest2src:
+                dst, (src, typename) = dest2src.popitem()
+                startingpoint = dst
+                tmpdecl = cdecl(typename, 'tmp')
+                code = ['{ %s = %s;' % (tmpdecl, dst)]
+                while src is not startingpoint:
+                    code.append('%s = %s;' % (dst, src))
+                    dst = src
+                    src, typename = dest2src.pop(dst)
+                code.append('%s = tmp; }' % (dst,))
+                yield ' '.join(code)
 
 # logging
 

Modified: pypy/dist/pypy/translator/c/test/test_support.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_support.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_support.py	Tue Aug 22 21:19:42 2006
@@ -1,20 +1,39 @@
+import random
 from pypy.translator.c.support import gen_assignments
 
 
-def gen_assign(input, expected):
-    assert ' '.join(gen_assignments(input)) == expected
+def test_gen_simple_assignments():
+    yield gen_check, [('int @', 'a', 'a')]
+    yield gen_check, [('int @', 'a', 'b')]
+    yield gen_check, [('int @', 'a', 'b'),
+                      ('int @', 'c', 'b')]
+    yield gen_check, [('int @', 'a', 'b'),
+                      ('int @', 'b', 'c')]
+    yield gen_check, [('int @', 'b', 'c'),
+                      ('int @', 'a', 'b')]
+    yield gen_check, [('int @', 'a', 'b'),
+                      ('int @', 'b', 'a')]
+    yield gen_check, [('int @', 'a', 'b'),
+                      ('int @', 'b', 'c'),
+                      ('int @', 'd', 'b')]
 
-def test_gen_assignments():
-    yield gen_assign, [('int @', 'a', 'a')], ''
-    yield gen_assign, [('int @', 'a', 'b')], 'a = b;'
-    yield gen_assign, [('int @', 'a', 'b'),
-                       ('int @', 'c', 'b')], 'a = b; c = b;'
-    yield gen_assign, [('int @', 'a', 'b'),
-                       ('int @', 'b', 'c')], 'a = b; b = c;'
-    yield gen_assign, [('int @', 'b', 'c'),
-                       ('int @', 'a', 'b')], 'a = b; b = c;'
-    yield gen_assign, [('int @', 'a', 'b'),
-                       ('int @', 'b', 'a')], '{ int tmp = b; b = a; a = tmp; }'
-    yield gen_assign, [('int @', 'a', 'b'),
-                       ('int @', 'b', 'c'),
-                       ('int @', 'd', 'b')], 'a = b; d = b; b = c;'
+def gen_check(input):
+    for _, dst, src in input:
+        print 'input:', dst, src
+    result = ' '.join(gen_assignments(input))
+    print result
+    result = result.replace('{ int', '').replace('}', '').strip()
+    d = {}
+    for _, dst, src in input:
+        d[src] = '<value of %s>' % (src,)
+    exec result in d
+    for _, dst, src in input:
+        assert d[dst] == '<value of %s>' % (src,)
+
+def test_gen_check():
+    varlist = list('abcdefg')
+    for i in range(100):
+        random.shuffle(varlist)
+        input = [('int @', varlist[n], random.choice(varlist))
+                 for n in range(random.randrange(1, 7))]
+        yield gen_check, input



More information about the Pypy-commit mailing list