/// <summary> /// Expands <paramref name="nodesInLoop"/> with the cross edges exiting from it. /// </summary> /// <param name="nodesInLoop">The nodes, already part of the loop.</param> /// <returns>Returns the expanded collection of nodes.</returns> private ICollection <DFSTNode> ExpandLoopBodyWithCrossEdges(ICollection <DFSTNode> nodesInLoop) { HashSet <DFSTNode> hashetNodes = new HashSet <DFSTNode>(nodesInLoop); Queue <DFSTNode> queue = new Queue <DFSTNode>(nodesInLoop); /// Perform BFS on the nodes. while (queue.Count > 0) { DFSTNode currentNode = queue.Dequeue(); /// Traversing the predecessors. /// Traverse predecessors instead of successors for two reasons /// 1) Predecessors are sure to be part of the loop, since the node it precedes is in the loop, thus the predecessor /// is dominated by the ehader node as well. /// 2) For CrossEdge successors, this statement is not valid. Both the node and the successor have common dominator, /// but this might not be the loop header node. foreach (DFSTNode predecessor in currentNode.CrossEdgePredecessors) { if (!hashetNodes.Contains(predecessor)) { hashetNodes.Add(predecessor); queue.Enqueue(predecessor); } } DFSTNode nodePredecessor = currentNode.Predecessor as DFSTNode; if (nodePredecessor != null && !hashetNodes.Contains(nodePredecessor)) { hashetNodes.Add(nodePredecessor); queue.Enqueue(nodePredecessor); } } return(hashetNodes); }
/// <summary> /// Recursively traverses the nodes and adds them to the tree. Also determines the type of each edge. /// </summary> /// <param name="currentNode"></param> private void DFSBuild(DFSTNode currentNode) { traversedNodes.Add(currentNode); //The current path is the set of all nodes on the DFS tree path from the root to the current node. currentPath.Add(currentNode); foreach (ISingleEntrySubGraph successorConstruct in LogicalFlowUtilities.GetTraversableSuccessors(currentNode.Construct)) { DFSTNode successor; if(!constructToNodeMap.TryGetValue(successorConstruct, out successor)) { //Special case for interval constructs continue; } if (!traversedNodes.Contains(successor)) { //If the successor is not traversed then the edge between the two nodes is a tree edge. successor.Predecessor = currentNode; currentNode.TreeEdgeSuccessors.Add(successor); theTree.TreeEdges.Add(new DFSTEdge(currentNode, successor)); //We continue the build from this successor. DFSBuild(successor); } else if(currentPath.Contains(successor)) { //If the successor is traversed and is on the current path then the edge between the nodes is a back edge. successor.BackEdgePredecessors.Add(currentNode); currentNode.BackEdgeSuccessors.Add(successor); theTree.BackEdges.Add(new DFSTEdge(currentNode, successor)); } else if (IsAncestor(successor, currentNode)) { //If the successor is traversed and the current node is its ancestor, then the edge is a forward edge. successor.ForwardEdgePredecessors.Add(currentNode); currentNode.ForwardEdgeSucessors.Add(successor); theTree.ForwardEdges.Add(new DFSTEdge(currentNode, successor)); } else { //Otherwise the edge between the nodes is a cross edge. successor.CrossEdgePredecessors.Add(currentNode); currentNode.CrossEdgeSuccessors.Add(successor); theTree.CrossEdges.Add(new DFSTEdge(currentNode, successor)); } } currentPath.Remove(currentNode); //Adding the nodes in post order. theTree.ReversePostOrder.Add(currentNode); }
private List <DFSTNode> GetPredecessors(DFSTNode node) { List <DFSTNode> result = new List <DFSTNode>(); if (node.Predecessor != null) { result.Add(node.Predecessor as DFSTNode); } result.AddRange(node.ForwardEdgePredecessors); result.AddRange(node.CrossEdgePredecessors); result.AddRange(node.BackEdgePredecessors); return(result); }
/// <summary> /// Removes backedges exiting from <paramref name="loopConstruct"/>. /// </summary> /// <param name="loopConstruct">The loop construct.</param> private void CleanUpEdges(LoopLogicalConstruct loopConstruct) { DFSTree dfsTree = DFSTBuilder.BuildTree(loopConstruct.Parent); DFSTNode loopNode = dfsTree.ConstructToNodeMap[loopConstruct]; if (loopNode.BackEdgeSuccessors.Count == 0) { return; } foreach (DFSTNode backedgeSuccessor in loopNode.BackEdgeSuccessors) { ILogicalConstruct edgeEndConstruct = backedgeSuccessor.Construct as ILogicalConstruct; if (!(edgeEndConstruct is ConditionLogicalConstruct)) /// if the target is ConditionLogicalConstruct, it can probably be a header of outer loop { MarkAsGotoEdge(loopConstruct, backedgeSuccessor.Construct as ILogicalConstruct); } } }
/// <summary> /// Gets the path in the tree between two nodes. The <paramref name="ancestorNode"/> /// must be on the path from the root to the <paramref name="descenderNode"/>. /// </summary> /// <param name="ancestorNode"></param> /// <param name="descenderNode"></param> /// <returns></returns> public List<DFSTNode> GetPath(DFSTNode ancestorNode, DFSTNode descenderNode) { List<DFSTNode> path = new List<DFSTNode>(); DFSTNode currentNodeOnPath = descenderNode; while (currentNodeOnPath != null && currentNodeOnPath != ancestorNode) { path.Add(currentNodeOnPath); currentNodeOnPath = (DFSTNode)currentNodeOnPath.Predecessor; } if (currentNodeOnPath != null) { path.Add(currentNodeOnPath); } else { //sanity check throw new Exception("No path between the two nodes."); } path.Reverse(); return path; }
/// <summary> /// Determines whether <paramref name="supposedAncestor"/> is on the tree path from the root to <paramref name="node"/> /// </summary> /// <param name="node"></param> /// <param name="supposedAncestor"></param> /// <returns></returns> private bool IsAncestor(DFSTNode node, DFSTNode supposedAncestor) { DFSTNode currentAncestor = (DFSTNode)node.Predecessor; while (currentAncestor != null) { if (currentAncestor == supposedAncestor) { return true; } currentAncestor = (DFSTNode)currentAncestor.Predecessor; } return false; }
private List<DFSTNode> GetPredecessors(DFSTNode node) { List<DFSTNode> result = new List<DFSTNode>(); if (node.Predecessor != null) { result.Add(node.Predecessor as DFSTNode); } result.AddRange(node.ForwardEdgePredecessors); result.AddRange(node.CrossEdgePredecessors); result.AddRange(node.BackEdgePredecessors); return result; }