private void CollectLoopBody(GraphNode gn)
 {
     if (gn == Cutpoint) return;
     if (!LoopNodes.Contains(gn))
     {
         if (gn.IsCutpoint) // nested loop found
         {
             Loop lo = new Loop(gn);
             foreach (GraphNode lgn in lo.LoopNodes)
             {
                 if (!LoopNodes.Contains(lgn)) LoopNodes.Add(lgn);
             }
             NestedLoops.Add(lo);
         }
         else
         {
             LoopNodes.Add(gn);
         }
         foreach (GraphNode pre in gn.Pre) if (!gn.LoopingPred.Contains(pre)) CollectLoopBody(pre);
     }
 }
 public void RemoveEdgeTo(GraphNode other)
 {
     if (this.Suc.Contains(other)) this.Suc.Remove(other);
     if (other.Pre.Contains(this)) other.Pre.Remove(this);         
 }
 public Loop(GraphNode cutpoint)
 {
     if (!cutpoint.IsCutpoint)
     {
         Debugger.Break();
     }
     Cutpoint = cutpoint;
     LoopNodes.Add(Cutpoint);
     foreach (GraphNode gn in Cutpoint.LoopingPred)
     {
         CollectLoopBody(gn);
     }
     CollectLoopExitNodes();
 }
 private List<Loop> m_CollectLoops(GraphNode gn, Loop lastLoop)
 {
     List<Loop> ret = new List<Loop>();
     if (gn.Visited) return ret;
     gn.Visited = true;
     List<GraphNode> loopingSucs = new List<GraphNode>();
     if (gn.IsCutpoint)
     {                
         Loop l = new Loop(gn);
         if (lastLoop != null)
         {
             lastLoop.SucLoops.Add(l);
             l.PreLoops.Add(lastLoop);
         }
         loopingSucs = l.LoopNodes;
         lastLoop = l;
         ret.Add(lastLoop);
     }
     foreach (GraphNode suc in gn.Suc)
     {
         if (!loopingSucs.Contains(suc)) ret.AddRange(m_CollectLoops(suc, lastLoop));                
     }
     //Debugger.Break();
     return ret;
 }
 public void AddEdgeTo(GraphNode other)
 {
     if (!this.Suc.Contains(other)) this.Suc.Add(other);
     if (!other.Pre.Contains(this)) other.Pre.Add(this);
 }
/*
        private void m_DetectCutPoints(GraphNode gn, GraphNode pred, List<GraphNode> visited )
        {
            if (visited.Contains(gn) )
            {
                if (pred != null && !gn.LoopingPred.Contains(pred)) gn.LoopingPred.Add(pred);
                gn.IsCutpoint = true;
                Console.WriteLine("Normal RootNode {0}", gn.Label.Label);
                return;
            }
            else
            {
                List<GraphNode> visited_ = new List<GraphNode>();
                visited_.AddRange(visited);
                visited_.Add(gn);
                foreach (GraphNode next in gn.Suc)
                {
                    m_DetectCutPoints(next,gn,visited_);
                }
            }

        }
*/


        private void m_DetectCutPoints(GraphNode gn)
        {
            List<GraphNode> todo = new List<GraphNode>();
            List<GraphNode> done = new List<GraphNode>();
            todo.Add(gn);

            GraphNode current = null;
            todo[0].Index = 0;

            while (todo.Count > 0)
            {
                current = todo[0];
                todo.Remove(current);

                bool ready = true;
                foreach (GraphNode p in current.Pre)
                {                    
                    if (!done.Contains(p) )
                    {
                        _loopbacktracking.Clear();
                        if (!m_isLoop(current, p, todo, done))
                        {
                            todo.Add(current);
                            ready = false;
                            break;
                        }
                        else
                        {
                            if (!current.LoopingPred.Contains(p)) current.LoopingPred.Add(p);
                            current.IsCutpoint = true;
                        }
                    } 
                }
                if (!ready) continue;
                done.Add(current);
                foreach (GraphNode s in current.Suc)
                {
                    if (!todo.Contains(s) && !done.Contains(s)) todo.Add(s);
                }
            }

        }
 private bool m_isLoop(GraphNode loophead, GraphNode gn, List<GraphNode> l1, List<GraphNode> l2)
 {
     if (loophead == gn) return true;
     if (l1.Contains(gn) || l2.Contains(gn) || _loopbacktracking.Contains(gn)) return false;
     _loopbacktracking.Add(gn);
     foreach (GraphNode p in gn.Pre)
     {
         if (m_isLoop(loophead, p, l1, l2)) return true;
     }
     return false;
 }
 public void DeleteGraphNode(GraphNode gn)
 {
     List<Block> affected = new List<Block>();
                 
     foreach (KeyValuePair<Block, GraphNode> kvp in GraphMap)
     {
         if (kvp.Value == gn && !affected.Contains(kvp.Key)) affected.Add(kvp.Key);
     }
     foreach (Block b in affected)
     {
         GraphMap.Remove(b);
     }
 }
        public GraphNode CloneGraphNode(GraphNode gn, string prefix)
        {
            List<Cmd> cmds = new List<Cmd>(gn.Label.Cmds);

            Block b = new Block(gn.Label.tok, prefix+gn.Label.Label, cmds, gn.Label.TransferCmd);
            GraphNode clone = new GraphNode(b);
            clone.IsCutpoint = gn.IsCutpoint;
            clone.Suc.AddRange(gn.Suc);
            clone.Pre.AddRange(gn.Pre);
            clone.LoopingPred.AddRange(gn.LoopingPred);
            GraphMap[b] = clone;
            //if (gn.Label == ExitBlock) ExitBlock = b;
            return clone;
        }
        public GraphAnalyzer(List<Block> blocks)
        {
            //ExitBlock = dedicatedExitBlock;
            if (blocks.Count < 1) return;
            foreach (Block b in blocks) GraphMap[b] = new GraphNode(b);
            foreach (Block b in blocks)
            {
                foreach (Block pre in b.Predecessors) GraphMap[b].Pre.Add(GraphMap[pre]);
                GotoCmd gc = b.TransferCmd as GotoCmd;
                if (gc != null)
                {
                    foreach (Block suc in gc.labelTargets) GraphMap[b].Suc.Add(GraphMap[suc]);
                }
            }

            
            m_DetectCutPoints(GraphMap[blocks[0]]);
            
            //m_DetectCutPoints(GraphMap[blocks[0]], null, new List<GraphNode>());  
            Graphloops = m_CollectLoops(GraphMap[blocks[0]], null);
            
        }
        private void m_ReplaceBackEdge(Loop l, GraphNode loopSkip)
        {

            foreach (GraphNode gn in l.Cutpoint.LoopingPred)
            {
                List<GraphNode> newsuc = new List<GraphNode>();
                foreach (GraphNode s in gn.Suc)
                {
                    if (s == l.Cutpoint) newsuc.Add(loopSkip);
                    else newsuc.Add(s);
                }
                gn.Suc = newsuc;
            }
        }
        private List<GraphNode> m_MarkLoopExitUncheckable(GraphNode g, Loop l)
        {
            List<GraphNode> ret = new List<GraphNode>();

            if (g.Pre.Count > 1) return ret;
            ret.Add(g);
            foreach (GraphNode gn in g.Suc)
            {
                ret.AddRange(m_MarkLoopExitUncheckable(gn, l));
            }

            return ret;
        }