private bool TryMakeLoop(IntervalConstruct interval, DominatorTree dominatorTree)
 {
     V_0 = DFSTBuilder.BuildTree(interval);
     if (V_0.get_BackEdges().get_Count() == 0)
     {
         return(false);
     }
     V_2 = this.BuildLoop(V_0, out V_1);
     V_4 = this.DetermineLoopType(V_1, V_2, interval, dominatorTree, out V_3);
     if (V_1.get_Count() > 0)
     {
         V_5 = new LoopLogicalConstruct(interval.get_Entry() as ILogicalConstruct, V_1, V_4, V_3, this.typeSystem);
         this.CleanUpEdges(V_5);
         this.UpdateDominatorTree(dominatorTree, V_5);
         return(true);
     }
     V_6 = V_0.get_BackEdges().GetEnumerator();
     try
     {
         while (V_6.MoveNext())
         {
             V_7 = V_6.get_Current();
             this.MarkAsGotoEdge(V_7.get_Start().get_Construct() as ILogicalConstruct, V_7.get_End().get_Construct() as ILogicalConstruct);
         }
     }
     finally
     {
         ((IDisposable)V_6).Dispose();
     }
     return(false);
 }
 private HashSet <ILogicalConstruct> GetIntervalSuccessors(IntervalConstruct interval, ILogicalConstruct startNode)
 {
     V_0 = new HashSet <ILogicalConstruct>();
     if (!interval.get_Children().Contains(startNode))
     {
         return(V_0);
     }
     V_1 = new Queue <ILogicalConstruct>();
     V_1.Enqueue(startNode);
     V_2       = new HashSet <ILogicalConstruct>();
     dummyVar0 = V_2.Add(startNode);
     while (V_1.get_Count() > 0)
     {
         V_3 = V_1.Dequeue().get_SameParentSuccessors().GetEnumerator();
         try
         {
             while (V_3.MoveNext())
             {
                 V_4 = (ILogicalConstruct)V_3.get_Current();
                 if (V_2.Contains(V_4) || !interval.get_Children().Contains(V_4) || !V_0.Add(V_4))
                 {
                     continue;
                 }
                 dummyVar1 = V_2.Add(V_4);
                 V_1.Enqueue(V_4);
             }
         }
         finally
         {
             ((IDisposable)V_3).Dispose();
         }
     }
     return(V_0);
 }
        /// <summary>
        /// Gets the successors (direct or indirect) of the given <paramref name="startNode"/>,
        /// that are in the specified <paramref name="interval"/>.
        /// </summary>
        /// <remarks>
        /// If the start node is not in the interval, then it will not be traversed. This is a corner case for entwined loops.
        /// The start node will not be included in the result, even if it is its own successor.
        /// </remarks>
        /// <returns></returns>
        private HashSet <ILogicalConstruct> GetIntervalSuccessors(IntervalConstruct interval, ILogicalConstruct startNode)
        {
            HashSet <ILogicalConstruct> intervalSuccessors = new HashSet <ILogicalConstruct>();

            if (!interval.Children.Contains(startNode))
            {
                return(intervalSuccessors);
            }

            Queue <ILogicalConstruct> traversalQueue = new Queue <ILogicalConstruct>();

            traversalQueue.Enqueue(startNode);
            HashSet <ILogicalConstruct> traversedNodes = new HashSet <ILogicalConstruct>();

            traversedNodes.Add(startNode);

            while (traversalQueue.Count > 0)
            {
                ILogicalConstruct currentNode = traversalQueue.Dequeue();
                foreach (ILogicalConstruct successor in currentNode.SameParentSuccessors)
                {
                    if (!traversedNodes.Contains(successor) && interval.Children.Contains(successor) && intervalSuccessors.Add(successor))
                    {
                        traversedNodes.Add(successor);
                        traversalQueue.Enqueue(successor);
                    }
                }
            }

            return(intervalSuccessors);
        }
        /// <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);
        }
        /// <summary>
        /// Adds all of the nodes from the <paramref name="interval"/>, that are not preceded by the <paramref name="loopSuccessor"/>,
        /// to the <paramref name="loopBody"/>.
        /// </summary>
        /// <remarks>
        /// Does not add the <paramref name="loopSuccessor"/>.
        /// </remarks>
        private void ExpandLoopBody(IntervalConstruct interval, HashSet <ILogicalConstruct> loopBody, ILogicalConstruct loopSuccessor)
        {
            HashSet <ILogicalConstruct> nodesToSkip = GetIntervalSuccessors(interval, loopSuccessor);

            nodesToSkip.Add(loopSuccessor);

            foreach (LogicalConstructBase node in interval.Children)
            {
                if (!nodesToSkip.Contains(node))
                {
                    loopBody.Add(node);
                }
            }
        }
        private void RemoveBlockingEdges(List <IntervalConstruct> intervals)
        {
            V_0 = new IntervalConstruct(intervals.get_Item(0));
            V_5 = 1;
            while (V_5 < intervals.get_Count())
            {
                dummyVar0 = V_0.get_Children().Add(intervals.get_Item(V_5));
                V_5       = V_5 + 1;
            }
            V_1 = DFSTBuilder.BuildTree(V_0);
            V_2 = V_1.get_BackEdges().FirstOrDefault <DFSTEdge>();
            if (V_2 == null)
            {
                V_2 = V_1.get_CrossEdges().FirstOrDefault <DFSTEdge>();
            }
            V_3 = V_2.get_Start().get_Construct() as IntervalConstruct;
            V_4 = V_2.get_End().get_Construct() as IntervalConstruct;
            V_6 = V_4.get_Entry().get_SameParentPredecessors().GetEnumerator();
            try
            {
                while (V_6.MoveNext())
                {
                    V_7 = (ILogicalConstruct)V_6.get_Current();
                    if (!V_3.get_Children().Contains(V_7))
                    {
                        continue;
                    }
                    V_8 = V_7;
                    V_9 = V_4.get_Entry() as ILogicalConstruct;
                    if (this.removedEdges.TryGetValue(V_8, out V_10) && V_10.Contains(V_9))
                    {
                        continue;
                    }
                    this.MarkAsGotoEdge(V_8, V_9);
                    goto Label0;
                }
            }
            finally
            {
                ((IDisposable)V_6).Dispose();
            }
Label0:
            return;
        }
        /// <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;
                    }
                }
            }
        }
 private void ExpandLoopBody(IntervalConstruct interval, HashSet <ILogicalConstruct> loopBody, ILogicalConstruct loopSuccessor)
 {
     V_0       = this.GetIntervalSuccessors(interval, loopSuccessor);
     dummyVar0 = V_0.Add(loopSuccessor);
     V_1       = interval.get_Children().GetEnumerator();
     try
     {
         while (V_1.MoveNext())
         {
             V_2 = (LogicalConstructBase)V_1.get_Current();
             if (V_0.Contains(V_2))
             {
                 continue;
             }
             dummyVar1 = loopBody.Add(V_2);
         }
     }
     finally
     {
         ((IDisposable)V_1).Dispose();
     }
     return;
 }
        /// <summary>
        /// Gets the successors (direct or indirect) of the given <paramref name="startNode"/>,
        /// that are in the specified <paramref name="interval"/>.
        /// </summary>
        /// <remarks>
        /// If the start node is not in the interval, then it will not be traversed. This is a corner case for entwined loops.
        /// The start node will not be included in the result, even if it is its own successor.
        /// </remarks>
        /// <returns></returns>
        private HashSet<ILogicalConstruct> GetIntervalSuccessors(IntervalConstruct interval, ILogicalConstruct startNode)
        {
            HashSet<ILogicalConstruct> intervalSuccessors = new HashSet<ILogicalConstruct>();
            if (!interval.Children.Contains(startNode))
            {
                return intervalSuccessors;
            }

            Queue<ILogicalConstruct> traversalQueue = new Queue<ILogicalConstruct>();
            traversalQueue.Enqueue(startNode);
            HashSet<ILogicalConstruct> traversedNodes = new HashSet<ILogicalConstruct>();
            traversedNodes.Add(startNode);

            while(traversalQueue.Count > 0)
            {
                ILogicalConstruct currentNode = traversalQueue.Dequeue();
                foreach (ILogicalConstruct successor in currentNode.SameParentSuccessors)
                {
                    if(!traversedNodes.Contains(successor) && interval.Children.Contains(successor) && intervalSuccessors.Add(successor))
                    {
                        traversedNodes.Add(successor);
                        traversalQueue.Enqueue(successor);
                    }
                }
            }

            return intervalSuccessors;
        }
        /// <summary>
        /// Adds all of the nodes from the <paramref name="interval"/>, that are not preceded by the <paramref name="loopSuccessor"/>,
        /// to the <paramref name="loopBody"/>.
        /// </summary>
        /// <remarks>
        /// Does not add the <paramref name="loopSuccessor"/>.
        /// </remarks>
        private void ExpandLoopBody(IntervalConstruct interval, HashSet<ILogicalConstruct> loopBody, ILogicalConstruct loopSuccessor)
        {
            HashSet<ILogicalConstruct> nodesToSkip = GetIntervalSuccessors(interval, loopSuccessor);
            nodesToSkip.Add(loopSuccessor);

            foreach (LogicalConstructBase node in interval.Children)
            {
                if (!nodesToSkip.Contains(node))
                {
                    loopBody.Add(node);
                }
            }
        }
        /// <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>
	    /// 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;
		}
        /// <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;
                    }
                }
            }
		}
        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);
        }
        /// <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);
                }
            }
        }