1 cananian 1.1 // DomTree.java, created Mon Sep 14 17:38:43 1998 by cananian 2 cananian 1.8 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.8 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1 package harpoon.Analysis; 5 cananian 1.1 6 cananian 1.8.2.2 import harpoon.ClassFile.HCode; 7 cananian 1.8.2.2 import harpoon.ClassFile.HCodeEdge; 8 cananian 1.8.2.2 import harpoon.ClassFile.HCodeElement; 9 cananian 1.8.2.6 import harpoon.IR.Properties.CFGrapher; 10 cananian 1.8.2.1 import harpoon.Util.ArrayFactory; 11 cananian 1.8.2.7 import harpoon.Util.ArrayIterator; 12 cananian 1.12 import net.cscott.jutil.AggregateSetFactory; 13 cananian 1.12 import net.cscott.jutil.GenericMultiMap; 14 cananian 1.12 import net.cscott.jutil.MultiMap; 15 cananian 1.8.2.4 import harpoon.Util.Util; 16 cananian 1.12 import net.cscott.jutil.Default; 17 cananian 1.1 18 cananian 1.8.2.8 import java.util.Collection; 19 cananian 1.8.2.8 import java.util.HashMap; 20 cananian 1.1 import java.util.Hashtable; 21 cananian 1.8.2.7 import java.util.Iterator; 22 cananian 1.8.2.8 import java.util.Map; 23 cananian 1.1 import java.util.Vector; 24 pnkfelix 1.8.2.9 import java.util.List; 25 pnkfelix 1.8.2.9 import java.util.Stack; 26 pnkfelix 1.8.2.9 27 cananian 1.1 /** 28 cananian 1.1 * <code>DomTree</code> computes the dominator tree of a flowgraph-structured 29 cananian 1.8.2.7 * IR. The <code>HCode</code> must have a valid 30 cananian 1.8.2.7 * <code>CFGrapher</code>. 31 cananian 1.1 * 32 cananian 1.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 33 cananian 1.12 * @version $Id: DomTree.java,v 1.12 2004/02/08 01:49:03 cananian Exp $ 34 cananian 1.1 */ 35 cananian 1.1 36 cananian 1.10.2.2 public class DomTree<HCE extends HCodeElement> /*implements Graph*/ { 37 cananian 1.8.2.7 /** <code>HCode</code> this <code>DomTree</code> corresponds to. */ 38 cananian 1.10.2.2 final HCode<HCE> hcode; // included only for DomFrontier's use. 39 cananian 1.8.2.7 /** <code>CFGrapher</code> used to construct this <code>DomTree</code>.*/ 40 cananian 1.10.2.2 final CFGrapher<HCE> grapher; // included only for DomFrontier's use. 41 cananian 1.1 /** Mapping of HCodeElements to their immediate dominators. */ 42 cananian 1.10.2.2 Map<HCE,HCE> idom = new HashMap<HCE,HCE>(); 43 cananian 1.1 /** Reverse mapping: mapping of an HCodeElement to the elements which 44 cananian 1.1 * have this element as their immediate dominator. */ 45 cananian 1.10.2.2 final SetHTable<HCE> children; 46 cananian 1.8.2.7 47 cananian 1.8.2.7 /** Creates a new <code>DomTree</code> with the dominator 48 cananian 1.8.2.7 * tree for the given <code>HCode</code>; if <code>isPost</code> is 49 cananian 1.8.2.6 * true, creates a postdominator tree instead. Uses the default 50 cananian 1.8.2.6 * <code>CFGrapher</code>, which means the elements of the 51 cananian 1.8.2.6 * <code>HCode</code> must implement <code>CFGraphable</code>. */ 52 cananian 1.10.2.2 public DomTree(HCode<HCE> hcode, boolean isPost) { 53 cananian 1.12 this(hcode, (CFGrapher<HCE>) CFGrapher.DEFAULT, isPost); 54 cananian 1.8.2.6 } 55 cananian 1.8.2.7 /** Creates a new <code>DomTree</code> with the dominator 56 cananian 1.8.2.7 * tree for the given <code>HCode</code>; if <code>isPost</code> is 57 cananian 1.8.2.7 * true, creates a postdominator tree instead. Uses the specified 58 cananian 1.8.2.7 * <code>CFGrapher</code> to construct the control flow graph of 59 cananian 1.8.2.7 * the <code>HCode</code>. */ 60 cananian 1.10.2.2 public DomTree(HCode<HCE> hcode, CFGrapher<HCE> grapher, boolean isPost) { 61 cananian 1.8.2.7 this(hcode, isPost?grapher.edgeReversed():grapher); 62 cananian 1.8.2.7 } 63 cananian 1.8.2.7 /** Common constructor. Not for external use: we want people to be aware 64 cananian 1.8.2.7 * whether they're requesting a dominator or post-dominator tree. */ 65 cananian 1.10.2.2 private DomTree(HCode<HCE> hcode, CFGrapher<HCE> grapher) { 66 cananian 1.8.2.7 this.hcode = hcode; 67 cananian 1.8.2.6 this.grapher = grapher; 68 cananian 1.10.2.2 this.children = new SetHTable<HCE>(hcode.elementArrayFactory()); 69 cananian 1.8.2.7 analyze(hcode, grapher); 70 cananian 1.8.2.7 71 cananian 1.1 } 72 cananian 1.1 73 cananian 1.8.2.7 /** Return the roots of the (post-)dominator tree (forest). */ 74 cananian 1.10.2.2 public HCE[] roots() { 75 cananian 1.8.2.7 return grapher.getFirstElements(hcode); 76 cananian 1.8.2.7 } 77 cananian 1.8.2.7 78 cananian 1.8.2.7 /** Return the immediate (post)dominator of an <code>HCodeElement</code>. 79 cananian 1.8.2.7 * @return the immediate (post)dominator of <code>n</code>, or 80 cananian 1.8.2.7 * <code>null</code> if <code>n</code> is the root (a leaf) 81 cananian 1.1 * of the flow graph. */ 82 cananian 1.10.2.2 public HCE idom(HCE n) { 83 cananian 1.10.2.2 return idom.get(n); 84 cananian 1.1 } 85 cananian 1.3 /** Return the children of an <code>HCodeElement</code> in the immediate 86 cananian 1.8.2.7 * (post)dominator tree. 87 cananian 1.1 * @return an array with all the children of <code>n</code> in the 88 cananian 1.1 * immediate dominator tree, or a zero-length array if 89 cananian 1.1 * <code>n</code> is a tree leaf. */ 90 cananian 1.10.2.2 public HCE[] children(HCE n) { 91 cananian 1.8.2.7 return children.getSet(n); 92 cananian 1.1 } 93 cananian 1.1 94 cananian 1.8.2.6 /** Analyze an <code>HCode</code>. */ 95 cananian 1.10.2.3 private void analyze(final HCode<HCE> hc, final CFGrapher<HCE> grapher) { 96 cananian 1.1 // Setup lists and tables. 97 cananian 1.10.2.2 final IntHTable<HCE> dfnum = new IntHTable<HCE>(); 98 cananian 1.10.2.2 final Map<HCE,HCE> semi = new HashMap<HCE,HCE>(); 99 cananian 1.10.2.2 final Map<HCE,HCE> ancestor = new HashMap<HCE,HCE>(); 100 cananian 1.10.2.2 final Map<HCE,HCE> parent = new HashMap<HCE,HCE>(); 101 cananian 1.10.2.2 final Map<HCE,HCE> best = new HashMap<HCE,HCE>(); 102 cananian 1.1 103 cananian 1.10.2.2 SetHTable<HCE> bucket = new SetHTable<HCE>(hc.elementArrayFactory()); 104 cananian 1.10.2.2 Map<HCE,HCE> samedom = new HashMap<HCE,HCE>(); 105 cananian 1.1 106 cananian 1.10.2.2 final Vector<HCE> vertex = new Vector<HCE>(); 107 cananian 1.1 108 cananian 1.1 /** Utility class wraps analysis subroutines. */ 109 cananian 1.1 class Utility { 110 pnkfelix 1.8.2.9 /** Number nodes of depth-first spanning tree 111 pnkfelix 1.8.2.9 @requires: n_orig != null. (note p_orig may be null) 112 pnkfelix 1.8.2.9 */ 113 cananian 1.10.2.2 void DFS(HCE p_orig, HCE n_orig) { 114 pnkfelix 1.8.2.9 // Does an depth first iteration by keeping partially 115 pnkfelix 1.8.2.9 // traversed iterators on the stack. 116 cananian 1.10.2.2 Stack<Pair<HCE,Iterator<HCE>>> stk = 117 cananian 1.10.2.2 new Stack<Pair<HCE,Iterator<HCE>>>(); 118 cananian 1.10.2.2 stk.push( cons(p_orig, Default.singletonIterator(n_orig)) ); 119 pnkfelix 1.8.2.9 while( ! stk.isEmpty() ){ 120 cananian 1.10.2.2 Pair<HCE,Iterator<HCE>> pair = stk.peek(); 121 cananian 1.10.2.2 HCE p = pair.left; 122 cananian 1.10.2.2 Iterator<HCE> niter = pair.right; 123 pnkfelix 1.8.2.9 if (niter.hasNext()){ 124 cananian 1.10.2.2 HCE n = niter.next(); 125 pnkfelix 1.8.2.9 if (dfnum.getInt(n)==0) { 126 pnkfelix 1.8.2.9 int N = vertex.size()+1; 127 pnkfelix 1.8.2.9 dfnum.putInt(n, N); 128 pnkfelix 1.8.2.9 if (p!=null) 129 pnkfelix 1.8.2.9 parent.put(n, p); 130 pnkfelix 1.8.2.9 vertex.addElement(n); 131 cananian 1.10.2.2 Iterator<HCE> succIter = grapher.succElemC(n).iterator(); 132 cananian 1.10.2.2 stk.push( cons(n, succIter) ); 133 pnkfelix 1.8.2.9 } 134 pnkfelix 1.8.2.9 continue; 135 cananian 1.2 } else { 136 pnkfelix 1.8.2.9 stk.pop(); 137 cananian 1.2 } 138 cananian 1.1 } 139 cananian 1.1 } 140 pnkfelix 1.8.2.9 141 cananian 1.1 /** Add edge p->n to spanning forest. */ 142 cananian 1.10.2.2 void Link(HCE p, HCE n) { 143 cananian 1.1 ancestor.put(n, p); 144 cananian 1.1 best.put(n, n); 145 cananian 1.1 } 146 cananian 1.1 /** In the forest, find nonroot ancestor of n that has 147 cananian 1.1 * lowest-numbered semidominator. */ 148 cananian 1.10.2.2 HCE Eval(HCE vOrig) { 149 cananian 1.10.2.2 HCE v, a, b; 150 cananian 1.10.2.2 Stack<Pair<HCE,HCE>> stk = new Stack<Pair<HCE,HCE>>(); 151 pnkfelix 1.8.2.9 v = vOrig; 152 cananian 1.10.2.2 a = ancestor.get(v); 153 pnkfelix 1.8.2.9 while( ancestor.get(a) != null ){ 154 cananian 1.10.2.2 stk.push( cons(v, a) ); 155 cananian 1.10.2.2 v = a; a = ancestor.get(a); 156 pnkfelix 1.8.2.9 } 157 cananian 1.10.2.2 b = best.get(v); // base case return 158 pnkfelix 1.8.2.9 while( ! stk.isEmpty() ){ 159 cananian 1.10.2.2 Pair<HCE,HCE> pair = stk.pop(); 160 cananian 1.10.2.2 v = pair.left; 161 cananian 1.10.2.2 a = pair.right; 162 cananian 1.1 ancestor.put(v, ancestor.get(a)); 163 pnkfelix 1.8.2.9 if (dfnum.getInt(semi.get(b)) < 164 pnkfelix 1.8.2.9 dfnum.getInt(semi.get(best.get(v)))){ 165 cananian 1.1 best.put(v, b); 166 pnkfelix 1.8.2.9 } 167 cananian 1.10.2.2 b = best.get(v); // recursive return 168 cananian 1.1 } 169 cananian 1.10.2.1 assert v == vOrig; 170 cananian 1.10.2.1 assert b == best.get(v); 171 pnkfelix 1.8.2.9 return b; 172 cananian 1.1 } 173 cananian 1.1 } 174 cananian 1.1 Utility u = new Utility(); 175 cananian 1.1 176 cananian 1.1 // Dominators algorithm: 177 cananian 1.10.2.3 for (Iterator<HCE> it = new ArrayIterator<HCE> 178 cananian 1.10.2.3 (grapher.getFirstElements(hc)); it.hasNext(); ) 179 cananian 1.10.2.2 u.DFS(null, it.next()); 180 cananian 1.2 181 cananian 1.2 for (int i=vertex.size()-1; i>=0; i--) { 182 cananian 1.1 // calculate the semidominator of vertex[i] 183 cananian 1.10.2.2 HCE n = vertex.elementAt(i); 184 cananian 1.10.2.2 HCE p = parent.get(n); 185 cananian 1.10.2.2 HCE s = p; 186 cananian 1.10.2.2 HCE sprime; 187 cananian 1.1 188 cananian 1.2 if (p == null) continue; // skip root(s). 189 cananian 1.2 190 cananian 1.1 // (for each predecessor v of n) 191 cananian 1.10.2.2 for (Iterator<HCodeEdge<HCE>> it=grapher.predC(n).iterator(); it.hasNext(); ) { 192 cananian 1.10.2.2 HCE v = it.next().from(); 193 cananian 1.1 // ignore unreachable nodes. 194 cananian 1.1 if (!dfnum.containsKey(v)) continue; 195 cananian 1.7 if (dfnum.getInt(v) <= dfnum.getInt(n)) 196 cananian 1.1 sprime = v; 197 cananian 1.1 else 198 cananian 1.10.2.2 sprime = semi.get(u.Eval(v)); 199 cananian 1.1 if (dfnum.getInt(sprime) < dfnum.getInt(s)) 200 cananian 1.1 s = sprime; 201 cananian 1.1 } 202 cananian 1.1 semi.put(n, s); 203 cananian 1.1 204 cananian 1.1 // Calculation of n's dominator is deferred until the path 205 cananian 1.1 // from s to n has been linked into the forest. 206 cananian 1.1 bucket.unionSet(s, n); 207 cananian 1.1 u.Link(p, n); 208 cananian 1.1 209 cananian 1.1 // Now that the path from p to n has been linked into the 210 cananian 1.1 // spanning forest, calculate the dominator of v (or else defer 211 cananian 1.1 // the calculation). 212 cananian 1.1 // (for each v in bucket[p]) 213 cananian 1.10.2.2 HCE[] hcel = bucket.getSet(p); 214 cananian 1.1 for (int j=0; j<hcel.length; j++) { 215 cananian 1.10.2.2 HCE v = hcel[j]; 216 cananian 1.10.2.2 HCE y = u.Eval(v); 217 cananian 1.1 if (semi.get(y) == semi.get(v)) 218 cananian 1.1 idom.put(v, p); 219 cananian 1.1 else 220 cananian 1.1 samedom.put(v, y); 221 cananian 1.1 } 222 cananian 1.1 bucket.clearSet(p); 223 cananian 1.1 } 224 cananian 1.1 // Now all the deferred dominator calculations are performed. 225 cananian 1.2 for (int i=0; i<vertex.size(); i++) { 226 cananian 1.10.2.2 HCE n = vertex.elementAt(i); 227 cananian 1.2 if (parent.get(n)==null) continue; // skip root(s). 228 cananian 1.1 if (samedom.get(n)!=null) 229 cananian 1.1 idom.put(n, idom.get(samedom.get(n))); 230 cananian 1.1 } 231 cananian 1.1 // done. Make inverse mapping. 232 cananian 1.2 for (int i=0; i<vertex.size(); i++) { 233 cananian 1.10.2.2 HCE n = vertex.elementAt(i); 234 cananian 1.10.2.2 HCE id = idom.get(n); 235 cananian 1.2 if (parent.get(n)==null) continue; // skip root(s). 236 cananian 1.1 children.unionSet(id, n); 237 cananian 1.1 } 238 cananian 1.1 } 239 cananian 1.1 240 cananian 1.10.2.2 // utility class. 241 cananian 1.10.2.2 static class Pair<A,B> { 242 cananian 1.10.2.2 public final A left; 243 cananian 1.10.2.2 public final B right; 244 cananian 1.10.2.2 Pair(A a, B b) { this.left = a; this.right = b; } 245 cananian 1.10.2.2 } 246 cananian 1.10.2.2 private static <A,B> Pair<A,B> cons(A a, B b) { return new Pair(a, b); } 247 cananian 1.1 248 cananian 1.1 // Useful Hashtable extensions. 249 cananian 1.10.2.2 static class IntHTable<V> { 250 cananian 1.10.2.2 private Map<V,Integer> m = new HashMap<V,Integer>(); 251 cananian 1.10.2.2 void putInt(V o, int n) { 252 cananian 1.8.2.8 m.put(o, new Integer(n)); 253 cananian 1.1 } 254 cananian 1.10.2.2 int getInt(V o) { 255 cananian 1.8.2.8 if (!m.containsKey(o)) return 0; 256 cananian 1.10.2.2 return m.get(o).intValue(); 257 cananian 1.8.2.8 } 258 cananian 1.8.2.8 boolean containsKey(Object o) { 259 cananian 1.8.2.8 return m.containsKey(o); 260 cananian 1.1 } 261 cananian 1.1 } 262 cananian 1.10.2.2 static class SetHTable<HCE extends HCodeElement> { 263 cananian 1.10.2.2 ArrayFactory<HCE> af; 264 cananian 1.10.2.2 MultiMap<HCE,HCE> mm = 265 cananian 1.10.2.2 new GenericMultiMap<HCE,HCE>(new AggregateSetFactory<HCE>()); 266 cananian 1.10.2.2 SetHTable(ArrayFactory<HCE> af) { super(); this.af = af; } 267 cananian 1.10.2.2 void clearSet(HCE hce) { 268 cananian 1.8.2.8 mm.remove(hce); 269 cananian 1.1 } 270 cananian 1.10.2.2 HCE[] getSet(HCE hce) { 271 cananian 1.10.2.2 Collection<HCE> c = mm.getValues(hce); 272 cananian 1.10.2.2 return c.toArray(af.newArray(c.size())); 273 cananian 1.1 } 274 cananian 1.10.2.2 void unionSet(HCE hce, HCE newEl) { 275 cananian 1.8.2.8 mm.add(hce, newEl); 276 cananian 1.1 } 277 cananian 1.1 } 278 cananian 1.1 }