/// <summary> /// Analyzes <paramref name="interval"/> and makes a loop from it, if possible. /// </summary> /// <param name="interval">The interval to be analyzed.</param> /// <returns>Returns true if a loop was made.</returns> private bool TryMakeLoop(IntervalConstruct interval, DominatorTree dominatorTree) { DFSTree dfsTree = DFSTBuilder.BuildTree(interval); if (dfsTree.BackEdges.Count == 0) { /// No back edges in the interval, so no loop can be made. return(false); } HashSet <ILogicalConstruct> loopBody; HashSet <ILogicalConstruct> possibleLatchingNodes = BuildLoop(dfsTree, out loopBody); ConditionLogicalConstruct loopCondition; LoopType typeOfLoop = DetermineLoopType(loopBody, possibleLatchingNodes, interval, dominatorTree, out loopCondition); if (loopBody.Count > 0) { LoopLogicalConstruct loop = new LoopLogicalConstruct(interval.Entry as ILogicalConstruct, loopBody, typeOfLoop, loopCondition, typeSystem); CleanUpEdges(loop); /// Covers the case in IrregularbackedgeExitLoop UpdateDominatorTree(dominatorTree, loop); return(true); } else { /// Empty loops should not be created. Instead, backedges that form such loops will be marked as goto. foreach (DFSTEdge backedge in dfsTree.BackEdges) { MarkAsGotoEdge(backedge.Start.Construct as ILogicalConstruct, backedge.End.Construct as ILogicalConstruct); } } return(false); }
private ConditionLogicalConstruct GetLoopConditionWithMaxIndex(DFSTree dfsTree, HashSet <ILogicalConstruct> loopBody, HashSet <ILogicalConstruct> loopExits, ILogicalConstruct loopSuccessor) { V_0 = -1; V_1 = loopExits.GetEnumerator(); try { while (V_1.MoveNext()) { V_2 = V_1.get_Current(); V_3 = dfsTree.get_ConstructToNodeMap().get_Item(V_2).get_ReversePostOrderIndex(); if (!V_2.get_SameParentSuccessors().Contains(loopSuccessor) || V_3 <= V_0 || !this.CanBeLoopCondition(V_2, loopBody)) { continue; } V_0 = V_3; } } finally { ((IDisposable)V_1).Dispose(); } if (V_0 <= -1) { return(null); } return(dfsTree.get_ReversePostOrder().get_Item(V_0).get_Construct() as ConditionLogicalConstruct); }
/// <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); }
private DFSTEdge[] GetForwardFlowEdges(DFSTree dfsTree) { V_0 = new DFSTEdge[dfsTree.get_TreeEdges().get_Count() + dfsTree.get_ForwardEdges().get_Count() + dfsTree.get_CrossEdges().get_Count()]; V_1 = 0; this.FillEdgesArray(V_0, dfsTree.get_TreeEdges(), ref V_1); this.FillEdgesArray(V_0, dfsTree.get_ForwardEdges(), ref V_1); this.FillEdgesArray(V_0, dfsTree.get_CrossEdges(), ref V_1); return(V_0); }
/// <summary> /// Builds if constructs in the specified construct. /// </summary> /// <param name="construct"></param> private void BuildIfConstructs(ILogicalConstruct construct) { DominatorTree dominatorTree = GetDominatorTreeFromContext(construct); DFSTree dfsTree = DFSTBuilder.BuildTree(construct); foreach (ConditionLogicalConstruct condition in GetPostOrderedIfConditionCandidates(dfsTree)) { TryBuildIfConstruct(condition, dominatorTree, dfsTree); } }
private void ProcessSwitchConstructs(ILogicalConstruct parent, List <CFGBlockLogicalConstruct> switchBlocks) { DominatorTree dominatorTree = GetDominatorTreeFromContext(parent); DFSTree dfsTree = DFSTBuilder.BuildTree(parent); switchBlocks.Sort((x, y) => dfsTree.ConstructToNodeMap[y].ReversePostOrderIndex.CompareTo(dfsTree.ConstructToNodeMap[x].ReversePostOrderIndex)); foreach (CFGBlockLogicalConstruct switchBlock in switchBlocks) { CreateSwitchConstruct(switchBlock, parent, this.logicalContext.CFG.SwitchBlocksInformation[switchBlock.TheBlock], dominatorTree); } }
/// <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> /// Creates a subgraph of the specified <paramref name="graph"/>. /// </summary> /// <remarks> /// The subgraph has the same vertices as the original. The difference is that the subgraph does not contain the back edges /// found by the dfs traversal of the <paramref name="graph"/>. /// </remarks> /// <param name="graph"></param> private void GetVerticesAndAdjacencyMatrix(ILogicalConstruct graph) { DFSTree dfsTree = DFSTBuilder.BuildTree(graph); orderedVertexArray = new ILogicalConstruct[dfsTree.ReversePostOrder.Count]; for (int i = 0; i < orderedVertexArray.Length; i++) { orderedVertexArray[i] = dfsTree.ReversePostOrder[i].Construct as ILogicalConstruct; } BuildAdjacencyMatrix(dfsTree); }
/// <summary> /// Gets the CFGBlockLC children of theBlock sorted in reverse post order. /// </summary> private void GetOrderedCFGNodes() { DFSTree dfsTree = DFSTBuilder.BuildTree(theBlock); foreach (DFSTNode node in dfsTree.ReversePostOrder) { CFGBlockLogicalConstruct cfgConstruct = node.Construct as CFGBlockLogicalConstruct; if (cfgConstruct != null) { orderedCFGNodes.Add(cfgConstruct); } } }
private HashSet <ILogicalConstruct> BuildLoop(DFSTree tree, out HashSet <ILogicalConstruct> loopBody) { loopBody = new HashSet <ILogicalConstruct>(); V_0 = new HashSet <ILogicalConstruct>(); V_1 = tree.get_BackEdges().GetEnumerator(); try { while (V_1.MoveNext()) { V_2 = V_1.get_Current(); V_3 = V_2.get_End().get_Construct() as ILogicalConstruct; V_4 = V_2.get_Start().get_Construct() as ILogicalConstruct; if (this.removedEdges.ContainsKey(V_4) && this.removedEdges.get_Item(V_4).Contains(V_3)) { continue; } V_5 = tree.GetPath(V_2.get_End(), V_2.get_Start()); V_6 = this.ExpandLoopBodyWithCrossEdges(V_5); V_7 = this.GetConstructsCollection(V_6); if (!this.CanBeLoop(V_3, V_4, V_6)) { continue; } dummyVar0 = V_0.Add(V_4); V_8 = V_7.GetEnumerator(); try { while (V_8.MoveNext()) { V_9 = V_8.get_Current(); dummyVar1 = loopBody.Add(V_9); } } finally { if (V_8 != null) { V_8.Dispose(); } } } } finally { ((IDisposable)V_1).Dispose(); } return(V_0); }
/// <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; } }
/// <summary> /// Sorts the intervals in Reverse post order. /// </summary> /// <param name="intervals">The intervals to be sorted.</param> /// <returns>Returns sorted list of intervals.</returns> private List <IntervalConstruct> SortIntervalList(List <IntervalConstruct> intervals) { IntervalConstruct intervalGraph = new IntervalConstruct(intervals[0]); foreach (ISingleEntrySubGraph interval in intervals) { intervalGraph.Children.Add(interval); } DFSTree dfsTree = DFSTBuilder.BuildTree(intervalGraph); List <IntervalConstruct> sortedList = new List <IntervalConstruct>(); foreach (DFSTNode node in dfsTree.ReversePostOrder) { sortedList.Add(node.Construct as IntervalConstruct); } return(sortedList); }
/// <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> /// Removes and edge, that is preventing the reducibillity of the graph. /// </summary> /// <param name="intervals">The graph, that can't be reduced.</param> private void RemoveBlockingEdges(List <IntervalConstruct> intervals) { //Creating this interval, so that it holds the interval tree //This way we can use the DFSTree. IntervalConstruct allIntervals = new IntervalConstruct(intervals[0]); for (int i = 1; i < intervals.Count; i++) { allIntervals.Children.Add(intervals[i]); } DFSTree dfsTree = DFSTBuilder.BuildTree(allIntervals); /// Blocking edge can be either cross edge or back edge. /// If a backedge is detected, that means it wasn't converted in loop, so it must be marked as goto. DFSTEdge edgeToDelete = dfsTree.BackEdges.FirstOrDefault(); if (edgeToDelete == null) { edgeToDelete = dfsTree.CrossEdges.FirstOrDefault(); } //both should not be null, since the DFS was ran onto intervals tree IntervalConstruct edgeStart = edgeToDelete.Start.Construct as IntervalConstruct; IntervalConstruct edgeEnd = edgeToDelete.End.Construct as IntervalConstruct; //Find all logical constructs that make the intervals have this edge between them. foreach (ILogicalConstruct edgeEndPredecessor in edgeEnd.Entry.SameParentPredecessors) { if (edgeStart.Children.Contains(edgeEndPredecessor)) { ILogicalConstruct constructEdgeStart = edgeEndPredecessor; ILogicalConstruct constructEdgeEnd = edgeEnd.Entry as ILogicalConstruct; HashSet <ILogicalConstruct> removedEdgeInfo; if (!removedEdges.TryGetValue(constructEdgeStart, out removedEdgeInfo) || !removedEdgeInfo.Contains(constructEdgeEnd)) { MarkAsGotoEdge(constructEdgeStart, constructEdgeEnd); return; } } } }
/// <summary> /// Removes back edges from switch blocks. Switch cases can not form a loop. If the control flow forms a loop, it should be represented by goto-label contructs. /// </summary> /// <param name="theConstruct">The construct, that might contain switches.</param> private void RemoveBackEdgesFromSwitchConstructs(ILogicalConstruct theConstruct) { DFSTree dfsTree = DFSTBuilder.BuildTree(theConstruct); foreach (DFSTEdge edge in dfsTree.BackEdges) { ILogicalConstruct startConstruct = edge.Start.Construct as ILogicalConstruct; if (startConstruct is ConditionLogicalConstruct) { continue; } CFGBlockLogicalConstruct startCfgConstruct = startConstruct as CFGBlockLogicalConstruct; if ((startCfgConstruct != null && startCfgConstruct.TheBlock.Last.OpCode.Code == Mono.Cecil.Cil.Code.Switch)) { MarkAsGotoEdge(startConstruct, edge.End.Construct as ILogicalConstruct); } } }
private void BuildAdjacencyMatrix(DFSTree dfsTree) { stackVariable2 = this.GetForwardFlowEdges(dfsTree); this.adjacencyMatrix = new int[(int)this.orderedVertexArray.Length, (int)this.orderedVertexArray.Length]; V_0 = stackVariable2; V_1 = 0; while (V_1 < (int)V_0.Length) { V_2 = V_0[V_1]; V_3 = V_2.get_Start().get_ReversePostOrderIndex(); V_4 = V_2.get_End().get_ReversePostOrderIndex(); if (V_3 != V_4) { V_5 = this.GetWeight(V_2.get_Start().get_Construct() as ILogicalConstruct, V_2.get_End().get_Construct() as ILogicalConstruct); this.adjacencyMatrix[V_3, V_4] = V_5; } V_1 = V_1 + 1; } return; }
/// <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); }
private Dictionary <ILogicalConstruct, HashSet <ISingleEntrySubGraph> > GetValidCases(DominatorTree dominatorTree, ILogicalConstruct switchCFGBlock) { Dictionary <ILogicalConstruct, HashSet <ISingleEntrySubGraph> > caseEntriesToDominatedNodesMap = new Dictionary <ILogicalConstruct, HashSet <ISingleEntrySubGraph> >(); HashSet <ISingleEntrySubGraph> legalPredecessors = new HashSet <ISingleEntrySubGraph>(); legalPredecessors.Add(switchCFGBlock); foreach (ILogicalConstruct successor in switchCFGBlock.SameParentSuccessors) { if (successor != switchCFGBlock && dominatorTree.GetImmediateDominator(successor) == switchCFGBlock) { HashSet <ISingleEntrySubGraph> dominatedNodes = dominatorTree.GetDominatedNodes(successor); caseEntriesToDominatedNodesMap.Add(successor, dominatedNodes); legalPredecessors.UnionWith(dominatedNodes); } } DFSTree dfsTree = DFSTBuilder.BuildTree(switchCFGBlock.Parent, switchCFGBlock); List <ILogicalConstruct> orderedCaseEntries = new List <ILogicalConstruct>(dfsTree.ReversePostOrder.Select(node => node.Construct as ILogicalConstruct).Where(construct => caseEntriesToDominatedNodesMap.ContainsKey(construct))); bool changed; do { changed = false; foreach (ILogicalConstruct caseEntry in orderedCaseEntries) { HashSet <ISingleEntrySubGraph> dominatedNodes; if (caseEntriesToDominatedNodesMap.TryGetValue(caseEntry, out dominatedNodes) && !IsCaseValid(caseEntry, legalPredecessors)) { legalPredecessors.ExceptWith(dominatedNodes); caseEntriesToDominatedNodesMap.Remove(caseEntry); changed = true; } } } while (changed); return(caseEntriesToDominatedNodesMap); }
private IEnumerable <ConditionLogicalConstruct> GetPostOrderedIfConditionCandidates(DFSTree dfsTree) { stackVariable1 = new IfBuilder.u003cGetPostOrderedIfConditionCandidatesu003ed__5(-2); stackVariable1.u003cu003e3__dfsTree = dfsTree; return(stackVariable1); }
private ILogicalConstruct CheckSuccessor(ILogicalConstruct condition, ILogicalConstruct conditionSuccessor, HashSet <ISingleEntrySubGraph> otherSuccessorFrontier, DFSTree dfsTree) { if (otherSuccessorFrontier.Contains(conditionSuccessor) && !dfsTree.get_ConstructToNodeMap().TryGetValue(conditionSuccessor, out V_0) || dfsTree.get_ConstructToNodeMap().get_Item(condition).CompareTo(V_0) < 0) { return(conditionSuccessor); } return(null); }
/// <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); }
private bool TryBuildIfConstruct(ConditionLogicalConstruct condition, DominatorTree dominatorTree, DFSTree dfsTree) { V_0 = condition.get_FalseSuccessor(); V_1 = condition.get_TrueSuccessor(); V_2 = dominatorTree.GetDominanceFrontier(V_0); V_3 = dominatorTree.GetDominanceFrontier(V_1); stackVariable15 = this.CheckSuccessor(condition, V_1, V_2, dfsTree); if (stackVariable15 == null) { dummyVar0 = stackVariable15; stackVariable15 = this.CheckSuccessor(condition, V_0, V_3, dfsTree); } V_4 = new HashSet <ISingleEntrySubGraph>(V_3); V_4.IntersectWith(V_2); if (stackVariable15 == null && V_2.get_Count() > 0 && V_3.get_Count() > 0 && V_4.get_Count() == 0) { return(false); } V_5 = this.GetBlockBody(dominatorTree, V_1, condition); V_6 = this.GetBlockBody(dominatorTree, V_0, condition); if (V_5 == null && V_6 == null) { return(false); } if (V_5 == null) { condition.Negate(this.typeSystem); stackVariable86 = V_1; V_1 = V_0; V_0 = stackVariable86; V_5 = V_6; V_6 = null; } if (V_6 == null && !this.CheckSuccessors(V_5, V_0)) { return(false); } if (this.ShouldInvertIfAndRemoveElse(V_5, V_1, V_6, V_0)) { condition.Negate(this.typeSystem); stackVariable73 = V_1; V_1 = V_0; V_0 = stackVariable73; stackVariable75 = V_5; V_5 = V_6; V_6 = stackVariable75; V_6 = null; } if (V_6 != null && !this.HasSuccessors(V_5)) { stackVariable61 = V_1.get_FirstBlock().get_TheBlock(); stackVariable63 = new Code[2]; stackVariable63[0] = 41; stackVariable63[1] = 119; if (this.SubtreeEndsInInstructionCode(stackVariable61, stackVariable63)) { V_6 = null; } } V_7 = new BlockLogicalConstruct(V_1, V_5); if (V_6 != null) { stackVariable46 = new BlockLogicalConstruct(V_0, V_6); } else { stackVariable46 = null; } this.UpdateDominatorTree(dominatorTree, IfLogicalConstruct.GroupInIfConstruct(condition, V_7, stackVariable46)); return(true); }
/// <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> /// Determines the type of the loop and the condition of the loop. Adds additional nodes into the loop body. /// </summary> /// <param name="loopBody"></param> /// <param name="header"></param> /// <param name="latchingNodes"></param> /// <param name="interval"></param> /// <param name="loopCondition"></param> /// <returns></returns> private LoopType DetermineLoopType(HashSet <ILogicalConstruct> loopBody, HashSet <ILogicalConstruct> latchingNodes, IntervalConstruct interval, DominatorTree dominatorTree, out ConditionLogicalConstruct loopCondition) { ILogicalConstruct header = interval.Entry as ILogicalConstruct; HashSet <ILogicalConstruct> legalExits = new HashSet <ILogicalConstruct>(latchingNodes); legalExits.Add(header); ILogicalConstruct parentConstruct = header.Parent as ILogicalConstruct; DFSTree dfsTree = DFSTBuilder.BuildTree(parentConstruct); //B - nodes in the loop body (= loopBody) //I - nodes in the interval (= interval.Children) //U - union of all of the dominance frontiers of the nodes in B //exitDominanceFrontier = (U n I) \ B //If a node is in the exitDominanceFrontier, then it is dominated by the header and is a successor (not necessarily direct) of more than one //node in the loop body. HashSet <ILogicalConstruct> exitDominanceFrontier = new HashSet <ILogicalConstruct>(); foreach (ILogicalConstruct loopNode in loopBody) { foreach (ILogicalConstruct frontierNode in dominatorTree.GetDominanceFrontier(loopNode)) { if (interval.Children.Contains(frontierNode) && !loopBody.Contains(frontierNode)) { exitDominanceFrontier.Add(frontierNode); } } } //This is leftover heuristic, that was used for determining a suitable successor that is going to be follow node of the loop. //Changing it now will break a good number of the tests. Since the produced output is acceptable, until a better heuristic is found //there is no need to change it. if (exitDominanceFrontier.Count == 0) { //If the exit dominance frontier is empty then we look for the node, with minimum post order index, that is a successor of a condition loop exit. //The desired exit should be a condition in order to reduce the number of infinite loops (heuristic). foreach (DFSTNode dfsNode in dfsTree.ReversePostOrder) { ILogicalConstruct construct = dfsNode.Construct as ILogicalConstruct; if (loopBody.Contains(construct)) { continue; } loopCondition = GetLoopConditionWithMaxIndex(dfsTree, loopBody, legalExits, construct); //By taking the successor with the minimum post order index and the loop exit with the maximum post order index, we ensure that //the produced construct will always be the same, since the post order in our case is a total order. //There are other various ways of finding the exit-successor pair that can bring consistent output, but none of them is found to yield //better results than the rest. if (loopCondition != null) { //We expand the loop body only when we've found a condition successor of the loop. //This is done in order to avoid adding all of the dominated nodes of an infinite loop to the body. (Better readability of the final code.) //E.g.: An infinite loop on the top level of the logical tree (i.e. child of the method block construct). If it dominates all of its //succeeding nodes then they will be in its interval, which means that they will be added to the loop. As a result there will //be an infinite loop at the end of the method, that encloses a cood part of the code, for no apparent reason. ExpandLoopBody(interval, loopBody, construct); if (loopCondition == header) { return(LoopType.PreTestedLoop); } else { return(LoopType.PostTestedLoop); } } } if (CanBeLoopCondition(header, loopBody)) { loopCondition = header as ConditionLogicalConstruct; return(LoopType.PreTestedLoop); } else { loopCondition = null; return(LoopType.InfiniteLoop); } } else { //If there are nodes in the exitDominanceFrontier, then we choose the one with the minimum postorder index for successor of the loop. //Then we try to find a condition exit of the loop, with maximum post order index, that is predecessor of the successor node. int minOrderIndexOfSuccessor = dfsTree.ReversePostOrder.Count; foreach (ILogicalConstruct successor in exitDominanceFrontier) { int currentOrderIndex = dfsTree.ConstructToNodeMap[successor].ReversePostOrderIndex; if (currentOrderIndex < minOrderIndexOfSuccessor) { minOrderIndexOfSuccessor = currentOrderIndex; } } ILogicalConstruct loopSuccessor = dfsTree.ReversePostOrder[minOrderIndexOfSuccessor].Construct as ILogicalConstruct; loopCondition = GetLoopConditionWithMaxIndex(dfsTree, loopBody, legalExits, loopSuccessor); ExpandLoopBody(interval, loopBody, loopSuccessor); if (loopCondition != null) { if (loopCondition == header) { return(LoopType.PreTestedLoop); } else { return(LoopType.PostTestedLoop); } } else { return(LoopType.InfiniteLoop); } } }
/// <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); }