[pypy-svn] r25560 - pypy/branch/stacklesscfg/pypy/translator/backendopt
mwh at codespeak.net
mwh at codespeak.net
Sat Apr 8 17:49:54 CEST 2006
Author: mwh
Date: Sat Apr 8 17:49:52 2006
New Revision: 25560
Modified:
pypy/branch/stacklesscfg/pypy/translator/backendopt/inline.py
Log:
merging of http://codespeak.net/svn/pypy/dist/pypy/translator/backendopt/inline.py
revisions 25473 to 25557:
------------------------------------------------------------------------
r25555 | hpk | 2006-04-08 17:32:31 +0200 (Sat, 08 Apr 2006) | 2 lines
merge r25548 of stacklesscfg branch (split_block returns splitlink instead of afterblock)
------------------------------------------------------------------------
r25544 | cfbolz | 2006-04-08 14:25:51 +0200 (Sat, 08 Apr 2006) | 2 lines
remove another debug print :-(
------------------------------------------------------------------------
r25543 | cfbolz | 2006-04-08 14:25:27 +0200 (Sat, 08 Apr 2006) | 2 lines
remove debug print
------------------------------------------------------------------------
r25542 | cfbolz | 2006-04-08 14:22:51 +0200 (Sat, 08 Apr 2006) | 3 lines
(pedronis, cfbolz): trying to make the order of inlining even more
deterministic
------------------------------------------------------------------------
r25541 | cfbolz | 2006-04-08 14:17:15 +0200 (Sat, 08 Apr 2006) | 2 lines
improve the weights of some operations. for some definition of improve
------------------------------------------------------------------------
r25535 | cfbolz | 2006-04-08 10:33:27 +0200 (Sat, 08 Apr 2006) | 2 lines
wua! bad me
------------------------------------------------------------------------
r25532 | cfbolz | 2006-04-08 10:14:47 +0200 (Sat, 08 Apr 2006) | 5 lines
(pedronis, cfbolz):
increase the weight of edges that go back in a loop because they are much more
likely
------------------------------------------------------------------------
r25495 | cfbolz | 2006-04-07 15:18:05 +0200 (Fri, 07 Apr 2006) | 6 lines
(pedronis, cfbolz):
introduced an optimizations remove_duplicate_casts to reduce the size of the
live variable set. For this we needed to make the exception heuristic in
inlining cleverer.
------------------------------------------------------------------------
Modified: pypy/branch/stacklesscfg/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/branch/stacklesscfg/pypy/translator/backendopt/inline.py (original)
+++ pypy/branch/stacklesscfg/pypy/translator/backendopt/inline.py Sat Apr 8 17:49:52 2006
@@ -6,11 +6,11 @@
from pypy.objspace.flow.model import SpaceOperation, c_last_exception
from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph
from pypy.annotation import model as annmodel
-from pypy.rpython.lltypesystem.lltype import Bool, typeOf, Void
+from pypy.rpython.lltypesystem.lltype import Bool, typeOf, Void, Ptr
from pypy.rpython import rmodel
from pypy.tool.algo import sparsemat
from pypy.translator.backendopt.support import log, split_block_with_keepalive
-from pypy.translator.backendopt.support import generate_keepalive
+from pypy.translator.backendopt.support import generate_keepalive, find_backedges, find_loop_blocks
BASE_INLINE_THRESHOLD = 32.4 # just enough to inline add__Int_Int()
# and just small enough to prevend inlining of some rlist functions.
@@ -68,25 +68,28 @@
except StopIteration:
return False
-def inline_function(translator, inline_func, graph):
- inliner = Inliner(translator, graph, inline_func)
+def inline_function(translator, inline_func, graph, lltype_to_classdef):
+ inliner = Inliner(translator, graph, inline_func, lltype_to_classdef)
return inliner.inline_all()
+def simple_inline_function(translator, inline_func, graph):
+ inliner = Inliner(translator, graph, inline_func,
+ translator.rtyper.lltype_to_classdef_mapping())
+ return inliner.inline_all()
+
+
def _find_exception_type(block):
#XXX slightly brittle: find the exception type for simple cases
#(e.g. if you do only raise XXXError) by doing pattern matching
- ops = [op for op in block.operations if op.opname != 'keepalive']
- if (len(ops) < 6 or
- ops[-6].opname != "malloc" or ops[-5].opname != "cast_pointer" or
- ops[-4].opname != "setfield" or ops[-3].opname != "cast_pointer" or
- ops[-2].opname != "getfield" or ops[-1].opname != "cast_pointer" or
- len(block.exits) != 1 or block.exits[0].args[0] != ops[-2].result or
- block.exitswitch is not None or
- block.exits[0].args[1] != ops[-1].result or
- not isinstance(ops[-4].args[1], Constant) or
- ops[-4].args[1].value != "typeptr"):
+ currvar = block.exits[0].args[1]
+ for op in block.operations[::-1]:
+ if op.opname in ("same_as", "cast_pointer") and op.result is currvar:
+ currvar = op.args[0]
+ elif op.opname == "malloc" and op.result is currvar:
+ break
+ else:
return None, None
- return ops[-4].args[2].value, block.exits[0]
+ return Ptr(op.args[0].value), block.exits[0]
def does_raise_directly(graph, raise_analyzer):
""" this function checks, whether graph contains operations which can raise
@@ -102,7 +105,8 @@
return False
class BaseInliner(object):
- def __init__(self, translator, graph, inline_guarded_calls=False,
+ def __init__(self, translator, graph, lltype_to_classdef,
+ inline_guarded_calls=False,
inline_guarded_calls_no_matter_what=False, raise_analyzer=None):
self.translator = translator
self.graph = graph
@@ -115,6 +119,7 @@
self.raise_analyzer = raise_analyzer
else:
self.raise_analyzer = None
+ self.lltype_to_classdef = lltype_to_classdef
def inline_all(self):
count = 0
@@ -275,22 +280,27 @@
def rewire_exceptblock_with_guard(self, afterblock, copiedexceptblock):
# this rewiring does not always succeed. in the cases where it doesn't
# there will be generic code inserted
+ from pypy.rpython.lltypesystem import rclass
exc_match = self.translator.rtyper.getexceptiondata().fn_exception_match
for link in self.entrymap[self.graph_to_inline.exceptblock]:
copiedblock = self.copy_block(link.prevblock)
- eclass, copiedlink = _find_exception_type(copiedblock)
+ VALUE, copiedlink = _find_exception_type(copiedblock)
#print copiedblock.operations
- if eclass is None:
+ if VALUE is None or VALUE not in self.lltype_to_classdef:
continue
- etype = copiedlink.args[0]
- evalue = copiedlink.args[1]
+ classdef = self.lltype_to_classdef[VALUE]
+ rtyper = self.translator.rtyper
+ classrepr = rclass.getclassrepr(rtyper, classdef)
+ vtable = classrepr.getruntime()
+ var_etype = copiedlink.args[0]
+ var_evalue = copiedlink.args[1]
for exceptionlink in afterblock.exits[1:]:
- if exc_match(eclass, exceptionlink.llexitcase):
+ if exc_match(vtable, exceptionlink.llexitcase):
passon_vars = self.passon_vars(link.prevblock)
copiedblock.operations += generate_keepalive(passon_vars)
copiedlink.target = exceptionlink.target
linkargs = self.find_args_in_exceptional_case(
- exceptionlink, link.prevblock, etype, evalue, afterblock, passon_vars)
+ exceptionlink, link.prevblock, var_etype, var_evalue, afterblock, passon_vars)
copiedlink.args = linkargs
break
@@ -388,9 +398,9 @@
class Inliner(BaseInliner):
- def __init__(self, translator, graph, inline_func, inline_guarded_calls=False,
+ def __init__(self, translator, graph, inline_func, lltype_to_classdef, inline_guarded_calls=False,
inline_guarded_calls_no_matter_what=False, raise_analyzer=None):
- BaseInliner.__init__(self, translator, graph,
+ BaseInliner.__init__(self, translator, graph, lltype_to_classdef,
inline_guarded_calls,
inline_guarded_calls_no_matter_what,
raise_analyzer)
@@ -404,21 +414,10 @@
self.block_to_index.setdefault(block, {})[i] = g
class OneShotInliner(BaseInliner):
- def __init__(self, translator, graph, inline_guarded_calls=False,
- inline_guarded_calls_no_matter_what=False, raise_analyzer=None):
- BaseInliner.__init__(self, translator, graph,
- inline_guarded_calls,
- inline_guarded_calls_no_matter_what,
- raise_analyzer)
-
def search_for_calls(self, block):
pass
-def _inline_function(translator, graph, block, index_operation):
- inline_func = block.operations[index_operation].args[0].value._obj._callable
- inliner = Inliner(translator, graph, inline_func)
-
# ____________________________________________________________
#
# Automatic inlining
@@ -426,14 +425,17 @@
OP_WEIGHTS = {'same_as': 0,
'cast_pointer': 0,
'keepalive': 0,
- 'direct_call': 2, # guess
- 'indirect_call': 2, # guess
+ 'malloc': 2,
'yield_current_frame_to_caller': sys.maxint, # XXX bit extreme
}
def block_weight(block, weights=OP_WEIGHTS):
total = 0
for op in block.operations:
+ if op.opname == "direct_call":
+ total += 1.5 + len(op.args) / 2
+ elif op.opname == "indirect_call":
+ total += 2 + len(op.args) / 2
total += weights.get(op.opname, 1)
if block.exitswitch is not None:
total += 1
@@ -446,15 +448,34 @@
for block in graph.iterblocks():
blockmap[block] = len(blocks)
blocks.append(block)
+ backedges = dict.fromkeys(find_backedges(graph), True)
+ loops = find_loop_blocks(graph)
M = sparsemat.SparseMatrix(len(blocks))
vector = []
for i, block in enumerate(blocks):
vector.append(block_weight(block))
M[i, i] = 1
if block.exits:
- f = 1.0 / len(block.exits)
+ if block not in loops:
+ current_loop_start = None
+ else:
+ current_loop_start = loops[block]
+ loop_exits = []
for link in block.exits:
- M[i, blockmap[link.target]] -= f
+ if (link.target in loops and
+ loops[link.target] is current_loop_start):
+ loop_exits.append(link)
+ if len(loop_exits) and len(loop_exits) < len(block.exits):
+ f = 0.3 / (len(block.exits) - len(loop_exits))
+ b = 0.7 / len(loop_exits)
+ else:
+ b = f = 1.0 / len(block.exits)
+ for link in block.exits:
+ if (link.target in loops and
+ loops[link.target] is current_loop_start):
+ M[i, blockmap[link.target]] -= b
+ else:
+ M[i, blockmap[link.target]] -= f
try:
Solution = M.solve(vector)
except ValueError:
@@ -507,30 +528,33 @@
for graph1, graph2 in static_callers(translator, ignore_primitives=True):
callers.setdefault(graph2, {})[graph1] = True
callees.setdefault(graph1, {})[graph2] = True
- fiboheap = [(0.0, graph) for graph in callers]
+ heap = [(0.0, -len(callers[graph]), graph) for graph in callers]
valid_weight = {}
couldnt_inline = {}
+ lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping()
- while fiboheap:
- weight, graph = fiboheap[0]
+ while heap:
+ weight, _, graph = heap[0]
if not valid_weight.get(graph):
weight = inlining_heuristic(graph, callers.get(graph), callees.get(graph))
#print ' + cost %7.2f %50s' % (weight, graph.name)
- heapreplace(fiboheap, (weight, graph))
+ heapreplace(heap, (weight, -len(callers[graph]), graph))
valid_weight[graph] = True
continue
if weight >= threshold:
break # finished
- heappop(fiboheap)
- log.inlining('%7.2f %50s' % (weight, graph.name))
+ heappop(heap)
+ if callers[graph]:
+ log.inlining('%7.2f %50s' % (weight, graph.name))
for parentgraph in callers[graph]:
if parentgraph == graph:
continue
sys.stdout.flush()
try:
- res = bool(inline_function(translator, graph, parentgraph))
+ res = bool(inline_function(translator, graph, parentgraph,
+ lltype_to_classdef))
except CannotInline:
couldnt_inline[graph] = True
res = CannotInline
@@ -545,5 +569,5 @@
# been modified. Maybe now we can inline it into further
# parents?
del couldnt_inline[parentgraph]
- heappush(fiboheap, (0.0, parentgraph))
+ heappush(heap, (0.0, -len(callers[parentgraph]), parentgraph))
valid_weight[parentgraph] = False
More information about the Pypy-commit
mailing list