[pypy-svn] r4681 - in pypy/trunk/src/pypy: objspace/flow translator

arigo at codespeak.net arigo at codespeak.net
Thu May 27 14:57:18 CEST 2004


Author: arigo
Date: Thu May 27 14:57:17 2004
New Revision: 4681

Modified:
   pypy/trunk/src/pypy/objspace/flow/model.py
   pypy/trunk/src/pypy/translator/simplify.py
   pypy/trunk/src/pypy/translator/transform.py
Log:
Dead variable analysis, to reduce these really long lists of variables passed 
around on each link.


Modified: pypy/trunk/src/pypy/objspace/flow/model.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/flow/model.py	(original)
+++ pypy/trunk/src/pypy/objspace/flow/model.py	Thu May 27 14:57:17 2004
@@ -9,6 +9,7 @@
     def __init__(self, name, startblock, return_var=None):
         self.name        = name    # function name (possibly mangled already)
         self.startblock  = startblock
+        self.startblock.isstartblock = True
         # build default returnblock
         self.returnblock = Block([return_var or Variable()])
         self.returnblock.operations = ()
@@ -40,6 +41,8 @@
         self.prevblock = None      # the block this Link is an exit of
 
 class Block:
+    isstartblock = False
+    
     def __init__(self, inputargs):
         self.inputargs = inputargs    # mixed list of variable/const 
         self.operations = []          # list of SpaceOperation(s)

Modified: pypy/trunk/src/pypy/translator/simplify.py
==============================================================================
--- pypy/trunk/src/pypy/translator/simplify.py	(original)
+++ pypy/trunk/src/pypy/translator/simplify.py	Thu May 27 14:57:17 2004
@@ -62,6 +62,10 @@
     traverse(visit, graph)
 
 def remove_implicit_exceptions(graph):
+    """An exception that is marked implicit (see implicitexc) and not
+    caught in the block is entierely removed.  This gets rid for example
+    of possible ValueErrors upon tuple unpacking, assuming they cannot
+    happen unless there is an exception handler in the same function."""
     def visit(link):
         if isinstance(link, Link) and link in link.prevblock.exits:
             if (isinstance(link.exitcase, type(Exception)) and

Modified: pypy/trunk/src/pypy/translator/transform.py
==============================================================================
--- pypy/trunk/src/pypy/translator/transform.py	(original)
+++ pypy/trunk/src/pypy/translator/transform.py	Thu May 27 14:57:17 2004
@@ -96,26 +96,77 @@
 
         block.operations = operations
 
-def transform_dead_operations(self):
-    """Remove dead operations."""
+def transform_dead_op_vars(self):
+    """Remove dead operations and variables that are passed over a link
+    but not used in the target block."""
     # the set of operations that can safely be removed (no side effects)
     CanRemove = {'newtuple': True,
                  'newlist': True,
                  'newdict': True}
+    read_vars = {}  # set of variables really used
+    variable_flow = {}  # map {Var: list-of-Vars-it-depends-on}
+    
+    # compute variable_flow and an initial read_vars
     for block in self.annotated:
         # figure out which variables are ever read
-        read_vars = {}
         for op in block.operations:
-            for arg in op.args:
-                read_vars[arg] = True
-        for link in block.exits:
-            for arg in link.args:
+            if op.opname not in CanRemove:  # mark the inputs as really needed
+                for arg in op.args:
+                    read_vars[arg] = True
+            else:
+                # if CanRemove, only mark dependencies of the result
+                # on the input variables
+                deps = variable_flow.setdefault(op.result, [])
+                deps.extend(op.args)
+        
+        if block.exits:
+            for link in block.exits:
+                for arg, targetarg in zip(link.args, link.target.inputargs):
+                    deps = variable_flow.setdefault(targetarg, [])
+                    deps.append(arg)
+        else:
+            # return blocks implicitely use their single input variable
+            assert len(block.inputargs) == 1
+            read_vars[block.inputargs[0]] = True
+        # an input block's inputargs should not be modified, even if some
+        # of the function's input arguments are not actually used
+        if block.isstartblock:
+            for arg in block.inputargs:
                 read_vars[arg] = True
+
+    # flow read_vars backwards so that any variable on which a read_vars
+    # depends is also included in read_vars
+    pending = list(read_vars)
+    for var in pending:
+        for prevvar in variable_flow.get(var, []):
+            if prevvar not in read_vars:
+                read_vars[prevvar] = True
+                pending.append(prevvar)
+
+    for block in self.annotated:
+        
         # look for removable operations whose result is never used
         for i in range(len(block.operations)-1, -1, -1):
             op = block.operations[i]
             if op.opname in CanRemove and op.result not in read_vars:
                 del block.operations[i]
+                
+        # look for output variables never used
+        # warning: this must be completely done *before* we attempt to
+        # remove the corresponding variables from block.inputargs!
+        # Otherwise the link.args get out of sync with the
+        # link.target.inputargs.
+        for link in block.exits:
+            for i in range(len(link.args)-1, -1, -1):
+                if link.target.inputargs[i] not in read_vars:
+                    del link.args[i]
+
+    for block in self.annotated:
+        # look for input variables never used
+        # The corresponding link.args have already been all removed above
+        for i in range(len(block.inputargs)-1, -1, -1):
+            if block.inputargs[i] not in read_vars:
+                del block.inputargs[i]
 
 def transform_graph(ann):
     """Apply set of transformations available."""
@@ -124,4 +175,4 @@
     transform_simple_call(ann)
     # do this last, after the previous transformations had a
     # chance to remove dependency on certain variables
-    transform_dead_operations(ann)
+    transform_dead_op_vars(ann)



More information about the Pypy-commit mailing list