private void CreateSwitchConstruct(CFGBlockLogicalConstruct switchBlock, ILogicalConstruct parentConstruct,
            SwitchData switchData, DominatorTree dominatorTree)
        {
            List<KeyValuePair<CFGBlockLogicalConstruct, List<int>>> cfgSuccessorToLabelsMap = GetOrderedCFGSuccessorToLabelsMap(switchData);
            Dictionary<ILogicalConstruct, HashSet<ISingleEntrySubGraph>> validCaseEntryToDominatedNodesMap = GetValidCases(dominatorTree, switchBlock);

            List<CaseLogicalConstruct> orderedCaseConstructs = new List<CaseLogicalConstruct>();
            PairList<List<int>, CFGBlockLogicalConstruct> labelsToCFGSuccessorsList = new PairList<List<int>, CFGBlockLogicalConstruct>();
            foreach (KeyValuePair<CFGBlockLogicalConstruct, List<int>> cfgSuccessorToLabelsPair in cfgSuccessorToLabelsMap)
            {
                ILogicalConstruct successor;
                HashSet<ISingleEntrySubGraph> dominatedNodes;
                if (LogicalFlowUtilities.TryGetParentConstructWithGivenParent(cfgSuccessorToLabelsPair.Key, parentConstruct, out successor) &&
                    validCaseEntryToDominatedNodesMap.TryGetValue(successor, out dominatedNodes))
                {
                    CaseLogicalConstruct newCaseConstruct = new CaseLogicalConstruct(successor);
                    newCaseConstruct.CaseNumbers.AddRange(cfgSuccessorToLabelsPair.Value);
                    newCaseConstruct.Body.UnionWith(dominatedNodes.Cast<ILogicalConstruct>());
                    newCaseConstruct.AttachCaseConstructToGraph();
                    orderedCaseConstructs.Add(newCaseConstruct);
                }
                else
                {
                    labelsToCFGSuccessorsList.Add(cfgSuccessorToLabelsPair.Value, cfgSuccessorToLabelsPair.Key);
                }
            }

            CaseLogicalConstruct defaultCase = null;
            CFGBlockLogicalConstruct defaultCFGSuccessor = GetCFGLogicalConstructFromBlock(switchData.DefaultCase);
            ILogicalConstruct defaultSuccessor;
            HashSet<ISingleEntrySubGraph> defaultCaseNodes;
            if (LogicalFlowUtilities.TryGetParentConstructWithGivenParent(defaultCFGSuccessor, parentConstruct, out defaultSuccessor) &&
                    validCaseEntryToDominatedNodesMap.TryGetValue(defaultSuccessor, out defaultCaseNodes))
            {
                defaultCase = new CaseLogicalConstruct(defaultSuccessor);
                if (HasSuccessors(defaultCaseNodes))
                {
                    defaultCase.Body.UnionWith(defaultCaseNodes.Cast<ILogicalConstruct>());
                }
                defaultCase.AttachCaseConstructToGraph();
            }

            SwitchLogicalConstruct theSwitch = SwitchLogicalConstruct.GroupInSwitchConstruct(switchBlock, orderedCaseConstructs, labelsToCFGSuccessorsList, defaultCase, defaultCFGSuccessor);
            UpdateDominatorTree(dominatorTree, theSwitch);
        }
        private void UpdateDominatorTree(DominatorTree dominatorTree, LoopLogicalConstruct theLoopConstruct)
        {
            HashSet<ISingleEntrySubGraph> loopNodes = new HashSet<ISingleEntrySubGraph>();
            if (theLoopConstruct.LoopCondition != null)
            {
                loopNodes.Add(theLoopConstruct.LoopCondition);
            }
            if (theLoopConstruct.LoopBodyBlock != null)
            {
                loopNodes.UnionWith(theLoopConstruct.LoopBodyBlock.Children);
            }

            ISingleEntrySubGraph loopEntry = (theLoopConstruct.LoopType == LoopType.PreTestedLoop) ? theLoopConstruct.LoopCondition : theLoopConstruct.LoopBodyBlock.Entry;
            dominatorTree.MergeNodes(loopNodes, loopEntry, theLoopConstruct);
        }
        /// <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>
        /// 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 void UpdateDominatorTree(DominatorTree dominatorTree, IfLogicalConstruct theIfConstruct)
        {
            HashSet<ISingleEntrySubGraph> ifNodes = new HashSet<ISingleEntrySubGraph>();
            ifNodes.Add(theIfConstruct.Condition);
            ifNodes.UnionWith(theIfConstruct.Then.Children);
            if (theIfConstruct.Else != null)
            {
                ifNodes.UnionWith(theIfConstruct.Else.Children);
            }

            dominatorTree.MergeNodes(ifNodes, theIfConstruct.Condition, theIfConstruct);
        }
        /// <summary>
        /// Gets the dominated nodes of the condition successor, only if they can form a legal block for the if construct.
        /// </summary>
        /// <param name="dominatorTree"></param>
        /// <param name="conditionSuccessor"></param>
        /// <returns>On success - a set of the nodes fo the block. Otherwise it returns null.</returns>
        private HashSet<ILogicalConstruct> GetBlockBody(DominatorTree dominatorTree, ILogicalConstruct conditionSuccessor, ConditionLogicalConstruct theCondition)
        {
            if(conditionSuccessor == dominatorTree.RootConstruct) //Corner case - the successor cannot be the entry of the construct.
            {
                return null;
            }

            HashSet<ILogicalConstruct> body = null;
            if(conditionSuccessor.AllPredecessors.Count == 1) //The condition successor must have only one predecessor - the condition.
            {
                body = new HashSet<ILogicalConstruct>();
                foreach (ILogicalConstruct node in dominatorTree.GetDominatedNodes(conditionSuccessor))
                {
                    if (node == theCondition)
                    {
                        return null;
                    }
                    body.Add(node);
                }
            }

            return body;
        }
        private void UpdateDominatorTree(DominatorTree dominatorTree, SwitchLogicalConstruct theSwitchConstruct)
        {
            HashSet<ISingleEntrySubGraph> switchNodes = new HashSet<ISingleEntrySubGraph>();
            switchNodes.Add(theSwitchConstruct.Entry);
            foreach (CaseLogicalConstruct @case in theSwitchConstruct.ConditionCases)
            {
                switchNodes.UnionWith(@case.Children);
            }

            if (theSwitchConstruct.DefaultCase != null)
            {
                switchNodes.UnionWith(theSwitchConstruct.DefaultCase.Children);
            }

            dominatorTree.MergeNodes(switchNodes, theSwitchConstruct.Entry, theSwitchConstruct);
        }
        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;
        }