def transition_copy_graph(func, env): """ Transition to a new phase: - create a copy of all functions in the call graph - update and cache copied function results in the 'flypy.state.copies' dict """ if not isinstance(func, ir.Function): return func, env graph = callgraph.callgraph(func) envs = env['flypy.state.envs'] phase = env['flypy.state.phase'] func_copies = env['flypy.state.copies'] if phase in func_copies: _, new_func, new_env = func_copies[phase] return new_func, new_env all_copies = find_copies(graph, envs, phase) copying.copy_graph(func, env, all_copies, graph) update_copies(all_copies, phase) _, new_func, new_env = func_copies[phase] return new_func, new_env
def transition_copy_graph(func, env): """ Transition to a new phase: - create a copy of all functions in the call graph - update and cache copied function results in the 'numba.state.copies' dict """ if not isinstance(func, ir.Function): return func, env graph = callgraph.callgraph(func) envs = env['numba.state.envs'] phase = env['numba.state.phase'] func_copies = env['numba.state.copies'] if phase in func_copies: _, new_func, new_env = func_copies[phase] return new_func, new_env all_copies = find_copies(graph, envs, phase) copying.copy_graph(func, env, all_copies, graph) update_copies(all_copies, phase) _, new_func, new_env = func_copies[phase] return new_func, new_env
def test_simple_callgraph(self): g = self.m.get_function('g') f = self.m.get_function('f') G = callgraph.callgraph(g) assert f in G.node assert g in G.node assert f in G.successors(g) assert not G.successors(f)
def generator_fusion(func, env): changed = True envs = env['flypy.state.envs'] dependences = callgraph.callgraph(func).node while changed: changed = False for f in dependences: e = envs[f] consumers = identify_consumers(f, e) #print("consumers", f.name, consumers) fuse_generators(f, e, consumers) changed |= bool(consumers)
def apply_all(phase, func, env, dependences=None): """Apply a phase to a function and its dependences""" if dependences is None: dependences = callgraph.callgraph(func).node envs = env["flypy.state.envs"] for dep in dependences: if func != dep: dep_env = envs[dep] phase.apply_single(dep, dep_env) return phase.apply_single(func, env)
def copy_graph(func, env, funcs=None, graph=None): """ Copy a function graph. """ if funcs is None: funcs = {} graph = graph or callgraph.callgraph(func) envs = env['flypy.state.envs'] copy_functions(graph, funcs, envs) update_callgraph(graph, funcs) return funcs
def _deps(func, debug=False): """ Locate dependences for a function. """ graph = callgraph.callgraph(func) if debug: import networkx as nx G = nx.DiGraph() for src in graph.node: for dst in graph.neighbors(src): G.add_edge(src.name, dst.name) dump(G, os.path.expanduser("~/callgraph.dot")) return graph.node
def code_generation(func, env, codegen=None): """ Invoke the code generator after initializing all functions in the call graph """ codegen = codegen or env["codegen.impl"] cache = env["codegen.cache"] graph = callgraph.callgraph(func) for callee in graph.node: if callee not in cache: cache[callee] = codegen.initialize(callee, env) # TODO: Different environments for each function? results = {} for callee in graph.node: results[callee] = codegen.translate(callee, env, cache[callee]) return results[func], env
def run(func, env): envs = env["flypy.state.envs"] dependences = [d for d in callgraph.callgraph(func).node] env["flypy.state.dependences"] = dependences
def _deps(func): return callgraph.callgraph(func).node
def apply_and_resolve(phase, func, env, graph=None): """Apply a phase to a function and its dependences""" graph = graph or callgraph.callgraph(func) envs = env["numba.state.envs"] for f in graph.node: phase(f, envs[f])