/* * Test Building Full Dominator Tree */ private static void TestCalculatingDominanceFrontier(int index, SortedSet <int> expected) { // Build Dominator Tree IRGraph cfg = BuildSampleCFG(); DominatorTree dominatorTree = new DominatorTree(cfg); SortedSet <IRBlock> result = dominatorTree.GetDominanceFrontier(cfg.GetBlock(index)); SortedSet <int> intResult = ConvertToIndexSet(result); if (!intResult.SetEquals(expected)) { throw new Exception("Dominance frontier for block " + index + " is " + ConvertSetToString(intResult) + " should be " + ConvertSetToString(expected)); } }
private LoopType DetermineLoopType(HashSet <ILogicalConstruct> loopBody, HashSet <ILogicalConstruct> latchingNodes, IntervalConstruct interval, DominatorTree dominatorTree, out ConditionLogicalConstruct loopCondition) { V_0 = interval.get_Entry() as ILogicalConstruct; V_1 = new HashSet <ILogicalConstruct>(latchingNodes); dummyVar0 = V_1.Add(V_0); V_2 = DFSTBuilder.BuildTree(V_0.get_Parent() as ILogicalConstruct); V_3 = new HashSet <ILogicalConstruct>(); V_4 = loopBody.GetEnumerator(); try { while (V_4.MoveNext()) { V_5 = V_4.get_Current(); V_6 = dominatorTree.GetDominanceFrontier(V_5).GetEnumerator(); try { while (V_6.MoveNext()) { V_7 = (ILogicalConstruct)V_6.get_Current(); if (!interval.get_Children().Contains(V_7) || loopBody.Contains(V_7)) { continue; } dummyVar1 = V_3.Add(V_7); } } finally { ((IDisposable)V_6).Dispose(); } } } finally { ((IDisposable)V_4).Dispose(); } if (V_3.get_Count() == 0) { V_8 = V_2.get_ReversePostOrder().GetEnumerator(); try { while (V_8.MoveNext()) { V_9 = V_8.get_Current().get_Construct() as ILogicalConstruct; if (loopBody.Contains(V_9)) { continue; } loopCondition = this.GetLoopConditionWithMaxIndex(V_2, loopBody, V_1, V_9); if (loopCondition == null) { continue; } this.ExpandLoopBody(interval, loopBody, V_9); if (loopCondition != V_0) { V_10 = 2; goto Label1; } else { V_10 = 1; goto Label1; } } goto Label0; } finally { ((IDisposable)V_8).Dispose(); } Label1: return(V_10); } V_11 = V_2.get_ReversePostOrder().get_Count(); V_4 = V_3.GetEnumerator(); try { while (V_4.MoveNext()) { V_13 = V_4.get_Current(); V_14 = V_2.get_ConstructToNodeMap().get_Item(V_13).get_ReversePostOrderIndex(); if (V_14 >= V_11) { continue; } V_11 = V_14; } } finally { ((IDisposable)V_4).Dispose(); } V_12 = V_2.get_ReversePostOrder().get_Item(V_11).get_Construct() as ILogicalConstruct; loopCondition = this.GetLoopConditionWithMaxIndex(V_2, loopBody, V_1, V_12); this.ExpandLoopBody(interval, loopBody, V_12); if (loopCondition == null) { return(0); } if (loopCondition == V_0) { return(1); } return(2); Label0: if (!this.CanBeLoopCondition(V_0, loopBody)) { loopCondition = null; return(0); } loopCondition = V_0 as ConditionLogicalConstruct; return(1); }
private static void InsertPhiFunctions(IRGraph graph, DominatorTree dominatorTree) { foreach (IRBlock block in graph.GetSetOfAllBlocks()) { Console.WriteLine(); Console.WriteLine("***"); Console.WriteLine("Block: " + block.GetIndex()); block.PrintStatements(); Console.Write("Predecessors: "); foreach (IRBlock pred in graph.GetPredecessors(block)) { Console.Write(pred.GetIndex() + ", "); } Console.WriteLine(); Console.Write("Live in : "); foreach (Ident ident in block.GetLiveIn()) { Console.Write(ident + ", "); } Console.WriteLine(); Console.Write("Defined vars: "); foreach (Ident ident in block.GetDefinedVars()) { Console.Write(ident + ", "); } Console.WriteLine(); } foreach (Ident v in graph.GetDefinedVars()) { // A(v) = blocks containing an assignment to v HashSet <IRBlock> Av = new HashSet <IRBlock>(); foreach (IRBlock block in graph.GetSetOfAllBlocks()) { if (block.GetDefinedVars().Contains(v) && block.GetLiveIn().Contains(v)) { Av.Add(block); } } // place Phi tuple for each v in the iterated dominance frontier of A(v) HashSet <IRBlock> needsPhiFunction = new HashSet <IRBlock>(); foreach (IRBlock Avblock in Av) { // create set of blocks that need phi functions foreach (IRBlock block in dominatorTree.GetDominanceFrontier(Avblock)) { needsPhiFunction.Add(block); } } // only want one phi function per block for each variable where appropiate foreach (IRBlock block in needsPhiFunction) { // Phi function should have as many arguments as it does predecessors List <Ident> sources = new List <Ident>(); foreach (IRBlock b in graph.GetPredecessors(block)) { sources.Add(v); } IRTupleManyOp phi = new IRTupleManyOp(IrOp.PHI, v, sources); block.InsertStatement(phi, 0); Console.WriteLine("** SSA: Inserting phi function: " + phi.toString() + " into block " + block.GetIndex()); } } }
/// <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); } } }
private static void InsertPhiFunctions(IRGraph graph, DominatorTree dominatorTree) { foreach (IRBlock block in graph.GetSetOfAllBlocks()) { Console.WriteLine(); Console.WriteLine("***"); Console.WriteLine("Block: " + block.GetIndex()); block.PrintStatements(); Console.Write("Predecessors: "); foreach (IRBlock pred in graph.GetPredecessors(block)) Console.Write(pred.GetIndex() + ", "); Console.WriteLine(); Console.Write("Live in : "); foreach (Ident ident in block.GetLiveIn()) Console.Write(ident + ", "); Console.WriteLine(); Console.Write("Defined vars: "); foreach (Ident ident in block.GetDefinedVars()) Console.Write(ident + ", "); Console.WriteLine(); } foreach (Ident v in graph.GetDefinedVars()) { // A(v) = blocks containing an assignment to v HashSet<IRBlock> Av = new HashSet<IRBlock>(); foreach (IRBlock block in graph.GetSetOfAllBlocks()) { if (block.GetDefinedVars().Contains(v) && block.GetLiveIn().Contains(v)) Av.Add(block); } // place Phi tuple for each v in the iterated dominance frontier of A(v) HashSet<IRBlock> needsPhiFunction = new HashSet<IRBlock>(); foreach (IRBlock Avblock in Av) { // create set of blocks that need phi functions foreach (IRBlock block in dominatorTree.GetDominanceFrontier(Avblock)) { needsPhiFunction.Add(block); } } // only want one phi function per block for each variable where appropiate foreach (IRBlock block in needsPhiFunction) { // Phi function should have as many arguments as it does predecessors List<Ident> sources = new List<Ident>(); foreach (IRBlock b in graph.GetPredecessors(block)) sources.Add(v); IRTupleManyOp phi = new IRTupleManyOp(IrOp.PHI, v, sources); block.InsertStatement(phi, 0); Console.WriteLine("** SSA: Inserting phi function: " + phi.toString() + " into block " + block.GetIndex()); } } }
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); }
/* * Test Building Full Dominator Tree */ private static void TestCalculatingDominanceFrontier(int index, SortedSet<int> expected) { // Build Dominator Tree IRGraph cfg = BuildSampleCFG(); DominatorTree dominatorTree = new DominatorTree(cfg); SortedSet<IRBlock> result = dominatorTree.GetDominanceFrontier(cfg.GetBlock(index)); SortedSet<int> intResult = ConvertToIndexSet(result); if(!intResult.SetEquals(expected)) { throw new Exception("Dominance frontier for block " + index + " is " + ConvertSetToString(intResult) + " should be " + ConvertSetToString(expected)); } }
/// <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); }