[pypy-svn] r21802 - pypy/dist/pypy/translator/backendopt
cfbolz at codespeak.net
cfbolz at codespeak.net
Sat Jan 7 22:50:18 CET 2006
Author: cfbolz
Date: Sat Jan 7 22:50:17 2006
New Revision: 21802
Modified:
pypy/dist/pypy/translator/backendopt/inline.py
Log:
Intermediate step in my feeble attempt to refactor The Inlining Blob (tm). I
don't dare to shuffle around more without checking in because afterwards it
might not work at all anymore.
Modified: pypy/dist/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/inline.py (original)
+++ pypy/dist/pypy/translator/backendopt/inline.py Sat Jan 7 22:50:17 2006
@@ -82,62 +82,60 @@
return None
return ops[-4].args[2].value
-def _inline_function(translator, graph, block, index_operation):
- op = block.operations[index_operation]
- graph_to_inline = op.args[0].value._obj.graph
- exception_guarded = False
- if (block.exitswitch == c_last_exception and
- index_operation == len(block.operations) - 1):
- exception_guarded = True
- if len(collect_called_graphs(graph_to_inline, translator)) != 0:
- raise CannotInline("can't handle exceptions yet")
- entrymap = mkentrymap(graph_to_inline)
- beforeblock = block
- afterblock = split_block(translator, graph, block, index_operation)
- assert afterblock.operations[0] is op
- #vars that need to be passed through the blocks of the inlined function
- passon_vars = {beforeblock: [arg for arg in beforeblock.exits[0].args
- if isinstance(arg, Variable)]}
- copied_blocks = {}
- varmap = {}
- def get_new_name(var):
+
+
+class Inliner(object):
+ def __init__(self, translator, graph, block, index_operation):
+ self.translator = translator
+ self.graph = graph
+ self.varmap = {}
+ self.beforeblock = block
+ self.copied_blocks = {}
+ self.do_inline(block, index_operation)
+
+ def get_new_name(self, var):
if var is None:
return None
if isinstance(var, Constant):
return var
- if var not in varmap:
- varmap[var] = copyvar(translator, var)
- return varmap[var]
- def get_new_passon_var_names(block):
- result = [copyvar(translator, var) for var in passon_vars[beforeblock]]
- passon_vars[block] = result
+ if var not in self.varmap:
+ self.varmap[var] = copyvar(self.translator, var)
+ return self.varmap[var]
+
+ def get_new_passon_var_names(self, block):
+ result = [copyvar(self.translator, var) for var in self.passon_vars[self.beforeblock]]
+ self.passon_vars[block] = result
return result
- def copy_operation(op):
- args = [get_new_name(arg) for arg in op.args]
- return SpaceOperation(op.opname, args, get_new_name(op.result))
- def copy_block(block):
- if block in copied_blocks:
+
+ def copy_operation(self, op):
+ args = [self.get_new_name(arg) for arg in op.args]
+ return SpaceOperation(op.opname, args, self.get_new_name(op.result))
+
+ def copy_block(self, block):
+ if block in self.copied_blocks:
"already there"
- return copied_blocks[block]
- args = ([get_new_name(var) for var in block.inputargs] +
- get_new_passon_var_names(block))
+ return self.copied_blocks[block]
+ args = ([self.get_new_name(var) for var in block.inputargs] +
+ self.get_new_passon_var_names(block))
newblock = Block(args)
- copied_blocks[block] = newblock
- newblock.operations = [copy_operation(op) for op in block.operations]
- newblock.exits = [copy_link(link, block) for link in block.exits]
- newblock.exitswitch = get_new_name(block.exitswitch)
+ self.copied_blocks[block] = newblock
+ newblock.operations = [self.copy_operation(op) for op in block.operations]
+ newblock.exits = [self.copy_link(link, block) for link in block.exits]
+ newblock.exitswitch = self.get_new_name(block.exitswitch)
newblock.exc_handler = block.exc_handler
return newblock
- def copy_link(link, prevblock):
- newargs = [get_new_name(a) for a in link.args] + passon_vars[prevblock]
- newlink = Link(newargs, copy_block(link.target), link.exitcase)
- newlink.prevblock = copy_block(link.prevblock)
- newlink.last_exception = get_new_name(link.last_exception)
- newlink.last_exc_value = get_new_name(link.last_exc_value)
+
+ def copy_link(self, link, prevblock):
+ newargs = [self.get_new_name(a) for a in link.args] + self.passon_vars[prevblock]
+ newlink = Link(newargs, self.copy_block(link.target), link.exitcase)
+ newlink.prevblock = self.copy_block(link.prevblock)
+ newlink.last_exception = self.get_new_name(link.last_exception)
+ newlink.last_exc_value = self.get_new_name(link.last_exc_value)
if hasattr(link, 'llexitcase'):
newlink.llexitcase = link.llexitcase
return newlink
- def generate_keepalive(vars):
+
+ def generate_keepalive(self, vars):
keepalive_ops = []
for v in vars:
if isinstance(v, Constant):
@@ -149,133 +147,155 @@
keepalive_ops.append(SpaceOperation('keepalive', [v], v_keepalive))
return keepalive_ops
- linktoinlined = beforeblock.exits[0]
- assert linktoinlined.target is afterblock
- copiedstartblock = copy_block(graph_to_inline.startblock)
- copiedstartblock.isstartblock = False
- #find args passed to startblock of inlined function
- passon_args = []
- for arg in op.args[1:]:
- if isinstance(arg, Constant):
- passon_args.append(arg)
- else:
- index = afterblock.inputargs.index(arg)
- passon_args.append(linktoinlined.args[index])
- passon_args += passon_vars[beforeblock]
- #rewire blocks
- linktoinlined.target = copiedstartblock
- linktoinlined.args = passon_args
- afterblock.inputargs = [op.result] + afterblock.inputargs
- afterblock.operations = generate_keepalive(afterblock.inputargs) + afterblock.operations[1:]
- if graph_to_inline.returnblock in entrymap:
- copiedreturnblock = copied_blocks[graph_to_inline.returnblock]
- linkfrominlined = Link([copiedreturnblock.inputargs[0]] + passon_vars[graph_to_inline.returnblock], afterblock)
- linkfrominlined.prevblock = copiedreturnblock
- copiedreturnblock.exitswitch = None
- copiedreturnblock.exits = [linkfrominlined]
- assert copiedreturnblock.exits[0].target == afterblock
- if graph_to_inline.exceptblock in entrymap:
- #let links to exceptblock of the graph to inline go to graphs exceptblock
- copiedexceptblock = copied_blocks[graph_to_inline.exceptblock]
- if not exception_guarded:
- # find all copied links that go to copiedexceptblock
- for link in entrymap[graph_to_inline.exceptblock]:
- copiedblock = copied_blocks[link.prevblock]
- for copiedlink in copiedblock.exits:
- if copiedlink.target is copiedexceptblock:
- copiedlink.args = copiedlink.args[:2]
- copiedlink.target = graph.exceptblock
- for a1, a2 in zip(copiedlink.args,
- graph.exceptblock.inputargs):
- if hasattr(a2, 'concretetype'):
- assert a1.concretetype == a2.concretetype
- else:
- # if graph.exceptblock was never used before
- a2.concretetype = a1.concretetype
- else:
- def find_args_in_exceptional_case(link, block, etype, evalue):
- linkargs = []
- for arg in link.args:
- if arg == link.last_exception:
- linkargs.append(etype)
- elif arg == link.last_exc_value:
- linkargs.append(evalue)
- elif isinstance(arg, Constant):
- linkargs.append(arg)
- else:
- index = afterblock.inputargs.index(arg)
- linkargs.append(passon_vars[block][index - 1])
- return linkargs
- exc_match = Constant(
- translator.rtyper.getexceptiondata().fn_exception_match)
- exc_match.concretetype = typeOf(exc_match.value)
- #try to match the exceptions for simple cases
- for link in entrymap[graph_to_inline.exceptblock]:
- copiedblock = copied_blocks[link.prevblock]
- copiedlink = copiedblock.exits[0]
- eclass = _find_exception_type(copiedblock)
- #print copiedblock.operations
- if eclass is None:
- continue
- etype = copiedlink.args[0]
- evalue = copiedlink.args[1]
- for exceptionlink in afterblock.exits[1:]:
- if exc_match.value(eclass, exceptionlink.llexitcase):
- copiedblock.operations += generate_keepalive(
- passon_vars[link.prevblock])
- copiedlink.target = exceptionlink.target
- linkargs = find_args_in_exceptional_case(exceptionlink,
- link.prevblock,
- etype, evalue)
- copiedlink.args = linkargs
- break
- #XXXXX don't look: insert blocks that do exception matching
- #for the cases where direct matching did not work
- blocks = []
- for i, link in enumerate(afterblock.exits[1:]):
- etype = copyvar(translator, copiedexceptblock.inputargs[0])
- evalue = copyvar(translator, copiedexceptblock.inputargs[1])
- block = Block([etype, evalue] + get_new_passon_var_names(link.target))
- res = Variable()
- res.concretetype = Bool
- translator.annotator.bindings[res] = annmodel.SomeBool()
- cexitcase = Constant(link.llexitcase)
- cexitcase.concretetype = typeOf(cexitcase.value)
- args = [exc_match, etype, cexitcase]
- block.operations.append(SpaceOperation("direct_call", args, res))
- block.exitswitch = res
- linkargs = find_args_in_exceptional_case(link, link.target,
- etype, evalue)
- l = Link(linkargs, link.target)
- l.prevblock = block
- l.exitcase = True
- l.llexitcase = True
- block.exits.append(l)
- if i > 0:
- l = Link(blocks[-1].inputargs, block)
- l.prevblock = blocks[-1]
- l.exitcase = False
- l.llexitcase = False
- blocks[-1].exits.insert(0, l)
- blocks.append(block)
- blocks[-1].exits = blocks[-1].exits[:1]
- blocks[-1].operations = []
- blocks[-1].exitswitch = None
- blocks[-1].exits[0].exitcase = None
- del blocks[-1].exits[0].llexitcase
- linkargs = copiedexceptblock.inputargs
- copiedexceptblock.closeblock(Link(linkargs, blocks[0]))
- copiedexceptblock.operations += generate_keepalive(linkargs)
- if exception_guarded:
- assert afterblock.exits[0].exitcase is None
- afterblock.exits = [afterblock.exits[0]]
- afterblock.exitswitch = None
- #cleaning up -- makes sense to be here, because I insert quite
- #some empty blocks and blocks that can be joined
- checkgraph(graph)
- eliminate_empty_blocks(graph)
- join_blocks(graph)
- remove_identical_vars(graph)
+ def find_args_in_exceptional_case(self, link, block, etype, evalue, afterblock):
+ linkargs = []
+ for arg in link.args:
+ if arg == link.last_exception:
+ linkargs.append(etype)
+ elif arg == link.last_exc_value:
+ linkargs.append(evalue)
+ elif isinstance(arg, Constant):
+ linkargs.append(arg)
+ else:
+ index = afterblock.inputargs.index(arg)
+ linkargs.append(self.passon_vars[block][index - 1])
+ return linkargs
+
+ def do_inline(self, block, index_operation):
+ # original
+ op = block.operations[index_operation]
+ graph_to_inline = op.args[0].value._obj.graph
+ exception_guarded = False
+ if (block.exitswitch == c_last_exception and
+ index_operation == len(block.operations) - 1):
+ exception_guarded = True
+ if len(collect_called_graphs(graph_to_inline, self.translator)) != 0:
+ raise CannotInline("can't handle exceptions yet")
+ entrymap = mkentrymap(graph_to_inline)
+ afterblock = split_block(self.translator, self.graph, block, index_operation)
+ assert afterblock.operations[0] is op
+ #vars that need to be passed through the blocks of the inlined function
+ self.passon_vars = {
+ self.beforeblock: [arg for arg in self.beforeblock.exits[0].args
+ if isinstance(arg, Variable)]}
+
+ linktoinlined = self.beforeblock.exits[0]
+ assert linktoinlined.target is afterblock
+ copiedstartblock = self.copy_block(graph_to_inline.startblock)
+ copiedstartblock.isstartblock = False
+ #find args passed to startblock of inlined function
+ passon_args = []
+ for arg in op.args[1:]:
+ if isinstance(arg, Constant):
+ passon_args.append(arg)
+ else:
+ index = afterblock.inputargs.index(arg)
+ passon_args.append(linktoinlined.args[index])
+ passon_args += self.passon_vars[self.beforeblock]
+ #rewire blocks
+ linktoinlined.target = copiedstartblock
+ linktoinlined.args = passon_args
+ afterblock.inputargs = [op.result] + afterblock.inputargs
+ afterblock.operations = self.generate_keepalive(afterblock.inputargs) + afterblock.operations[1:]
+ if graph_to_inline.returnblock in entrymap:
+ copiedreturnblock = self.copied_blocks[graph_to_inline.returnblock] # XXX
+ linkfrominlined = Link([copiedreturnblock.inputargs[0]] + self.passon_vars[graph_to_inline.returnblock], afterblock)
+ linkfrominlined.prevblock = copiedreturnblock
+ copiedreturnblock.exitswitch = None
+ copiedreturnblock.exits = [linkfrominlined]
+ assert copiedreturnblock.exits[0].target == afterblock
+ if graph_to_inline.exceptblock in entrymap:
+ #let links to exceptblock of the graph to inline go to graphs exceptblock
+ copiedexceptblock = self.copied_blocks[graph_to_inline.exceptblock] #XXX
+ if not exception_guarded:
+ # find all copied links that go to copiedexceptblock
+ for link in entrymap[graph_to_inline.exceptblock]:
+ copiedblock = self.copied_blocks[link.prevblock]
+ for copiedlink in copiedblock.exits:
+ if copiedlink.target is copiedexceptblock:
+ copiedlink.args = copiedlink.args[:2]
+ copiedlink.target = self.graph.exceptblock
+ for a1, a2 in zip(copiedlink.args,
+ self.graph.exceptblock.inputargs):
+ if hasattr(a2, 'concretetype'):
+ assert a1.concretetype == a2.concretetype
+ else:
+ # if self.graph.exceptblock was never used before
+ a2.concretetype = a1.concretetype
+ else:
+ exc_match = Constant(
+ self.translator.rtyper.getexceptiondata().fn_exception_match)
+ exc_match.concretetype = typeOf(exc_match.value)
+ #try to match the exceptions for simple cases
+ for link in entrymap[graph_to_inline.exceptblock]:
+ copiedblock = self.copied_blocks[link.prevblock]
+ copiedlink = copiedblock.exits[0]
+ eclass = _find_exception_type(copiedblock)
+ #print copiedblock.operations
+ if eclass is None:
+ continue
+ etype = copiedlink.args[0]
+ evalue = copiedlink.args[1]
+ for exceptionlink in afterblock.exits[1:]:
+ if exc_match.value(eclass, exceptionlink.llexitcase):
+ copiedblock.operations += self.generate_keepalive(
+ self.passon_vars[link.prevblock])
+ copiedlink.target = exceptionlink.target
+ linkargs = self.find_args_in_exceptional_case(exceptionlink,
+ link.prevblock,
+ etype, evalue, afterblock)
+ copiedlink.args = linkargs
+ break
+ #XXXXX don't look: insert blocks that do exception matching
+ #for the cases where direct matching did not work
+ blocks = []
+ for i, link in enumerate(afterblock.exits[1:]):
+ etype = copyvar(self.translator, copiedexceptblock.inputargs[0])
+ evalue = copyvar(self.translator, copiedexceptblock.inputargs[1])
+ block = Block([etype, evalue] + self.get_new_passon_var_names(link.target))
+ res = Variable()
+ res.concretetype = Bool
+ self.translator.annotator.bindings[res] = annmodel.SomeBool()
+ cexitcase = Constant(link.llexitcase)
+ cexitcase.concretetype = typeOf(cexitcase.value)
+ args = [exc_match, etype, cexitcase]
+ block.operations.append(SpaceOperation("direct_call", args, res))
+ block.exitswitch = res
+ linkargs = self.find_args_in_exceptional_case(link, link.target,
+ etype, evalue, afterblock)
+ l = Link(linkargs, link.target)
+ l.prevblock = block
+ l.exitcase = True
+ l.llexitcase = True
+ block.exits.append(l)
+ if i > 0:
+ l = Link(blocks[-1].inputargs, block)
+ l.prevblock = blocks[-1]
+ l.exitcase = False
+ l.llexitcase = False
+ blocks[-1].exits.insert(0, l)
+ blocks.append(block)
+ blocks[-1].exits = blocks[-1].exits[:1]
+ blocks[-1].operations = []
+ blocks[-1].exitswitch = None
+ blocks[-1].exits[0].exitcase = None
+ del blocks[-1].exits[0].llexitcase
+ linkargs = copiedexceptblock.inputargs
+ copiedexceptblock.closeblock(Link(linkargs, blocks[0]))
+ copiedexceptblock.operations += self.generate_keepalive(linkargs)
+ if exception_guarded:
+ assert afterblock.exits[0].exitcase is None
+ afterblock.exits = [afterblock.exits[0]]
+ afterblock.exitswitch = None
+ #cleaning up -- makes sense to be here, because I insert quite
+ #some empty blocks and blocks that can be joined
+ checkgraph(self.graph)
+ eliminate_empty_blocks(self.graph)
+ join_blocks(self.graph)
+ remove_identical_vars(self.graph)
+
+
+_inline_function = Inliner
# ____________________________________________________________
#
More information about the Pypy-commit
mailing list