[pypy-svn] r32501 - in pypy/branch/timeshift-refactoring/pypy/translator/backendopt: . test
arigo at codespeak.net
arigo at codespeak.net
Tue Sep 19 16:57:43 CEST 2006
Author: arigo
Date: Tue Sep 19 16:57:37 2006
New Revision: 32501
Modified:
pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py
pypy/branch/timeshift-refactoring/pypy/translator/backendopt/test/test_ssa.py
Log:
(arre, arigo)
A possibly useful tool for graph construction and transformation.
It allows us to build a few blocks without worrying about passing
variables along links and renaming them *at all*, and then goes
along and fixes the blocks. More precisely, it's an SSA to SSI
transformation.
Modified: pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py
==============================================================================
--- pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py (original)
+++ pypy/branch/timeshift-refactoring/pypy/translator/backendopt/ssa.py Tue Sep 19 16:57:37 2006
@@ -16,9 +16,7 @@
# [Block, blockvar, linkvar, linkvar, linkvar...]
opportunities = []
opportunities_with_const = []
- for block, links in mkentrymap(graph).items():
- if block is graph.startblock:
- continue
+ for block, links in mkinsideentrymap(graph).items():
assert links
for n, inputvar in enumerate(block.inputargs):
vars = [block, inputvar]
@@ -124,3 +122,92 @@
vct = [getattr(v, 'concretetype', None) for v in vlist]
assert vct == vct[:1] * len(vct), (
"variables called %s have mixed concretetypes: %r" % (vname, vct))
+
+# ____________________________________________________________
+
+def mkinsideentrymap(graph_or_blocks):
+ # graph_or_blocks can be a full FunctionGraph, or a mapping
+ # {block: reachable-from-outside-flag}.
+ if isinstance(graph_or_blocks, dict):
+ blocks = graph_or_blocks
+ entrymap = {}
+ for block in blocks:
+ for link in block.exits:
+ if link.target in blocks and not blocks[link.target]:
+ entrymap.setdefault(link.target, []).append(link)
+ return entrymap
+ else:
+ graph = graph_or_blocks
+ entrymap = mkentrymap(graph)
+ del entrymap[graph.startblock]
+ return entrymap
+
+def variables_created_in(block):
+ result = {}
+ for v in block.inputargs:
+ result[v] = True
+ for op in block.operations:
+ result[op.result] = True
+ return result
+
+
+def SSA_to_SSI(blocks, annotator=None):
+ """Turn a number of blocks belonging to a flow graph into valid (i.e. SSI)
+ form, assuming that they are only in SSA form (i.e. they can use each
+ other's variables directly, without having to pass and rename them along
+ links).
+
+ 'blocks' is a mapping {block: reachable-from-outside-flag}.
+ """
+ from pypy.translator.unsimplify import copyvar
+
+ entrymap = mkinsideentrymap(blocks)
+ variable_families = DataFlowFamilyBuilder(blocks).get_variable_families()
+
+ pending = [] # list of (block, var-used-but-not-defined)
+
+ for block in blocks:
+ variables_created = variables_created_in(block)
+ variables_used = {}
+ for op in block.operations:
+ for v in op.args:
+ if isinstance(v, Variable):
+ variables_used[v] = True
+ if isinstance(block.exitswitch, Variable):
+ variables_used[v] = True
+ for link in block.exits:
+ for v in link.args:
+ if isinstance(v, Variable):
+ variables_used[v] = True
+
+ for v in variables_used:
+ if v not in variables_created:
+ pending.append((block, v))
+
+ while pending:
+ block, v = pending.pop()
+ v_rep = variable_families.find_rep(v)
+ variables_created = variables_created_in(block)
+ if v in variables_created:
+ continue # already ok
+ for w in variables_created:
+ w_rep = variable_families.find_rep(w)
+ if v_rep is w_rep:
+ # 'w' is in the same family as 'v', so we can simply
+ # reuse its value for 'v'
+ block.renamevariables({v: w})
+ break
+ else:
+ # didn't find it. Add it to all incoming links.
+ try:
+ links = entrymap[block]
+ except KeyError:
+ raise Exception("SSA_to_SSI failed: no way to give a value to"
+ " %r in %r" % (v, block))
+ w = copyvar(annotator, v)
+ variable_families.union(v, w)
+ block.renamevariables({v: w})
+ block.inputargs.append(w)
+ for link in links:
+ link.args.append(v)
+ pending.append((link.prevblock, v))
Modified: pypy/branch/timeshift-refactoring/pypy/translator/backendopt/test/test_ssa.py
==============================================================================
--- pypy/branch/timeshift-refactoring/pypy/translator/backendopt/test/test_ssa.py (original)
+++ pypy/branch/timeshift-refactoring/pypy/translator/backendopt/test/test_ssa.py Tue Sep 19 16:57:37 2006
@@ -1,6 +1,7 @@
from pypy.translator.backendopt.ssa import *
from pypy.translator.translator import TranslationContext
-from pypy.objspace.flow.model import flatten, Block
+from pypy.objspace.flow.model import flatten, Block, Link, Variable, Constant
+from pypy.objspace.flow.model import SpaceOperation
def test_data_flow_families():
@@ -49,3 +50,63 @@
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
+
+
+def test_SSA_to_SSI():
+ c = Variable('c')
+ x = Variable('x')
+ y = Variable('y')
+ b1 = Block([c])
+ b2 = Block([x])
+ b3 = Block([])
+
+ b2.operations.append(SpaceOperation('add', [x, c], y))
+ b2.exitswitch = y
+
+ b1.closeblock(Link([Constant(0)], b2))
+ b2.closeblock(Link([y], b2), Link([], b3))
+ b3.closeblock(Link([y, c], None))
+
+ SSA_to_SSI({b1: True, # reachable from outside
+ b2: False,
+ b3: False})
+
+ assert len(b1.inputargs) == 1
+ assert len(b2.inputargs) == 2
+ assert len(b3.inputargs) == 2
+
+ assert b2.inputargs == b2.operations[0].args
+ assert len(b1.exits[0].args) == 2
+ assert b1.exits[0].args[1] is c
+ assert len(b2.exits[0].args) == 2
+ assert b2.exits[0].args == [y, b2.inputargs[1]]
+ assert len(b2.exits[1].args) == 2
+ assert len(b3.exits[0].args) == 2
+
+ index = b3.inputargs.index(b3.exits[0].args[0])
+ assert b2.exits[1].args[index] is b2.operations[0].result
+
+ index = b3.inputargs.index(b3.exits[0].args[1])
+ assert b2.exits[1].args[index] is b2.inputargs[1]
+
+
+def test_SSA_to_SSI_2():
+ x = Variable('x')
+ y = Variable('y')
+ z = Variable('z')
+ b1 = Block([x])
+ b2 = Block([y])
+ b3 = Block([])
+
+ b3.operations.append(SpaceOperation('hello', [y], z))
+ b1.closeblock(Link([x], b2), Link([], b3))
+
+ SSA_to_SSI({b1: True, # reachable from outside
+ b2: False,
+ b3: False})
+
+ assert b1.inputargs == [x]
+ assert b2.inputargs == [y]
+ assert b3.inputargs == [b3.operations[0].args[0]]
+ assert b1.exits[0].args == [x]
+ assert b1.exits[1].args == [x]
More information about the Pypy-commit
mailing list