def analyze_dependence(program): program_w_attributes = assign_node_ids(program) graph = DependenceGraph() for (ref1, ref2) in iterate_unique_reference_pairs(program_w_attributes): for dependence_dv in iterate_dependence_direction_vectors(ref1, ref2): for ref1_then_ref2_dv in iterate_execution_order_direction_vector( ref1, ref2): logger.debug( f'Testing:\n' f'{ref1.pprint()} -> {ref2.pprint()}:, ' f'dep({dependence_dv}) exe_order({ref1_then_ref2_dv})') dv1 = calculate_valid_direction_vector(dependence_dv, ref1_then_ref2_dv) if dv1 is not None: logger.debug(f'Valid direction vector: {dv1}') graph.add(ref1, ref2, dv1) dependence_dv_inv = negate_direction_vector(dependence_dv) for ref2_then_ref1_dv in iterate_execution_order_direction_vector( ref2, ref1): logger.debug( f'Testing:\n' f'{ref2.pprint()} -> {ref2.pprint()}:, ' f'dep({dependence_dv_inv}) exe_order({ref2_then_ref1_dv})') dv2 = calculate_valid_direction_vector(dependence_dv_inv, ref2_then_ref1_dv) if dv2 is not None: logger.debug(f'Valid direction vector: {dv2}') graph.add(ref2, ref1, dv2) return graph, program_w_attributes
class LoopFusion(Transform): def pre_apply(self, fn): self.graph = DependenceGraph() self.graph.visit_fn(fn) self.waiting = self.graph.nodes self.added = set([]) self.scopes = [] def post_apply(self, fn): if len(self.waiting) != 0: print "Statement nodes not added:" for stmt_node in self.waiting: print " -- ", stmt_node assert False, "Not all statements added back to program!" def transform_block(self, old_stmts): """ Do an extremely slow and inefficient topological sort (change this later, now just prototyping) """ first_iter = True n_added = 0 scope = id(old_stmts) self.scopes.append(scope) new_stmts = [] while first_iter or n_added > 0: n_added = 0 first_iter = False for node in sorted(list(self.waiting)): if node.id not in self.added and \ node.scope == scope and \ all(node_id in self.added or node_id == node.id for node_id in node.depends_on): self.waiting.remove(node) stmt = self.transform_stmt(node.stmt) new_stmts.append(stmt) self.added.add(node.id) n_added += 1 self.scopes.pop() return new_stmts
def pre_apply(self, fn): self.graph = DependenceGraph() self.graph.visit_fn(fn) self.waiting = self.graph.nodes self.added = set([]) self.scopes = []