using System.Collections; namespace Graphing; type Node = object; type Edge = ; class PreHeader { Node myHeader; PreHeader(Node h) { myHeader = h; } public override string ToString() { return "#" + myHeader.ToString(); } } public class Graph { private Set es; private Set ns; private Node source; private bool reducible; private Set headers; private Map> backEdgeNodes; private Map> naturalLoops; private Map> dominatorMap; private Map> immediateDominatorMap; public Graph(Set edges) { es = edges; ns = Set{ x : in es } + Set{ y : in es }; } public Graph() { es = Set{}; ns = Set{}; } public void AddSource(Node x) { ns += Set{x}; source = x; } public void AddEdge(Node source, Node dest) { es += Set{}; ns += Set{source, dest}; } public Set Nodes { get { return ns; } } public Set Edges { get { return es; } } public bool Edge(Node x, Node y) { return in es; } Set predecessors(Node n) { Set result = Set{ x : x in Nodes, Edge(x,n) }; return result; } public override string ToString() { return es.ToString(); } public IEnumerable TopologicalSort() { > = TopSort(this); return res ? ns : null; } public void ComputeLoops() { , Map>, Map>> = Reducible(this,this.source); this.reducible = reducible; this.headers = headers; this.backEdgeNodes = backEdgeNodes; this.naturalLoops = naturalLoops; return; } public bool Reducible { get { return reducible; } } public IEnumerable Headers { get { return headers; } } public IEnumerable BackEdgeNodes(Node h) { return h in backEdgeNodes ? backEdgeNodes[h] : null; } public IEnumerable NaturalLoops(Node header, Node backEdgeNode) { Edge e = ; return e in naturalLoops ? naturalLoops[e] : null; } public bool Acyclic { get { return Acyclic(this,this.source); } } public Map> DominatorMap { get { if (dominatorMap == null) dominatorMap = ComputeDominators(this, source); return dominatorMap; } } public Map> ImmediateDominatorMap { get { if (immediateDominatorMap == null) { immediateDominatorMap = Map{}; foreach(Node y in Nodes) { Set nodesThatYDominates = Set{ x : x in Nodes, x != y && (y in DominatorMap[x]) }; Set immediateDominatees = Set{ x : x in nodesThatYDominates, !(Exists{ v != y && v != x && (v in DominatorMap[x]) : v in nodesThatYDominates }) }; immediateDominatorMap[y] = immediateDominatees; } } return immediateDominatorMap; } } public Set ImmediatelyDominatedBy(Node n) { return ImmediateDominatorMap[n]; } } // From AsmL distribution example: TopologicalSort > TopSort(Graph g) { Seq S = Seq{}; Set V = g.Nodes; bool change = true; while ( change ) { change = false; Set X = V - ((Set) S); if ( X != Set{} ) { Node temp = Choose{ v : v in X, !(Exists{ g.Edge(u,v) : u in X }) ifnone null }; if ( temp == null ) { return {}>; } else if ( temp != Seq{} ) { S += Seq{temp}; change = true; } } } return ; } bool Acyclic(Graph g, Node source) { > = TopSort(g); return acyc; } // // [Dragon, pp. 670--671] // returns map D s.t. d in D(n) iff d dom n // Map> ComputeDominators(Graph g, Node source) { Set N = g.Nodes; Set nonSourceNodes = N - Set{source}; Map> D = Map{}; D[source] = Set{ source }; foreach (Node n in nonSourceNodes) { D[n] = N; } bool change = true; while ( change ) { change = false; foreach (Node n in nonSourceNodes) { Set> allPreds = Set{ D[p] : p in g.predecessors(n) }; Set temp = Set{ n } + BigIntersect(allPreds); if ( temp != D[n] ) { change = true; D[n] = temp; } } } return D; } // [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.] Set NaturalLoop(Graph g, Edge backEdge) { = backEdge; Seq stack = Seq{}; Set loop = Set{ d }; if ( n != d ) // then n is not in loop { loop += Set{ n }; stack = Seq{ n } + stack; // push n onto stack } while ( stack != Seq{} ) // not empty { Node m = Head(stack); stack = Tail(stack); // pop stack foreach (Node p in g.predecessors(m)) { if ( !(p in loop) ) { loop += Set{ p }; stack = Seq{ p } + stack; // push p onto stack } } } return loop; } // [Dragon, p. 606] , Map>, Map>> Reducible(Graph g, Node source) { // first, compute the dom relation Map> D = g.DominatorMap; return Reducible(g,source,D); } // [Dragon, p. 606] , Map>, Map>> Reducible(Graph g, Node source, Map> DomRelation) { Set edges = g.Edges; Set backEdges = Set{}; Set nonBackEdges = Set{}; foreach (Edge e in edges) { = e; // so there is an edge from x to y if ( y in DomRelation[x] ) // y dom x: which means y dominates x { backEdges += Set{ e }; } else { nonBackEdges += Set{ e }; } } if ( !Acyclic(new Graph(nonBackEdges), source) ) { return {},Map>{},Map>{}>; } else { Set headers = Set{ d : in backEdges }; Map> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set{ b : in backEdges, x == h } }; Map> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges }; return ; } } // [Dragon, p. 606] bool OldReducible(Graph g, Node source) { // first, compute the dom relation Map> D = ComputeDominators(g, source); return OldReducible(g,source,D); } // [Dragon, p. 606] bool OldReducible(Graph g, Node source, Map> DomRelation) { Set edges = g.Edges; Set backEdges = Set{}; Set nonBackEdges = Set{}; foreach (Edge e in edges) { = e; if ( y in DomRelation[x] ) // y dom x { backEdges += Set{ e }; } else { nonBackEdges += Set{ e }; } } WriteLine("backEdges: " + backEdges); WriteLine("nonBackEdges: " + nonBackEdges); if ( Acyclic(new Graph(nonBackEdges), source) ) { foreach(Edge e in backEdges) { Set naturalLoop = NaturalLoop(g,e); WriteLine("Natural loop for back edge '" + e + "' is: " + naturalLoop); } Set headers = Set{ d : in backEdges }; WriteLine("Loop headers = " + headers); edges -= backEdges; // this cuts all of the back edges foreach (Node h in headers) { Set bs = Set{ : in backEdges, d == h }; Set preds = Set{ p : in edges, y == h }; Node preheader = new PreHeader(h); edges += Set{ }; foreach (Node p in preds) { edges -= Set{ }; edges += Set{ }; } } Graph newGraph = new Graph(edges); WriteLine("transformed graph = " + newGraph); return true; } else { return false; } } void Main() { Graph g; Map> D; /* g = new Graph(Set{ <1,2>, <1,3>, <2,3> }); g.AddSource(1); Map> doms = ComputeDominators(g,1); WriteLine(doms); */ g = new Graph(Set{ <1,2>, <1,3>, <2,3>, <3,4>, <4,3>, <4,5>, <4,6>, <5,7>, <6,7>, <7,4>, <7,8>, <8,3>, <8,9>, <8,10>, <9,1>, <10,7> }); g.AddSource(1); WriteLine("G = " + g); D = ComputeDominators(g,1); WriteLine("Dom relation: " + D); WriteLine("G's Dominator Map = " + g.DominatorMap); WriteLine("G's Immediate Dominator Map = " + g.ImmediateDominatorMap); WriteLine("G is reducible: " + OldReducible(g,1,D)); g.ComputeLoops(); WriteLine(""); g = new Graph(Set{ <1,2>, <1,3>, <2,3>, <3,2> }); g.AddSource(1); WriteLine("G = " + g); D = ComputeDominators(g,1); WriteLine("Dom relation: " + D); WriteLine("G's Dominator Map = " + g.DominatorMap); WriteLine("G's Immediate Dominator Map = " + g.ImmediateDominatorMap); WriteLine("G is reducible: " + OldReducible(g,1,D)); g.ComputeLoops(); WriteLine(""); g = new Graph(Set{ <1,2>, <2,3>, <2,4>, <3,2> }); g.AddSource(1); WriteLine("G = " + g); WriteLine("G's Dominator Map = " + g.DominatorMap); WriteLine("G's Immediate Dominator Map = " + g.ImmediateDominatorMap); // D = ComputeDominators(g,1); // WriteLine("Dom relation: " + D); // WriteLine("G is reducible: " + OldReducible(g,1,D)); g.ComputeLoops(); }