예제 #1
0
def remove_asserts(translator, graphs):
    rtyper = translator.rtyper
    clsdef = translator.annotator.bookkeeper.getuniqueclassdef(AssertionError)
    r_AssertionError = rclass.getclassrepr(rtyper, clsdef)
    ll_AssertionError = r_AssertionError.convert_const(AssertionError)
    total_count = [0, 0]

    for graph in graphs:
        count = 0
        morework = True
        while morework:
            morework = False
            eliminate_empty_blocks(graph)
            join_blocks(graph)
            for link in graph.iterlinks():
                if (link.target is graph.exceptblock
                    and isinstance(link.args[0], Constant)
                    and link.args[0].value == ll_AssertionError):
                    if kill_assertion_link(graph, link):
                        count += 1
                        morework = True
                        break
                    else:
                        total_count[0] += 1
                        if translator.config.translation.verbose:
                            log.removeassert("cannot remove an assert from %s" % (graph.name,))
        if count:
            # now melt away the (hopefully) dead operation that compute
            # the condition
            total_count[1] += count
            if translator.config.translation.verbose:
                log.removeassert("removed %d asserts in %s" % (count, graph.name))
            checkgraph(graph)
            #transform_dead_op_vars(graph, translator)
    log.removeassert("Could not remove %d asserts, but removed %d asserts." % tuple(total_count))
예제 #2
0
파일: llimpl.py 프로젝트: TheDunn/flex-pypy
def show_incremental_progress(gv_func):
    from pypy import conftest
    graph = _getgraph(gv_func)
    fixduplicatevars(graph)
    flowmodel.checkgraph(graph)
    if conftest.option.view:
        eliminate_empty_blocks(graph)
        graph.show()
예제 #3
0
def show_incremental_progress(gv_func):
    from pypy import conftest
    graph = _getgraph(gv_func)
    fixduplicatevars(graph)
    flowmodel.checkgraph(graph)
    if conftest.option.view:
        eliminate_empty_blocks(graph)
        graph.show()
예제 #4
0
파일: all.py 프로젝트: xx312022850/pypy
    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)
예제 #5
0
파일: all.py 프로젝트: enyst/plexnet
    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)
예제 #6
0
파일: llimpl.py 프로젝트: TheDunn/flex-pypy
def _buildgraph(graph):
    assert graph.startblock.operations[0].opname == 'debug_assert'
    del graph.startblock.operations[0]
    # rgenop makes graphs that use the same variable in several blocks,
    fixduplicatevars(graph)                             # fix this now
    flowmodel.checkgraph(graph)
    eliminate_empty_blocks(graph)
    # we cannot call join_blocks(graph) here!  It has a subtle problem:
    # it copies operations between blocks without renaming op.result.
    # See test_promotion.test_many_promotions for a failure.
    graph.rgenop = True
    return graph
예제 #7
0
def _buildgraph(graph):
    assert graph.startblock.operations[0].opname == 'debug_assert'
    del graph.startblock.operations[0]
    # rgenop makes graphs that use the same variable in several blocks,
    fixduplicatevars(graph)  # fix this now
    flowmodel.checkgraph(graph)
    eliminate_empty_blocks(graph)
    # we cannot call join_blocks(graph) here!  It has a subtle problem:
    # it copies operations between blocks without renaming op.result.
    # See test_promotion.test_many_promotions for a failure.
    graph.rgenop = True
    return graph
예제 #8
0
    def check_auto_inlining(self,
                            func,
                            sig,
                            multiplier=None,
                            call_count_check=False,
                            checkvirtual=False,
                            remove_same_as=False,
                            heuristic=None,
                            const_fold_first=False):
        t = self.translate(func, sig)
        if checkvirtual:
            check_virtual_methods()
        if const_fold_first:
            from pypy.translator.backendopt.constfold import constant_fold_graph
            from pypy.translator.simplify import eliminate_empty_blocks
            for graph in t.graphs:
                constant_fold_graph(graph)
                eliminate_empty_blocks(graph)
        if option.view:
            t.view()
        # inline!
        sanity_check(t)  # also check before inlining (so we don't blame it)

        threshold = INLINE_THRESHOLD_FOR_TEST
        if multiplier is not None:
            threshold *= multiplier

        call_count_pred = None
        if call_count_check:
            call_count_pred = lambda lbl: True
            instrument_inline_candidates(t.graphs, threshold)

        if remove_same_as:
            for graph in t.graphs:
                removenoops.remove_same_as(graph)

        if heuristic is not None:
            kwargs = {"heuristic": heuristic}
        else:
            kwargs = {}
        auto_inlining(t, threshold, call_count_pred=call_count_pred, **kwargs)

        sanity_check(t)
        if option.view:
            t.view()
        interp = LLInterpreter(t.rtyper)

        def eval_func(args):
            return interp.eval_graph(graphof(t, func), args)

        return eval_func, t
