Example #1
0
def merge_if_blocks(graph, verbose=True):
    merge = False
    while merge_if_blocks_once(graph):
        merge = True
    if merge:
        if verbose:
            log("merging blocks in %s" % (graph.name, ))
        else:
            log.dot()
Example #2
0
def merge_if_blocks(graph, verbose=True):
    merge = False
    while merge_if_blocks_once(graph):
        merge = True
    if merge:
        if verbose:
            log("merging blocks in %s" % (graph.name, ))
        else:
            log.dot()
Example #3
0
 def remove_simple_mallocs(self, graph):
     """Iteratively remove (inline) the mallocs that can be simplified away."""
     tot = 0
     while True:
         count = self.remove_mallocs_once(graph)
         if count:
             if self.verbose:
                 log.malloc('%d simple mallocs removed in %r' % (count, graph.name))
             else:
                 log.dot()
             tot += count
         else:
             break
     return tot
Example #4
0
 def remove_simple_mallocs(self, graph):
     """Iteratively remove (inline) the mallocs that can be simplified away."""
     tot = 0
     while True:
         count = self.remove_mallocs_once(graph)
         if count:
             if self.verbose:
                 log.malloc('%d simple mallocs removed in %r' %
                            (count, graph.name))
             else:
                 log.dot()
             tot += count
         else:
             break
     return tot
Example #5
0
 def logresult(self, op, msg, exc=None):    # only for nice log outputs
     if self.verbose:
         if exc is None:
             exc = ''
         else:
             exc = ': %s' % (exc,)
         chain = []
         while True:
             chain.append(str(op.result))
             if op.opname != 'direct_call':
                 break
             fobj = op.args[0].value._obj
             op = self.inline_and_remove[fobj.graph]
         log.mallocv('%s %s%s' % ('->'.join(chain), msg, exc))
     elif exc is None:
         log.dot()
Example #6
0
 def logresult(self, op, msg, exc=None):    # only for nice log outputs
     if self.verbose:
         if exc is None:
             exc = ''
         else:
             exc = ': %s' % (exc,)
         chain = []
         while True:
             chain.append(str(op.result))
             if op.opname != 'direct_call':
                 break
             fobj = op.args[0].value._obj
             op = self.inline_and_remove[fobj.graph]
         log.mallocv('%s %s%s' % ('->'.join(chain), msg, exc))
     elif exc is None:
         log.dot()
Example #7
0
def auto_inlining(translator, threshold=None,
                  callgraph=None,
                  call_count_pred=None,
                  heuristic=inlining_heuristic):
    assert threshold is not None and threshold != 1
    from heapq import heappush, heappop, heapreplace, heapify
    callers = {}     # {graph: {graphs-that-call-it}}
    callees = {}     # {graph: {graphs-that-it-calls}}
    if callgraph is None:
        callgraph = inlinable_static_callers(translator.graphs)
    for graph1, graph2 in callgraph:
        callers.setdefault(graph2, {})[graph1] = True
        callees.setdefault(graph1, {})[graph2] = True
    # the -len(callers) change is OK
    heap = [(0.0, -len(callers[graph]), graph) for graph in callers]
    valid_weight = {}
    try_again = {}
    lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping()
    raise_analyzer = RaiseAnalyzer(translator)
    count = 0

    while heap:
        weight, _, graph = heap[0]
        if not valid_weight.get(graph):
            weight, fixed = heuristic(graph)
            #print '  + cost %7.2f %50s' % (weight, graph.name)
            heapreplace(heap, (weight, -len(callers[graph]), graph))
            valid_weight[graph] = True
            if not fixed:
                try_again[graph] = True
            continue

        if weight >= threshold:
            # finished... unless some graphs not in valid_weight would now
            # have a weight below the threshold.  Re-insert such graphs
            # at the start of the heap
            finished = True
            for i in range(len(heap)):
                graph = heap[i][2]
                if not valid_weight.get(graph):
                    heap[i] = (0.0, heap[i][1], graph)
                    finished = False
            if finished:
                break
            else:
                heapify(heap)
                continue

        heappop(heap)
        if callers[graph]:
            if translator.config.translation.verbose:
                log.inlining('%7.2f %50s' % (weight, graph.name))
            else:
                log.dot()
        for parentgraph in callers[graph]:
            if parentgraph == graph:
                continue
            subcount = 0
            try:
                subcount = inline_function(translator, graph, parentgraph,
                                           lltype_to_classdef, raise_analyzer,
                                           call_count_pred)
                res = bool(subcount)
            except CannotInline:
                try_again[graph] = True
                res = CannotInline
            if res is True:
                count += subcount
                # the parentgraph should now contain all calls that were
                # done by 'graph'
                for graph2 in callees.get(graph, {}):
                    callees[parentgraph][graph2] = True
                    callers[graph2][parentgraph] = True
                if parentgraph in try_again:
                    # the parentgraph was previously uninlinable, but it has
                    # been modified.  Maybe now we can inline it into further
                    # parents?
                    del try_again[parentgraph]
                    heappush(heap, (0.0, -len(callers[parentgraph]), parentgraph))
                valid_weight[parentgraph] = False
    return count
