def test_merge_several(): def merge(n, m): r = -1 if n == 0: if m == 0: r = 0 elif m == 1: r = 1 else: r = 2 elif n == 1: r = 4 else: r = 6 return r t = TranslationContext() a = t.buildannotator() a.build_types(merge, [int, int]) rtyper = t.buildrtyper() rtyper.specialize() graph = tgraphof(t, merge) remove_same_as(graph) merge_if_blocks(graph) assert len(graph.startblock.exits) == 3 assert len(list(graph.iterblocks())) == 3 interp = LLInterpreter(rtyper) for m in range(3): res = interp.eval_graph(graph, [0, m]) assert res == m res = interp.eval_graph(graph, [1, 0]) assert res == 4 res = interp.eval_graph(graph, [2, 0]) assert res == 6
def get_generated_c_source(fn, types): """Return the generated C source for fn.""" t = Translation(fn, types, backend="c") t.annotate() merge_if_blocks(t.driver.translator.graphs[0]) c_filename_path = t.source_c() return t.driver.cbuilder.c_source_filename.join('..', 'rpython_translator_c_test.c').read()
def get_generated_c_source(fn, types): """Return the generated C source for fn.""" t = Translation(fn, types, backend="c") t.annotate() merge_if_blocks(t.driver.translator.graphs[0]) c_filename_path = t.source_c() return t.driver.cbuilder.c_source_filename.join( '..', 'rpython_translator_c_test.c').read()
def test_two_constants(): def fn(): r = range(10, 37, 4) r.reverse() return r[0] t = TranslationContext() a = t.buildannotator() a.build_types(fn, []) rtyper = t.buildrtyper() rtyper.specialize() backend_optimizations(t, merge_if_blocks=True) graph = tgraphof(t, fn) blocknum = len(list(graph.iterblocks())) merge_if_blocks(graph) assert blocknum == len(list(graph.iterblocks()))
def test_dont_merge(): def merge(n, m): r = -1 if n == 0: r += m if n == 1: r += 2 * m else: r += 6 return r t = TranslationContext() a = t.buildannotator() a.build_types(merge, [int, int]) rtyper = t.buildrtyper() rtyper.specialize() graph = tgraphof(t, merge) remove_same_as(graph) blocknum = len(list(graph.iterblocks())) merge_if_blocks(graph) assert blocknum == len(list(graph.iterblocks()))
def backend_optimizations(translator, graphs=None, secondary=False, inline_graph_from_anywhere=False, **kwds): # sensible keywords are # raisingop2direct_call, inline_threshold, mallocs # merge_if_blocks, constfold, heap2stack # clever_malloc_removal, remove_asserts 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.raisingop2direct_call: raisingop2direct_call(translator, graphs) 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.clever_malloc_removal: threshold = config.clever_malloc_removal_threshold heuristic = get_function(config.clever_malloc_removal_heuristic) log.inlineandremove("phase with threshold factor: %s" % threshold) log.inlineandremove("heuristic: %s.%s" % (heuristic.__module__, heuristic.__name__)) count = mallocprediction.clever_inlining_and_malloc_removal( translator, graphs, threshold = threshold, heuristic=heuristic) log.inlineandremove("removed %d simple mallocs in total" % count) constfold(config, graphs) if config.print_statistics: print "after clever inlining and malloc removal" print_statistics(translator.graphs[0], translator) if config.storesink: 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 backend_optimizations(translator, graphs=None, secondary=False, inline_graph_from_anywhere=False, **kwds): # sensible keywords are # inline_threshold, mallocs # merge_if_blocks, constfold, heap2stack # clever_malloc_removal, 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.clever_malloc_removal: threshold = config.clever_malloc_removal_threshold heuristic = get_function(config.clever_malloc_removal_heuristic) log.inlineandremove("phase with threshold factor: %s" % threshold) log.inlineandremove("heuristic: %s.%s" % (heuristic.__module__, heuristic.__name__)) count = mallocprediction.clever_inlining_and_malloc_removal( translator, graphs, threshold = threshold, heuristic=heuristic) log.inlineandremove("removed %d simple mallocs in total" % count) constfold(config, graphs) if config.print_statistics: print "after clever inlining and malloc removal" print_statistics(translator.graphs[0], translator) if config.storesink: 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)