def is_loop_invariant(self, node, loop_node): node_dependency_set = self.get_node_dependencies(node) # print "is loop invariant node:", node # for x in node_dependency_set: # print " dep:", x # find dependencies within the loop node but outside the node we're checking node_dependency_set_except_node_tree = node_dependency_set - set(flatten_tree(node)) dependencies_within_loop = set(flatten_tree(loop_node)).intersection( node_dependency_set_except_node_tree) depends_on_loop_variants = bool(loop_node.loop_variant_set.intersection( node_dependency_set)) # TODO: Disabling warnings for now. They are useless witout # filenames. Also need to make sure all these cases are valid. # if not depends_on_loop_variants and dependencies_within_loop: # # we can't assume this is invariant because it depends on other # # nodes inside the loop. eventually we should hoist out both the # # node and its dependencies. # dependency_nodes = '\n'.join(' %s' % node.parent for node in dependencies_within_loop) # logging.warning("Cannot hoist possible loop invariant: %s.", node) # logging.warning("Please move following dependencies out of the loop:\n%s", # dependency_nodes) return not depends_on_loop_variants and not dependencies_within_loop
def get_node_dependencies(self, node): node_dependency_set = set(flatten_tree(node)) parent_block = self.get_parent_block(node) for n in list(node_dependency_set): # when this is an identifier, you need to check all of the potential # the dependencies for that symbol, which means doing some crawling if isinstance(n, IdentifierNode): identifier = n parent_block_to_check = parent_block while parent_block_to_check: for block_node in parent_block_to_check.child_nodes: if isinstance(block_node, AssignNode): if block_node.left == identifier: node_dependency_set.update( self.get_node_dependencies(block_node.right)) parent_block_to_check = None break elif isinstance(block_node, IfNode): # if you encounter a conditional in your chain, you depend on any # dependencies of the condition itself # FIXME: calling get_node_dependencies(block_node.test_expression) # causes an infinite loop, but that is probably the correct way # forward to address the dependency chain node_dependency_set.update( flatten_tree(block_node.test_expression)) else: parent_block_to_check = self.get_parent_block( parent_block_to_check) #elif isinstance(n, (GetUDNNode, FilterNode)): # node_dependency_set.update( # self.get_node_dependencies(node.expression)) #print "get_node_dependencies", node #print " deps:", node_dependency_set return node_dependency_set
def _get_identifiers_from_expression(node): """Find the IdentifierNodes present in an expression. This function searches through the nodes of an expression and returns a set of the IdentiferNodes that are present. This function doesn't traverse ast.GetAttrNode or any LiteralNodes such as ListLiteral or DictLiteral nodes. """ return set([n for n in walker.flatten_tree(node) if isinstance(n, ast.IdentifierNode)])