using Graphing; using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; namespace Microsoft.Boogie { public static class GraphAlgorithms { public static Graph Dual(this Graph g, Node dummySource) { var exits = g.Nodes.Where(n => g.Successors(n).Count() == 0).ToList(); if (exits.Count == 0) return null; var dual = new Graph(new HashSet>(g.Edges.Select(e => new Tuple(e.Item2, e.Item1)))); if (exits.Count == 1) dual.AddSource(exits[0]); else { dual.AddSource(dummySource); foreach (var exit in exits) dual.AddEdge(dummySource, exit); } return dual; } public static List> LoopyTopSort(this Graph g) { Contract.Assert(g.Reducible); int n = g.Nodes.Count; var nodeToNumber = new Dictionary(n); var numberToNode = new Node[n]; var allNodes = new List(); int counter = 0; foreach (Node node in g.Nodes) { numberToNode[counter] = node; nodeToNumber[node] = counter; allNodes.Add(counter); counter++; } var loops = new List[n]; foreach (var h in g.Headers) { var loopNodes = new HashSet(); foreach (var b in g.BackEdgeNodes(h)) loopNodes.UnionWith(g.NaturalLoops(h, b)); loops[nodeToNumber[h]] = new List(loopNodes.Select(node => nodeToNumber[node])); } var successors = new List[n]; int[] incomingEdges = new int[n]; foreach (var e in g.Edges) { Contract.Assert(e.Item1 != null); Contract.Assert(e.Item2 != null); int source = nodeToNumber[e.Item1], target = nodeToNumber[e.Item2]; if (loops[target] == null || !loops[target].Contains(source)) { if (successors[source] == null) successors[source] = new List(); successors[source].Add(target); incomingEdges[target]++; } } var sortedNodes = new List>(); var regionStack = new Stack>>(); regionStack.Push(new Tuple>(default(Node), allNodes)); while (regionStack.Count != 0) { int rootIndex = -1; foreach (var i in regionStack.Peek().Item2) { if (incomingEdges[i] == 0) { rootIndex = i; break; } } if (rootIndex == -1) { var region = regionStack.Pop(); if (regionStack.Count != 0) sortedNodes.Add(new Tuple(region.Item1, true)); continue; } incomingEdges[rootIndex] = -1; sortedNodes.Add(new Tuple(numberToNode[rootIndex], false)); if (successors[rootIndex] != null) foreach (int s in successors[rootIndex]) incomingEdges[s]--; if (loops[rootIndex] != null) regionStack.Push(new Tuple>(numberToNode[rootIndex], loops[rootIndex])); } return sortedNodes; } // Algorithm from Jeanne Ferrante, Karl J. Ottenstein, Joe D. Warren, // "The Program Dependence Graph and Its Use in Optimization" public static Dictionary> ControlDependence(this Graph g) where Node : class, new() { Graph dual = g.Dual(new Node()); DomRelation pdom = dual.DominatorMap; var result = new Dictionary>(); var S = g.Edges.Where(e => !pdom.DominatedBy(e.Item1, e.Item2)); foreach (var edge in S) { var L = pdom.LeastCommonAncestor(edge.Item1, edge.Item2); var deps = new List(); if (L == edge.Item1) { pdom.DominatedBy(edge.Item2, edge.Item1, deps); deps.Add(edge.Item2); deps.Add(edge.Item1); } else { pdom.DominatedBy(edge.Item2, L, deps); deps.Add(edge.Item2); } if (result.ContainsKey(edge.Item1)) { result[edge.Item1].UnionWith(deps); } else { result[edge.Item1] = new HashSet(deps); } } return result; } } }