Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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()
Beispiel #4
0
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()
Beispiel #5
0
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()))
Beispiel #6
0
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()))
Beispiel #7
0
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()))
Beispiel #8
0
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()))
Beispiel #9
0
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)
Beispiel #10
0
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)