예제 #9
0
 def simplify(self, block_subset=None, extra_passes=None):
     # Generic simplifications
     transform.transform_graph(self, block_subset=block_subset,
                               extra_passes=extra_passes)
     if block_subset is None:
         graphs = self.translator.graphs
     else:
         graphs = {}
         for block in block_subset:
             graph = self.annotated.get(block)
             if graph:
                 graphs[graph] = True
     for graph in graphs:
         simplify.eliminate_empty_blocks(graph)
예제 #10
0
 def simplify(self, block_subset=None, extra_passes=None):
     # Generic simplifications
     transform.transform_graph(self, block_subset=block_subset,
                               extra_passes=extra_passes)
     if block_subset is None:
         graphs = self.translator.graphs
     else:
         graphs = {}
         for block in block_subset:
             graph = self.annotated.get(block)
             if graph:
                 graphs[graph] = True
     for graph in graphs:
         simplify.eliminate_empty_blocks(graph)
예제 #11
0
파일: malloc.py 프로젝트: TheDunn/flex-pypy
def remove_mallocs(translator, graphs=None, type_system="lltypesystem"):
    if graphs is None:
        graphs = translator.graphs
    tot = 0
    for graph in graphs:
        count = remove_simple_mallocs(graph, type_system=type_system, verbose=translator.config.translation.verbose)
        if count:
            # remove typical leftovers from malloc removal
            removenoops.remove_same_as(graph)
            simplify.eliminate_empty_blocks(graph)
            simplify.transform_dead_op_vars(graph, translator)
            tot += count
    log.malloc("removed %d simple mallocs in total" % tot)
    return tot
예제 #12
0
def remove_mallocs(translator, graphs=None, type_system="lltypesystem"):
    if graphs is None:
        graphs = translator.graphs
    tot = 0
    for graph in graphs:
        count = remove_simple_mallocs(
            graph,
            type_system=type_system,
            verbose=translator.config.translation.verbose)
        if count:
            # remove typical leftovers from malloc removal
            removenoops.remove_same_as(graph)
            simplify.eliminate_empty_blocks(graph)
            simplify.transform_dead_op_vars(graph, translator)
            tot += count
    log.malloc("removed %d simple mallocs in total" % tot)
    return tot
예제 #13
0
파일: test_inline.py 프로젝트: alkorzt/pypy
    def check_auto_inlining(self, func, sig, multiplier=None, call_count_check=False,
                            checkvirtual=False, remove_same_as=False, heuristic=None,
                            const_fold_first=False):
        t = self.translate(func, sig)
        if checkvirtual:
            check_virtual_methods()
        if const_fold_first:
            from pypy.translator.backendopt.constfold import constant_fold_graph
            from pypy.translator.simplify import eliminate_empty_blocks
            for graph in t.graphs:
                constant_fold_graph(graph)
                eliminate_empty_blocks(graph)
        if option.view:
            t.view()
        # inline!
        sanity_check(t)    # also check before inlining (so we don't blame it)

        threshold = INLINE_THRESHOLD_FOR_TEST
        if multiplier is not None:
            threshold *= multiplier

        call_count_pred = None
        if call_count_check:
            call_count_pred = lambda lbl: True
            instrument_inline_candidates(t.graphs, threshold)

        if remove_same_as:
            for graph in t.graphs:
                removenoops.remove_same_as(graph)
            
        if heuristic is not None:
            kwargs = {"heuristic": heuristic}
        else:
            kwargs = {}
        auto_inlining(t, threshold, call_count_pred=call_count_pred, **kwargs)

        sanity_check(t)
        if option.view:
            t.view()
        interp = LLInterpreter(t.rtyper)
        def eval_func(args):
            return interp.eval_graph(graphof(t, func), args)
        return eval_func, t
예제 #14
0
def remove_tail_calls_to_self(translator, graph):
    entrymap = mkentrymap(graph)
    changed = False
    for link in entrymap[graph.returnblock]:
        block = link.prevblock
        if (len(block.exits) == 1 and len(block.operations) > 0
                and block.operations[-1].opname == 'direct_call'
                and block.operations[-1].result == link.args[0]):
            call = get_graph(block.operations[-1].args[0], translator)
            print "getgraph", graph
            if graph is graph:
                _remove_tail_call(translator, graph, block)
                changed = True
    if changed:
        from pypy.translator import simplify
        checkgraph(graph)
        simplify.remove_identical_vars(graph)
        simplify.eliminate_empty_blocks(graph)
        simplify.join_blocks(graph)
