1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
from __future__ import print_function
from rpython.translator.backendopt import removenoops
from rpython.translator.backendopt import inline
from rpython.translator.backendopt.malloc import remove_mallocs
from rpython.translator.backendopt.constfold import constant_fold_graph
from rpython.translator.backendopt.constfold import replace_we_are_jitted
from rpython.translator.backendopt.stat import print_statistics
from rpython.translator.backendopt.merge_if_blocks import merge_if_blocks
from rpython.translator import simplify
from rpython.translator.backendopt.removeassert import remove_asserts
from rpython.translator.backendopt.support import log
from rpython.translator.backendopt.storesink import storesink_graph
from rpython.translator.backendopt import gilanalysis
from rpython.flowspace.model import checkgraph
INLINE_THRESHOLD_FOR_TEST = 33
def get_function(dottedname):
parts = dottedname.split('.')
module = '.'.join(parts[:-1])
name = parts[-1]
try:
mod = __import__(module, {}, {}, ['__doc__'])
except ImportError as e:
raise Exception("Import error loading %s: %s" % (dottedname, e))
try:
func = getattr(mod, name)
except AttributeError:
raise Exception("Function %s not found in module" % dottedname)
return func
def backend_optimizations(translator, graphs=None, secondary=False,
inline_graph_from_anywhere=False, **kwds):
# sensible keywords are
# inline_threshold, mallocs
# merge_if_blocks, constfold, heap2stack
# remove_asserts
# replace_we_are_jitted
config = translator.config.translation.backendopt.copy(as_default=True)
config.set(**kwds)
if graphs is None:
graphs = translator.graphs
for graph in graphs:
assert not hasattr(graph, '_seen_by_the_backend')
if config.print_statistics:
print("before optimizations:")
print_statistics(translator.graphs[0], translator, "per-graph.txt")
if config.replace_we_are_jitted:
for graph in graphs:
replace_we_are_jitted(graph)
if config.remove_asserts:
constfold(config, graphs)
remove_asserts(translator, graphs)
if config.really_remove_asserts:
for graph in graphs:
removenoops.remove_debug_assert(graph)
# the dead operations will be killed by the remove_obvious_noops below
# remove obvious no-ops
def remove_obvious_noops():
for graph in graphs:
removenoops.remove_same_as(graph)
simplify.eliminate_empty_blocks(graph)
simplify.transform_dead_op_vars(graph, translator)
removenoops.remove_duplicate_casts(graph, translator)
if config.print_statistics:
print("after no-op removal:")
print_statistics(translator.graphs[0], translator)
remove_obvious_noops()
if config.inline or config.mallocs:
heuristic = get_function(config.inline_heuristic)
if config.inline:
threshold = config.inline_threshold
else:
threshold = 0
inline_malloc_removal_phase(config, translator, graphs,
threshold,
inline_heuristic=heuristic,
inline_graph_from_anywhere=inline_graph_from_anywhere)
constfold(config, graphs)
if config.storesink:
remove_obvious_noops()
for graph in graphs:
storesink_graph(graph)
if config.profile_based_inline and not secondary:
threshold = config.profile_based_inline_threshold
heuristic = get_function(config.profile_based_inline_heuristic)
inline.instrument_inline_candidates(graphs, threshold)
counters = translator.driver_instrument_result(
config.profile_based_inline)
n = len(counters)
def call_count_pred(label):
if label >= n:
return False
return counters[label] > 250 # xxx introduce an option for this
inline_malloc_removal_phase(config, translator, graphs,
threshold,
inline_heuristic=heuristic,
call_count_pred=call_count_pred)
constfold(config, graphs)
if config.merge_if_blocks:
log.mergeifblocks("starting to merge if blocks")
for graph in graphs:
merge_if_blocks(graph, translator.config.translation.verbose)
if config.print_statistics:
print("after if-to-switch:")
print_statistics(translator.graphs[0], translator)
remove_obvious_noops()
for graph in graphs:
checkgraph(graph)
gilanalysis.analyze(graphs, translator)
def constfold(config, graphs):
if config.constfold:
for graph in graphs:
constant_fold_graph(graph)
def inline_malloc_removal_phase(config, translator, graphs, inline_threshold,
inline_heuristic,
call_count_pred=None,
inline_graph_from_anywhere=False):
# inline functions in each other
if inline_threshold:
log.inlining("phase with threshold factor: %s" % inline_threshold)
log.inlining("heuristic: %s.%s" % (inline_heuristic.__module__,
inline_heuristic.__name__))
inline.auto_inline_graphs(translator, graphs, inline_threshold,
heuristic=inline_heuristic,
call_count_pred=call_count_pred,
inline_graph_from_anywhere=inline_graph_from_anywhere)
if config.print_statistics:
print("after inlining:")
print_statistics(translator.graphs[0], translator)
# vaporize mallocs
if config.mallocs:
log.malloc("starting malloc removal")
remove_mallocs(translator, graphs)
if config.print_statistics:
print("after malloc removal:")
print_statistics(translator.graphs[0], translator)
|