Example #8
0
File: inline.py Project: njues/Sypy
def auto_inlining(translator,
                  threshold=None,
                  callgraph=None,
                  call_count_pred=None,
                  heuristic=inlining_heuristic):

    assert threshold is not None and threshold != 1
    to_cleanup = {}
    from heapq import heappush, heappop, heapreplace, heapify
    callers = {}  # {graph: {graphs-that-call-it}}
    callees = {}  # {graph: {graphs-that-it-calls}}
    if callgraph is None:
        callgraph = inlinable_static_callers(translator.graphs)
    for graph1, graph2 in callgraph:
        callers.setdefault(graph2, {})[graph1] = True
        callees.setdefault(graph1, {})[graph2] = True
    # the -len(callers) change is OK
    heap = [(0.0, -len(callers[graph]), graph) for graph in callers]
    valid_weight = {}
    try_again = {}
    lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping()
    raise_analyzer = RaiseAnalyzer(translator)
    count = 0
    while heap:
        weight, _, graph = heap[0]
        if not valid_weight.get(graph):
            if hasattr(graph, 'func') and \
                   getattr(graph.func, '_always_inline_', None):
                weight, fixed = 0.0, True
            else:
                weight, fixed = heuristic(graph)
            #print '  + cost %7.2f %50s' % (weight, graph.name)
            heapreplace(heap, (weight, -len(callers[graph]), graph))
            valid_weight[graph] = True
            if not fixed:
                try_again[graph] = True
            continue

        if weight >= threshold:
            # finished... unless some graphs not in valid_weight would now
            # have a weight below the threshold.  Re-insert such graphs
            # at the start of the heap
            finished = True
            for i in range(len(heap)):
                graph = heap[i][2]
                if not valid_weight.get(graph):
                    heap[i] = (0.0, heap[i][1], graph)
                    finished = False
            if finished:
                break
            else:
                heapify(heap)
                continue

        heappop(heap)
        if callers[graph]:
            if translator.config.translation.verbose:
                log.inlining('%7.2f %50s' % (weight, graph.name))
            else:
                log.dot()
        for parentgraph in callers[graph]:
            if parentgraph == graph:
                continue
            subcount = 0
            try:
                subcount = inline_function(translator,
                                           graph,
                                           parentgraph,
                                           lltype_to_classdef,
                                           raise_analyzer,
                                           call_count_pred,
                                           cleanup=False)
                to_cleanup[parentgraph] = True
                res = bool(subcount)
            except CannotInline:
                try_again[graph] = True
                res = CannotInline
            if res is True:
                count += subcount
                # the parentgraph should now contain all calls that were
                # done by 'graph'
                for graph2 in callees.get(graph, {}):
                    callees[parentgraph][graph2] = True
                    callers[graph2][parentgraph] = True
                if parentgraph in try_again:
                    # the parentgraph was previously uninlinable, but it has
                    # been modified.  Maybe now we can inline it into further
                    # parents?
                    del try_again[parentgraph]
                    heappush(heap,
                             (0.0, -len(callers[parentgraph]), parentgraph))
                valid_weight[parentgraph] = False
    for graph in to_cleanup:
        cleanup_graph(graph)
    return count