예제 #15
0
def remove_tail_calls_to_self(translator, graph):
    entrymap = mkentrymap(graph)
    changed = False
    for link in entrymap[graph.returnblock]:
        block = link.prevblock
        if (len(block.exits) == 1 and
            len(block.operations) > 0 and
            block.operations[-1].opname == 'direct_call' and
            block.operations[-1].result == link.args[0]):
            call = get_graph(block.operations[-1].args[0], translator)
            print "getgraph", graph
            if graph is graph:
                _remove_tail_call(translator, graph, block)
                changed = True
    if changed:
        from pypy.translator import simplify
        checkgraph(graph)
        simplify.remove_identical_vars(graph)
        simplify.eliminate_empty_blocks(graph)
        simplify.join_blocks(graph)
예제 #16
0
def test_ignore_breaking_transformations():
    def f():
        pass
    f._annspecialcase_ = "override:ignore"
    def g(i):
        if i == 1:
            return "ab"
        else:
            try:
                return f()
            except:
                return "hello!"
    t, typer, graph = gengraph(g, [int])
    from pypy.translator import simplify
    from pypy.translator.backendopt import removenoops
    from pypy.objspace.flow.model import checkgraph
    removenoops.remove_same_as(graph)
    simplify.eliminate_empty_blocks(graph)
    #should not crash:
    checkgraph(graph)
예제 #17
0
def remove_asserts(translator, graphs):
    rtyper = translator.rtyper
    clsdef = translator.annotator.bookkeeper.getuniqueclassdef(AssertionError)
    r_AssertionError = rclass.getclassrepr(rtyper, clsdef)
    ll_AssertionError = r_AssertionError.convert_const(AssertionError)
    total_count = [0, 0]

    for graph in graphs:
        count = 0
        morework = True
        while morework:
            morework = False
            eliminate_empty_blocks(graph)
            join_blocks(graph)
            for link in graph.iterlinks():
                if (link.target is graph.exceptblock
                        and isinstance(link.args[0], Constant)
                        and link.args[0].value == ll_AssertionError):
                    if kill_assertion_link(graph, link):
                        count += 1
                        morework = True
                        break
                    else:
                        total_count[0] += 1
                        if translator.config.translation.verbose:
                            log.removeassert(
                                "cannot remove an assert from %s" %
                                (graph.name, ))
        if count:
            # now melt away the (hopefully) dead operation that compute
            # the condition
            total_count[1] += count
            if translator.config.translation.verbose:
                log.removeassert("removed %d asserts in %s" %
                                 (count, graph.name))
            checkgraph(graph)
            #transform_dead_op_vars(graph, translator)
    log.removeassert("Could not remove %d asserts, but removed %d asserts." %
                     tuple(total_count))
예제 #18
0
def tweak_generator_body_graph(Entry, graph):
    # First, always run simplify_graph in order to reduce the number of
    # variables passed around
    simplify_graph(graph)
    #
    assert graph.startblock.operations[0].opname == 'generator_mark'
    graph.startblock.operations.pop(0)
    #
    insert_empty_startblock(None, graph)
    _insert_reads(graph.startblock, Entry.varnames)
    Entry.block = graph.startblock
    #
    mappings = [Entry]
    #
    stopblock = Block([])
    v0 = Variable()
    v1 = Variable()
    stopblock.operations = [
        SpaceOperation('simple_call', [Constant(StopIteration)], v0),
        SpaceOperation('type', [v0], v1),
    ]
    stopblock.closeblock(Link([v1, v0], graph.exceptblock))
    #
    for block in list(graph.iterblocks()):
        for exit in block.exits:
            if exit.target is graph.returnblock:
                exit.args = []
                exit.target = stopblock
        assert block is not stopblock
        for index in range(len(block.operations) - 1, -1, -1):
            op = block.operations[index]
            if op.opname == 'yield':
                [v_yielded_value] = op.args
                del block.operations[index]
                newlink = split_block(None, block, index)
                newblock = newlink.target

                #
                class Resume(AbstractPosition):
                    _immutable_ = True
                    block = newblock

                Resume.__name__ = 'Resume%d' % len(mappings)
                mappings.append(Resume)
                varnames = get_variable_names(newlink.args)
                #
                _insert_reads(newblock, varnames)
                #
                v_resume = Variable('resume')
                block.operations.append(
                    SpaceOperation('simple_call', [Constant(Resume)],
                                   v_resume))
                for i, name in enumerate(varnames):
                    block.operations.append(
                        SpaceOperation(
                            'setattr',
                            [v_resume,
                             Constant(name), newlink.args[i]], Variable()))
                v_pair = Variable('pair')
                block.operations.append(
                    SpaceOperation('newtuple', [v_resume, v_yielded_value],
                                   v_pair))
                newlink.args = [v_pair]
                newlink.target = graph.returnblock
    #
    regular_entry_block = Block([Variable('entry')])
    block = regular_entry_block
    for Resume in mappings:
        v_check = Variable()
        block.operations.append(
            SpaceOperation(
                'simple_call',
                [Constant(isinstance), block.inputargs[0],
                 Constant(Resume)], v_check))
        block.exitswitch = v_check
        link1 = Link([block.inputargs[0]], Resume.block)
        link1.exitcase = True
        nextblock = Block([Variable('entry')])
        link2 = Link([block.inputargs[0]], nextblock)
        link2.exitcase = False
        block.closeblock(link1, link2)
        block = nextblock
    block.closeblock(
        Link([
            Constant(AssertionError),
            Constant(AssertionError("bad generator class"))
        ], graph.exceptblock))
    graph.startblock = regular_entry_block
    graph.signature = Signature(['entry'])
    graph.defaults = ()
    checkgraph(graph)
    eliminate_empty_blocks(graph)
