[pypy-svn] r17530 - pypy/dist/pypy/translator/backendopt

arigo at codespeak.net arigo at codespeak.net
Tue Sep 13 17:16:35 CEST 2005


Author: arigo
Date: Tue Sep 13 17:16:34 2005
New Revision: 17530

Modified:
   pypy/dist/pypy/translator/backendopt/malloc.py
Log:
Fixed the broken algo in _try_inline_malloc().


Modified: pypy/dist/pypy/translator/backendopt/malloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/malloc.py	(original)
+++ pypy/dist/pypy/translator/backendopt/malloc.py	Tue Sep 13 17:16:34 2005
@@ -3,9 +3,6 @@
 from pypy.tool.unionfind import UnionFind
 from pypy.rpython import lltype
 
-class Blocked(Exception):
-    pass
-
 class LifeTime:
 
     def __init__(self, (block, var)):
@@ -121,81 +118,86 @@
             flatconstants[S, name] = constant
     flatten(STRUCT, example)
 
-    pending = info.variables.keys()
-    for block, var in pending:
-        newvarsmap = {}
-
-        def var_comes_from_outside():
-            for key in flatnames:
-                newvar = Variable()
-                newvar.concretetype = flatconstants[key].concretetype
-                newvarsmap[key] = newvar
-
-        def var_is_created_here():
-            newvarsmap.update(flatconstants)
-
-        def make_newvars():
-            return [newvarsmap[key] for key in flatnames]
-
-        if var in block.inputargs:
-            var_comes_from_outside()
-            i = block.inputargs.index(var)
-            block.inputargs = (block.inputargs[:i] + make_newvars() +
-                               block.inputargs[i+1:])
-
-        assert block.operations != ()
-        newops = []
-        try:
+    variables_by_block = {}
+    for block, var in info.variables:
+        vars = variables_by_block.setdefault(block, {})
+        vars[var] = True
+
+    for block, vars in variables_by_block.items():
+
+        def flowin(var, newvarsmap):
+            # in this 'block', follow where the 'var' goes to and replace
+            # it by a flattened-out family of variables.  This family is given
+            # by newvarsmap, whose keys are the 'flatnames'.
+            vars = {var: True}
+
+            def list_newvars():
+                return [newvarsmap[key] for key in flatnames]
+
+            assert block.operations != ()
+            newops = []
             for op in block.operations:
-                assert var not in op.args[1:]   # should be the first arg only
-                if op.args and var == op.args[0]:
+                for arg in op.args[1:]:   # should be the first arg only
+                    assert arg not in vars
+                if op.args and op.args[0] in vars:
                     if op.opname == "getfield":
-                        S = var.concretetype.TO
+                        S = op.args[0].concretetype.TO
                         fldname = op.args[1].value
                         newop = SpaceOperation("same_as",
                                                [newvarsmap[S, fldname]],
                                                op.result)
                         newops.append(newop)
                     elif op.opname == "setfield":
-                        S = var.concretetype.TO
+                        S = op.args[0].concretetype.TO
                         fldname = op.args[1].value
                         assert (S, fldname) in newvarsmap
                         newvarsmap[S, fldname] = op.args[2]
                     elif op.opname in ("same_as", "cast_pointer"):
-                        # temporary pseudo-operation, should be removed below
-                        newop = SpaceOperation("_tmp_same_as",
-                                               make_newvars(),
-                                               op.result)
-                        newops.append(newop)
-                    else:
-                        raise AssertionError, op.opname
-                elif var == op.result:
-                    assert not newvarsmap
-                    if op.opname == "malloc":
-                        var_is_created_here()
-                    elif op.opname in ("same_as", "cast_pointer"):
-                        # in a 'v2=same_as(v1)', we must analyse v1 before
-                        # we can analyse v2.  If we get them in the wrong
-                        # order we cancel and reschedule v2.
-                        raise Blocked
-                    elif op.opname == "_tmp_same_as":
-                        # pseudo-operation just introduced by the code
-                        # some lines above.
-                        for key, v in zip(flatnames, op.args):
-                            newvarsmap[key] = v
+                        assert op.result not in vars
+                        vars[op.result] = True
+                        # Consider the two pointers (input and result) as
+                        # equivalent.  We can, and indeed must, use the same
+                        # flattened list of variables for both, as a "setfield"
+                        # via one pointer must be reflected in the other.
                     else:
                         raise AssertionError, op.opname
+                elif op.result in vars:
+                    assert op.opname == "malloc"
+                    assert vars == {var: True}
+                    # drop the "malloc" operation
                 else:
                     newops.append(op)
-        except Blocked:
-            pending.append((block, var))
-            continue
-        block.operations[:] = newops
-
-        for link in block.exits:
-            while var in link.args:
-                i = link.args.index(var)
-                link.args = link.args[:i] + make_newvars() + link.args[i+1:]
+            block.operations[:] = newops
+
+            for link in block.exits:
+                newargs = []
+                for arg in link.args:
+                    if arg in vars:
+                        newargs += list_newvars()
+                    else:
+                        newargs.append(arg)
+                link.args[:] = newargs
+
+        # look for variables arriving from outside the block
+        for var in vars:
+            if var in block.inputargs:
+                i = block.inputargs.index(var)
+                newinputargs = block.inputargs[:i]
+                newvarsmap = {}
+                for key in flatnames:
+                    newvar = Variable()
+                    newvar.concretetype = flatconstants[key].concretetype
+                    newvarsmap[key] = newvar
+                    newinputargs.append(newvar)
+                newinputargs += block.inputargs[i+1:]
+                block.inputargs[:] = newinputargs
+                flowin(var, newvarsmap)
+
+        # look for variables created inside the block by a malloc
+        for op in block.operations:
+            if op.opname == "malloc" and op.result in vars:
+                newvarsmap = flatconstants.copy()   # dummy initial values
+                flowin(op.result, newvarsmap)
 
     return True
 



More information about the Pypy-commit mailing list