Exemplo n.º 1
0
def function_limit_bound (fname, split):
    p = functions[fname].as_problem (problem.Problem)
    p.do_loop_analysis (skipInnerLoopCheck = True)
    [p_split] = [n for n in p.loop_heads () if split in p.loop_body (n)]
    splits = [n for n in p.loop_body (p_split) if p.loop_splittables[n]]
    # doesn't cover a really odd case, but I think it's good enough
    for n in splits:
      if p.nodes[n].kind == 'Call':
        if function_limit (p.nodes[n].fname) != None:
          return (function_limit (p.nodes[n].fname), 'FunctionLimit')
    return None
Exemplo n.º 2
0
def function_limit_bound(fname, split):
    p = functions[fname].as_problem(problem.Problem)
    p.do_analysis()
    cuts = [n for n in p.loop_body(split) if p.nodes[n].kind == "Call" if function_limit(p.nodes[n].fname) != None]
    if not cuts:
        return None
    graph = p.mk_node_graph(p.loop_body(split))
    # it is not possible to iterate the loop without visiting a bounded
    # function. naively, this sets the limit to the sum of all the possible
    # bounds, plus one because we can enter the loop a final time without
    # visiting any function call site yet.
    if logic.divides_loop(graph, set(cuts)):
        fnames = set([p.nodes[n].fname for n in cuts])
        return (sum([function_limit(f) for f in fnames]) + 1, "FunctionLimit")
Exemplo n.º 3
0
def function_limit_bound(fname, split):
    p = functions[fname].as_problem(problem.Problem)
    p.do_analysis()
    cuts = [
        n for n in p.loop_body(split) if p.nodes[n].kind == 'Call'
        if function_limit(p.nodes[n].fname) != None
    ]
    if not cuts:
        return None
    graph = p.mk_node_graph(p.loop_body(split))
    # it is not possible to iterate the loop without visiting a bounded
    # function. naively, this sets the limit to the sum of all the possible
    # bounds, plus one because we can enter the loop a final time without
    # visiting any function call site yet.
    if logic.divides_loop(graph, set(cuts)):
        fnames = set([p.nodes[n].fname for n in cuts])
        return (sum([function_limit(f) for f in fnames]) + 1, 'FunctionLimit')
Exemplo n.º 4
0
def get_bound_super_ctxt_inner(split, call_ctxt, no_splitting=(False, None)):
    first_f = trace_refute.identify_function([], (call_ctxt + [split])[:1])
    call_sites = all_call_sites(first_f)

    if function_limit(first_f) == 0:
        return (0, "FunctionLimit")
    safe_call_sites = [cs for cs in call_sites if ctxt_within_function_limits([cs] + call_ctxt)]
    if call_sites and not safe_call_sites:
        return (0, "FunctionLimit")

    if len(call_ctxt) < 3 and len(safe_call_sites) == 1:
        call_ctxt2 = list(safe_call_sites) + call_ctxt
        if call_ctxt_computable(split, call_ctxt2):
            return get_bound_super_ctxt(split, call_ctxt2)

    fname = trace_refute.identify_function(call_ctxt, [split])
    bound = function_limit_bound(fname, split)
    if bound:
        return bound

    bound = get_bound_ctxt(split, call_ctxt)
    if bound:
        return bound

    if no_splitting[0]:
        assert no_splitting[1], no_splitting
        no_splitting[1][0] = True
        return None

    # try to split over potential call sites
    if len(call_ctxt) >= 3:
        return None

    if len(call_sites) == 0:
        # either entry point or nonsense
        return None

    if [call_site for call_site in safe_call_sites if not call_ctxt_computable(split, [call_site] + call_ctxt)]:
        return None

    anc_bounds = [
        get_bound_super_ctxt(split, [call_site] + call_ctxt, no_splitting=True) for call_site in safe_call_sites
    ]
    if None in anc_bounds:
        return None
    (bound, kind) = max(anc_bounds)
    return (bound, "MergedBound")
Exemplo n.º 5
0
def get_bound_super_ctxt_inner(split, call_ctxt, no_splitting=(False, None)):
    first_f = trace_refute.identify_function([], (call_ctxt + [split])[:1])
    call_sites = all_call_sites(first_f)

    if function_limit(first_f) == 0:
        return (0, 'FunctionLimit')
    safe_call_sites = [
        cs for cs in call_sites
        if ctxt_within_function_limits([cs] + call_ctxt)
    ]
    if call_sites and not safe_call_sites:
        return (0, 'FunctionLimit')

    if len(call_ctxt) < 3 and len(safe_call_sites) == 1:
        call_ctxt2 = list(safe_call_sites) + call_ctxt
        if call_ctxt_computable(split, call_ctxt2):
            trace('using unique calling context %s' % str((split, call_ctxt2)))
            return get_bound_super_ctxt(split, call_ctxt2)

    fname = trace_refute.identify_function(call_ctxt, [split])
    bound = function_limit_bound(fname, split)
    if bound:
        return bound

    bound = get_bound_ctxt(split, call_ctxt)
    if bound:
        return bound

    trace('no bound found immediately.')

    if no_splitting[0]:
        assert no_splitting[1], no_splitting
        no_splitting[1][0] = True
        trace('cannot split by context (recursion).')
        return None

    # try to split over potential call sites
    if len(call_ctxt) >= 3:
        trace('cannot split by context (context depth).')
        return None

    if len(call_sites) == 0:
        # either entry point or nonsense
        trace('cannot split by context (reached top level).')
        return None

    problem_sites = [
        call_site for call_site in safe_call_sites
        if not call_ctxt_computable(split, [call_site] + call_ctxt)
    ]
    if problem_sites:
        trace('cannot split by context (issues in %s).' % problem_sites)
        return None

    anc_bounds = [
        get_bound_super_ctxt(split, [call_site] + call_ctxt, no_splitting=True)
        for call_site in safe_call_sites
    ]
    if None in anc_bounds:
        return None
    (bound, kind) = max(anc_bounds)
    return (bound, 'MergedBound')