예제 #19
0
파일: all.py 프로젝트: TheDunn/flex-pypy
def backend_optimizations(translator, graphs=None, secondary=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

    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 translator.rtyper.type_system.name == 'ootypesystem':
        check_virtual_methods()

    # remove obvious no-ops
    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)

    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)
        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.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.remove_asserts:
        remove_asserts(translator, graphs)

    if config.heap2stack:
        assert graphs is translator.graphs  # XXX for now
        malloc_to_stack(translator)

    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)

    for graph in graphs:
        checkgraph(graph)
예제 #20
0
파일: generator.py 프로젝트: Debug-Orz/Sypy
def tweak_generator_body_graph(Entry, graph):
    # First, always run simplify_graph in order to reduce the number of
    # variables passed around
    simplify_graph(graph)
    #
    assert graph.startblock.operations[0].opname == 'generator_mark'
    graph.startblock.operations.pop(0)
    #
    insert_empty_startblock(None, graph)
    _insert_reads(graph.startblock, Entry.varnames)
    Entry.block = graph.startblock
    #
    mappings = [Entry]
    #
    stopblock = Block([])
    v0 = Variable(); v1 = Variable()
    stopblock.operations = [
        SpaceOperation('simple_call', [Constant(StopIteration)], v0),
        SpaceOperation('type', [v0], v1),
        ]
    stopblock.closeblock(Link([v1, v0], graph.exceptblock))
    #
    for block in list(graph.iterblocks()):
        for exit in block.exits:
            if exit.target is graph.returnblock:
                exit.args = []
                exit.target = stopblock
        assert block is not stopblock
        for index in range(len(block.operations)-1, -1, -1):
            op = block.operations[index]
            if op.opname == 'yield':
                [v_yielded_value] = op.args
                del block.operations[index]
                newlink = split_block(None, block, index)
                newblock = newlink.target
                #
                class Resume(AbstractPosition):
                    _immutable_ = True
                    block = newblock
                Resume.__name__ = 'Resume%d' % len(mappings)
                mappings.append(Resume)
                varnames = get_variable_names(newlink.args)
                #
                _insert_reads(newblock, varnames)
                #
                v_resume = Variable('resume')
                block.operations.append(
                    SpaceOperation('simple_call', [Constant(Resume)],
                                   v_resume))
                for i, name in enumerate(varnames):
                    block.operations.append(
                        SpaceOperation('setattr', [v_resume, Constant(name),
                                                   newlink.args[i]],
                                       Variable()))
                v_pair = Variable('pair')
                block.operations.append(
                    SpaceOperation('newtuple', [v_resume, v_yielded_value],
                                   v_pair))
                newlink.args = [v_pair]
                newlink.target = graph.returnblock
    #
    regular_entry_block = Block([Variable('entry')])
    block = regular_entry_block
    for Resume in mappings:
        v_check = Variable()
        block.operations.append(
            SpaceOperation('simple_call', [Constant(isinstance),
                                           block.inputargs[0],
                                           Constant(Resume)],
                           v_check))
        block.exitswitch = v_check
        link1 = Link([block.inputargs[0]], Resume.block)
        link1.exitcase = True
        nextblock = Block([Variable('entry')])
        link2 = Link([block.inputargs[0]], nextblock)
        link2.exitcase = False
        block.closeblock(link1, link2)
        block = nextblock
    block.closeblock(Link([Constant(AssertionError),
                           Constant(AssertionError("bad generator class"))],
                          graph.exceptblock))
    graph.startblock = regular_entry_block
    graph.signature = Signature(['entry'])
    graph.defaults = ()
    checkgraph(graph)
    eliminate_empty_blocks(graph)