/// <summary> /// Analyzes the loop nesting structure of the control-flow graph. /// The default implementation directs the tasks to Havlak's algorithm. /// </summary> protected virtual void AnalyzeLoops() { IGraphAdapter <BasicBlock <Ti> > a = BasicBlock <Ti> .LoopAnalysisAdapter; BasicBlock <Ti>[] reachable = a.GetPreOrder(BasicBlocks, EntryCB); a.InvertRelation(a.Succs, a.Preds, reachable); a.AnalyzeLoops(reachable, EntryCB); }
/// <summary> /// Determines the loop nesting structure of the given (control-flow) graph. /// </summary> /// <remarks> /// This is an implementation of Paul Havlak's loop analysis algorithm. /// Reference: ACM Transactions on Programming Languages and Systems, Vol. 19, No. 4, July 1997, Pages 557-567. /// </remarks> /// <param name="a">graph adapter</param> /// <param name="nodes">nodes to consider</param> /// <param name="start">entry node</param> public static void AnalyzeLoops <T>(this IGraphAdapter <T> a, IList <T> nodes, T start) { T[] order = a.GetPreOrder(nodes, start); // fix_loops part #if false foreach (T w in order) { a.RedBackIn[w] = new HashSet <T>(); a.OtherIn[w] = new HashSet <T>(); foreach (T v in a.Preds[w]) { if (a.PreOrderIndex[w] < a.PreOrderIndex[v]) { a.RedBackIn[w].Add(v); } else { a.OtherIn[w].Add(v); } } if (a.RedBackIn[w].Count > 0 && a.OtherIn[w].Count > 1) { throw new NotImplementedException(); } } #endif foreach (T w in order /*nodes*/) { a.BackPreds[w] = new HashSet <T>(); a.NonBackPreds[w] = new HashSet <T>(); a.Header[w] = start; a.Type[w] = ENodeType.Nonheader; foreach (T v in a.Preds[w]) { if (a.IsAncestor(w, v)) { a.BackPreds[w].Add(v); } else { a.NonBackPreds[w].Add(v); } } } a.Header[start] = default(T); HashSet <T> P = new HashSet <T>(); UnionFind <T> uf = new PreOrderSetAdapter <T>(a).CreateUnionFind(order); for (int iw = order.Length - 1; iw >= 0; iw--) { T w = order[iw]; P.Clear(); foreach (T v in a.BackPreds[w]) { if (!v.Equals(w)) { P.Add(uf.Find(v)); } else { a.Type[w] = ENodeType.Self; } } Queue <T> worklist = new Queue <T>(P); if (P.Count > 0) { a.Type[w] = ENodeType.Reducible; } while (worklist.Count > 0) { T x = worklist.Dequeue(); foreach (T y in a.NonBackPreds[x]) { T y_ = uf.Find(y); if (!a.IsAncestor(w, y_)) { a.Type[w] = ENodeType.Irreducible; a.NonBackPreds[w].Add(y_); } else if (!P.Contains(y_) && !w.Equals(y_)) { P.Add(y_); worklist.Enqueue(y_); } } } foreach (T x in P) { a.Header[x] = w; uf.Union(x, w); } } }