[pypy-svn] r26917 - pypy/dist/pypy/translator/backendopt
cfbolz at codespeak.net
cfbolz at codespeak.net
Sun May 7 09:20:48 CEST 2006
Author: cfbolz
Date: Sun May 7 09:20:46 2006
New Revision: 26917
Modified:
pypy/dist/pypy/translator/backendopt/propagate.py
pypy/dist/pypy/translator/backendopt/removenoops.py
Log:
make partial_folding more general (although a bit inefficient). This makes the
optimization a bit too good: it now unrolls loops with constants bounds. On the
other hand it nicely folds away isinstance calls on tagged ptrs to just a bit
comparison.
Modified: pypy/dist/pypy/translator/backendopt/propagate.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/propagate.py (original)
+++ pypy/dist/pypy/translator/backendopt/propagate.py Sun May 7 09:20:46 2006
@@ -1,10 +1,11 @@
from pypy.objspace.flow.model import Block, Variable, Constant, c_last_exception
from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph
-from pypy.objspace.flow.model import SpaceOperation
+from pypy.objspace.flow.model import SpaceOperation, Link
from pypy.rpython.lltypesystem import lltype, lloperation
from pypy.rpython.llinterp import LLInterpreter, LLFrame
from pypy.translator import simplify
from pypy.translator.simplify import get_graph
+from pypy.translator.unsimplify import copyvar
from pypy.translator.backendopt.removenoops import remove_same_as
from pypy.translator.backendopt.inline import OP_WEIGHTS
from pypy.translator.backendopt.ssa import DataFlowFamilyBuilder
@@ -197,72 +198,140 @@
return True
return False
+#def partial_folding_once(graph, translator, analyzer=None):
+# if analyzer is None:
+# analyzer = CanfoldAnalyzer(translator)
+# lli = LLInterpreter(translator.rtyper)
+# entrymap = mkentrymap(graph)
+# for block in graph.iterblocks():
+# if (block is graph.startblock or block is graph.returnblock or
+# block is graph.exceptblock):
+# continue
+# usedvars = {}
+# cannotfold = False
+# for op in block.operations:
+# if analyzer.analyze(op):
+# cannotfold = True
+# break
+# for arg in op.args:
+# if (isinstance(arg, Variable) and arg in block.inputargs):
+# usedvars[arg] = True
+# if cannotfold:
+# continue
+# if isinstance(block.exitswitch, Variable):
+# usedvars[block.exitswitch] = True
+# pattern = [arg in usedvars for arg in block.inputargs]
+# for link in entrymap[block]:
+# s = sum([isinstance(arg, Constant) or not p
+# for arg, p in zip(link.args, pattern)])
+# if s != len(link.args):
+# continue
+# args = []
+# for i, arg in enumerate(link.args):
+# if isinstance(arg, Constant):
+# args.append(arg.value)
+# else:
+# assert not pattern[i]
+# args.append(arg.concretetype._example())
+# llframe = LLFrame(graph, None, lli)
+# llframe.fillvars(block, args)
+# nextblock, forwardargs = llframe.eval_block(block)
+# if nextblock is not None:
+# newargs = []
+# for i, arg in enumerate(nextblock.inputargs):
+# try:
+# index = [l.target for l in block.exits].index(nextblock)
+# index = block.inputargs.index(block.exits[index].args[i])
+# except ValueError:
+# c = Constant(forwardargs[i])
+# c.concretetype = arg.concretetype
+# newargs.append(c)
+# else:
+# newargs.append(link.args[index])
+# else:
+# assert 0, "this should not occur"
+# unchanged = link.target == nextblock and link.args == newargs
+# link.target = nextblock
+# link.args = newargs
+# checkgraph(graph)
+# if not unchanged:
+# return True
+# return False
+
def partial_folding_once(graph, translator, analyzer=None):
+ # XXX this is quite a suboptimal way to do it, but was easy to program
if analyzer is None:
analyzer = CanfoldAnalyzer(translator)
lli = LLInterpreter(translator.rtyper)
entrymap = mkentrymap(graph)
- for block in graph.iterblocks():
- if (block is graph.startblock or block is graph.returnblock or
- block is graph.exceptblock):
- continue
- usedvars = {}
- cannotfold = False
- for op in block.operations:
- if analyzer.analyze(op):
- cannotfold = True
- break
- for arg in op.args:
- if (isinstance(arg, Variable) and arg in block.inputargs):
- usedvars[arg] = True
- if cannotfold:
- continue
- if isinstance(block.exitswitch, Variable):
- usedvars[block.exitswitch] = True
- pattern = [arg in usedvars for arg in block.inputargs]
- for link in entrymap[block]:
- s = sum([isinstance(arg, Constant) or not p
- for arg, p in zip(link.args, pattern)])
- if s != len(link.args):
- continue
- args = []
+ for block, links in entrymap.iteritems():
+ # identify candidates
+ for link in links:
+ available_vars = {}
+ foldable_ops = {}
for i, arg in enumerate(link.args):
if isinstance(arg, Constant):
- args.append(arg.value)
+ available_vars[block.inputargs[i]] = True
+ if not available_vars:
+ continue
+ for op in block.operations:
+ if analyzer.analyze(op):
+ continue
+ for arg in op.args:
+ if not (isinstance(arg, Constant) or arg in available_vars):
+ break
else:
- assert not pattern[i]
- args.append(arg.concretetype._example())
- llframe = LLFrame(graph, None, lli)
- llframe.fillvars(block, args)
- nextblock, forwardargs = llframe.eval_block(block)
- if nextblock is not None:
- newargs = []
- for i, arg in enumerate(nextblock.inputargs):
- try:
- index = [l.target for l in block.exits].index(nextblock)
- index = block.inputargs.index(block.exits[index].args[i])
- except ValueError:
- c = Constant(forwardargs[i])
- c.concretetype = arg.concretetype
- newargs.append(c)
- else:
- newargs.append(link.args[index])
- else:
- assert 0, "this should not occur"
- unchanged = link.target == nextblock and link.args == newargs
- link.target = nextblock
- link.args = newargs
- checkgraph(graph)
- if not unchanged:
- return True
- return False
+ foldable_ops[op] = True
+ available_vars[op.result] = True
+ if not foldable_ops:
+ continue
+ # the link is a candidate. copy the target block so that
+ # constant folding can do its work
+ # whew, copying is annoying :-(. XXX nicely factor this out
+ vars_to_newvars = {}
+ def getnewvar(var):
+ if var in vars_to_newvars:
+ return vars_to_newvars[var]
+ if var is None:
+ return None
+ if isinstance(var, Constant):
+ return var
+ result = copyvar(translator, var)
+ vars_to_newvars[var] = result
+ return result
+ newops = []
+ for op in block.operations:
+ newargs = [getnewvar(var) for var in op.args]
+ newresult = getnewvar(op.result)
+ newops.append(SpaceOperation(op.opname, newargs, newresult))
+ newargs = [getnewvar(var) for var in block.inputargs]
+ newblock = Block(newargs)
+ newblock.exitswitch = getnewvar(block.exitswitch)
+ newblock.operations = newops
+ newlinks = []
+ for copylink in block.exits:
+ newargs = [getnewvar(var) for var in copylink.args]
+ newlink = Link(newargs, copylink.target, copylink.exitcase)
+ newlink.prevblock = block
+ newlink.last_exception = getnewvar(link.last_exception)
+ newlink.last_exc_value = getnewvar(link.last_exc_value)
+ if hasattr(link, 'llexitcase'):
+ newlink.llexitcase = link.llexitcase
+ newlinks.append(newlink)
+ newblock.closeblock(*newlinks)
+ link.target = newblock
+ propagate_consts(graph)
+ result = constant_folding(graph, translator, analyzer)
+ if result:
+ simplify.join_blocks(graph)
+ return result
-def partial_folding(graph, translator):
+def partial_folding(graph, translator, analyzer=None):
"""this function does constant folding in the following situation:
a block has a link that leads to it that has only constant args. Then all
the operations of this block are evaluated and the link leading to the
block is adjusted according to the resulting value of the exitswitch"""
- if do_atmost(1000, partial_folding_once, graph, translator):
+ if do_atmost(1000, partial_folding_once, graph, translator, analyzer):
propagate_consts(graph)
simplify.join_blocks(graph)
return True
@@ -363,10 +432,10 @@
changed = False
changed = rewire_links(graph) or changed
changed = propagate_consts(graph) or changed
-# changed = coalesce_links(graph) or changed
-# changed = do_atmost(100, constant_folding, graph,
-# translator, analyzer) or changed
-# changed = partial_folding(graph, translator, analyzer) or changed
+ changed = coalesce_links(graph) or changed
+ changed = do_atmost(100, constant_folding, graph,
+ translator, analyzer) or changed
+ changed = partial_folding(graph, translator, analyzer) or changed
changed = remove_all_getfields(graph, translator) or changed
checkgraph(graph)
return changed
Modified: pypy/dist/pypy/translator/backendopt/removenoops.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/removenoops.py (original)
+++ pypy/dist/pypy/translator/backendopt/removenoops.py Sun May 7 09:20:46 2006
@@ -23,6 +23,9 @@
for i in range(len(op.args)):
if op.args[i] == op_result:
op.args[i] = op_arg
+ if op.opname == "indirect_call" and op.args[0] == op_arg:
+ op.opname = "direct_call"
+ op.args = op.args[:-1]
for link in block.exits:
for i in range(len(link.args)):
if link.args[i] == op_result:
More information about the Pypy-commit
mailing list