private void TraverseAndBuildTree() { this.theTree = new DFSTree(this.constructToNodeMap); this.DFSBuild(this.constructToNodeMap.get_Item(this.entry)); this.theTree.get_ReversePostOrder().Reverse(); this.theTree.get_ReversePostOrder().TrimExcess(); this.AssignOrderIndices(); return; }
/// <summary> /// Builds the tree starting from the graph's entry. /// </summary> private void TraverseAndBuildTree() { theTree = new DFSTree(constructToNodeMap); DFSTNode root = constructToNodeMap[this.entry]; DFSBuild(root); //Since the nodes were added in postorder we must reverse them to get ... the reverse postorder. theTree.ReversePostOrder.Reverse(); theTree.ReversePostOrder.TrimExcess(); AssignOrderIndices(); }
/// <summary> /// Gets the candidates to become conditions of if constructs in postorder. /// </summary> /// <param name="construct"></param> /// <returns></returns> private IEnumerable<ConditionLogicalConstruct> GetPostOrderedIfConditionCandidates(DFSTree dfsTree) { //The post order is so that we start making the if constructs from the innermost nested first (if there is nesting). for (int i = dfsTree.ReversePostOrder.Count - 1; i >= 0; i--) { ConditionLogicalConstruct currentConstruct = dfsTree.ReversePostOrder[i].Construct as ConditionLogicalConstruct; //For candidates we take these conditions that have 2 same parent successors. //TODO: consider taking the conditions with 1 same parent successor. if (currentConstruct != null && currentConstruct.SameParentSuccessors.Count == 2) { yield return currentConstruct; } } }
/// <summary> /// Returns the condition loop exit with the greatest post order index, that has the <paramref name="loopSuccessor"/> as successor. /// </summary> /// <param name="dfsTree"></param> /// <param name="loopBody"></param> /// <param name="loopExits"></param> /// <param name="loopSuccessor"></param> /// <returns></returns> private ConditionLogicalConstruct GetLoopConditionWithMaxIndex(DFSTree dfsTree, HashSet<ILogicalConstruct> loopBody, HashSet<ILogicalConstruct> loopExits, ILogicalConstruct loopSuccessor) { int maxOrderIndexOfExit = -1; foreach (ILogicalConstruct loopExit in loopExits) { int currentOrderIndex = dfsTree.ConstructToNodeMap[loopExit].ReversePostOrderIndex; if (loopExit.SameParentSuccessors.Contains(loopSuccessor) && currentOrderIndex > maxOrderIndexOfExit && CanBeLoopCondition(loopExit, loopBody)) { maxOrderIndexOfExit = currentOrderIndex; } } if(maxOrderIndexOfExit > -1) { return dfsTree.ReversePostOrder[maxOrderIndexOfExit].Construct as ConditionLogicalConstruct; } return null; }
/// <summary> /// Gets a collection of all possible latching nodes for a loop. Builds the body of the loop in the process. /// </summary> /// <param name="tree">The tree in which the loop was found.</param> /// <param name="loopBody">On exit contains the resulted loop body.</param> /// <returns>Returns collection of all possible latching nodes.</returns> private HashSet<ILogicalConstruct> BuildLoop(DFSTree tree, out HashSet<ILogicalConstruct> loopBody) { loopBody = new HashSet<ILogicalConstruct>(); HashSet<ILogicalConstruct> possibleLatchingNodes = new HashSet<ILogicalConstruct>(); /// Loops are defined by their backedges. foreach (DFSTEdge edge in tree.BackEdges) { ILogicalConstruct header = edge.End.Construct as ILogicalConstruct; ILogicalConstruct latchingNode = edge.Start.Construct as ILogicalConstruct; /// The edge between the header and the latching node was marked as goto-edge on an earlier step. if(removedEdges.ContainsKey(latchingNode) && removedEdges[latchingNode].Contains(header)) { continue; } ICollection<DFSTNode> shortLoopBody = tree.GetPath(edge.End, edge.Start); ICollection<DFSTNode> fullLoopBody = ExpandLoopBodyWithCrossEdges(shortLoopBody); ICollection<ILogicalConstruct> fullLoopBodyConstructs = GetConstructsCollection(fullLoopBody); if (CanBeLoop(header, latchingNode, fullLoopBody)) { possibleLatchingNodes.Add(latchingNode); foreach (ILogicalConstruct construct in fullLoopBodyConstructs) { loopBody.Add(construct); } } } return possibleLatchingNodes; }
/// <summary> /// Tries to build an if construct with condition - the specified condition. /// </summary> /// <remarks> /// The idea is to get the dominated nodes of the true successor to create the then block and the dominated nodes of the false successor /// to create the else block. /// If both the then and else blocks have successors, then they must have a common successor to create the if construct. /// </remarks> /// <param name="condition"></param> /// <returns>True on success.</returns> private bool TryBuildIfConstruct(ConditionLogicalConstruct condition, DominatorTree dominatorTree, DFSTree dfsTree) { //Store the true and false successors for optimization. ILogicalConstruct falseSuccessor = condition.FalseSuccessor; ILogicalConstruct trueSuccessor = condition.TrueSuccessor; HashSet<ISingleEntrySubGraph> falseSuccessorFrontier = dominatorTree.GetDominanceFrontier(falseSuccessor); HashSet<ISingleEntrySubGraph> trueSuccessorFrontier = dominatorTree.GetDominanceFrontier(trueSuccessor); ILogicalConstruct exitSuccessor = CheckSuccessor(condition, trueSuccessor, falseSuccessorFrontier, dfsTree) ?? CheckSuccessor(condition, falseSuccessor, trueSuccessorFrontier, dfsTree); HashSet<ISingleEntrySubGraph> frontierIntersection = new HashSet<ISingleEntrySubGraph>(trueSuccessorFrontier); frontierIntersection.IntersectWith(falseSuccessorFrontier); if (exitSuccessor == null && falseSuccessorFrontier.Count > 0 && trueSuccessorFrontier.Count > 0 && frontierIntersection.Count == 0) { //If none of the successors can be a proper exit and the false and true successor frontiers are not empty but have no common node, //then we do not make the if since it will not have a common exit. return false; } HashSet<ILogicalConstruct> thenBody = GetBlockBody(dominatorTree, trueSuccessor, condition); HashSet<ILogicalConstruct> elseBody = GetBlockBody(dominatorTree, falseSuccessor, condition); if (thenBody == null && elseBody == null) { return false; } else if(thenBody == null) { condition.Negate(typeSystem); ILogicalConstruct swapHelper = trueSuccessor; trueSuccessor = falseSuccessor; falseSuccessor = swapHelper; thenBody = elseBody; elseBody = null; } //If the else body is null but the false successor is not a successor of the then body then we do not make the if. if(elseBody == null && !CheckSuccessors(thenBody, falseSuccessor)) { return false; } if (ShouldInvertIfAndRemoveElse(thenBody, trueSuccessor, elseBody, falseSuccessor)) { ///This is performed for cosmetic reasons. condition.Negate(typeSystem); ILogicalConstruct successorSwapHelper = trueSuccessor; trueSuccessor = falseSuccessor; falseSuccessor = successorSwapHelper; HashSet<ILogicalConstruct> swapHelper = thenBody; thenBody = elseBody; elseBody = swapHelper; elseBody = null; } if (elseBody != null && !HasSuccessors(thenBody) && SubtreeEndsInInstructionCode(trueSuccessor.FirstBlock.TheBlock,new Code[]{Code.Ret, Code.Throw})) // check if all ends are throw and/or return -> allow mixed ends as well { // we don't need the else elseBody = null; } BlockLogicalConstruct theThenBlock = new BlockLogicalConstruct(trueSuccessor, thenBody); BlockLogicalConstruct theElseBlock = elseBody != null ? new BlockLogicalConstruct(falseSuccessor, elseBody) : null; IfLogicalConstruct theIfConstruct = IfLogicalConstruct.GroupInIfConstruct(condition, theThenBlock, theElseBlock); UpdateDominatorTree(dominatorTree, theIfConstruct); return true; }
/// <summary> /// Checks if the specified condition successor can be successor of the if construct. /// </summary> /// <param name="condition">The condition.</param> /// <param name="conditionSuccessor">The condition successor.</param> /// <param name="otherSuccessorFrontier">The dominance frontier of the other successor.</param> /// <returns>On success - the successor. Otherwise null.</returns> private ILogicalConstruct CheckSuccessor(ILogicalConstruct condition, ILogicalConstruct conditionSuccessor, HashSet<ISingleEntrySubGraph> otherSuccessorFrontier, DFSTree dfsTree) { //In order the condition successor to be successor of the if, it has to be in the dominance frontier of the other successor. //Also the edge between the condition and the successor should not be backedge or crossedge. DFSTNode successorNode; if(otherSuccessorFrontier.Contains(conditionSuccessor) && (!dfsTree.ConstructToNodeMap.TryGetValue(conditionSuccessor, out successorNode) || dfsTree.ConstructToNodeMap[condition].CompareTo(successorNode) < 0)) { return conditionSuccessor; } return null; }
/// <summary> /// Gets an array containing the tree, forward and cross edges of the given DFS traversal tree. /// </summary> /// <param name="dfsTree">The DFS traversal tree.</param> /// <returns></returns> private DFSTEdge[] GetForwardFlowEdges(DFSTree dfsTree) { DFSTEdge[] regularEdges = new DFSTEdge[dfsTree.TreeEdges.Count + dfsTree.ForwardEdges.Count + dfsTree.CrossEdges.Count]; int index = 0; FillEdgesArray(regularEdges, dfsTree.TreeEdges, ref index); FillEdgesArray(regularEdges, dfsTree.ForwardEdges, ref index); FillEdgesArray(regularEdges, dfsTree.CrossEdges, ref index); return regularEdges; }
/// <summary> /// Builds the adjacency matrix of the subgraph by using the given <paramref name="dfsTree"/>. /// </summary> /// <remarks> /// The back edges are not included in the built subgraph. /// </remarks> /// <param name="dfsTree"></param> private void BuildAdjacencyMatrix(DFSTree dfsTree) { DFSTEdge[] edgeArray = GetForwardFlowEdges(dfsTree); adjacencyMatrix = new int[orderedVertexArray.Length, orderedVertexArray.Length]; foreach (DFSTEdge edge in edgeArray) { int startIndex = edge.Start.ReversePostOrderIndex; int endIndex = edge.End.ReversePostOrderIndex; if(startIndex == endIndex) { continue; } int weight = GetWeight(edge.Start.Construct as ILogicalConstruct, edge.End.Construct as ILogicalConstruct); adjacencyMatrix[startIndex, endIndex] = weight; } }