1 cananian 1.1.2.1 // DeadCode2.java, created Thu Oct 8 03:11:37 1998 by cananian 2 cananian 1.1.2.1 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 5 cananian 1.1.2.1 package harpoon.Analysis.Quads; 6 cananian 1.1.2.1 7 cananian 1.1.2.4 import harpoon.Analysis.AllocationInformationMap; 8 cananian 1.1.2.4 import harpoon.Analysis.Maps.AllocationInformation; 9 cananian 1.1.2.3 import harpoon.ClassFile.HClass; 10 cananian 1.1.2.3 import harpoon.ClassFile.HCode; 11 salcianu 1.6 import harpoon.IR.Quads.Code; 12 salcianu 1.6 import harpoon.IR.Quads.QuadSSI; 13 cananian 1.1.2.3 import harpoon.IR.Quads.Quad; 14 cananian 1.1.2.3 import harpoon.IR.Quads.QuadVisitor; 15 cananian 1.1.2.3 import harpoon.IR.Quads.Edge; 16 cananian 1.1.2.3 import harpoon.IR.Quads.AGET; 17 cananian 1.1.2.3 import harpoon.IR.Quads.ALENGTH; 18 cananian 1.1.2.3 import harpoon.IR.Quads.ANEW; 19 cananian 1.1.2.3 import harpoon.IR.Quads.ARRAYINIT; 20 cananian 1.1.2.3 import harpoon.IR.Quads.ASET; 21 cananian 1.1.2.3 import harpoon.IR.Quads.CALL; 22 cananian 1.1.2.3 import harpoon.IR.Quads.CJMP; 23 cananian 1.1.2.3 import harpoon.IR.Quads.COMPONENTOF; 24 cananian 1.1.2.3 import harpoon.IR.Quads.CONST; 25 cananian 1.1.2.3 import harpoon.IR.Quads.FOOTER; 26 cananian 1.1.2.3 import harpoon.IR.Quads.GET; 27 cananian 1.1.2.3 import harpoon.IR.Quads.HANDLER; 28 cananian 1.1.2.3 import harpoon.IR.Quads.HEADER; 29 cananian 1.1.2.3 import harpoon.IR.Quads.INSTANCEOF; 30 cananian 1.1.2.3 import harpoon.IR.Quads.METHOD; 31 cananian 1.1.2.3 import harpoon.IR.Quads.MONITORENTER; 32 cananian 1.1.2.3 import harpoon.IR.Quads.MONITOREXIT; 33 cananian 1.1.2.3 import harpoon.IR.Quads.MOVE; 34 cananian 1.1.2.3 import harpoon.IR.Quads.NEW; 35 cananian 1.1.2.3 import harpoon.IR.Quads.NOP; 36 cananian 1.1.2.3 import harpoon.IR.Quads.OPER; 37 cananian 1.1.2.3 import harpoon.IR.Quads.PHI; 38 cananian 1.1.2.3 import harpoon.IR.Quads.RETURN; 39 cananian 1.1.2.3 import harpoon.IR.Quads.SET; 40 cananian 1.1.2.3 import harpoon.IR.Quads.SIGMA; 41 cananian 1.1.2.3 import harpoon.IR.Quads.SWITCH; 42 cananian 1.1.2.3 import harpoon.IR.Quads.THROW; 43 cananian 1.1.2.7 import harpoon.IR.Quads.TYPESWITCH; 44 cananian 1.1.2.3 import harpoon.IR.LowQuad.LowQuadVisitor; 45 cananian 1.1.2.3 import harpoon.IR.LowQuad.PCALL; 46 cananian 1.1.2.3 import harpoon.IR.LowQuad.PSET; 47 cananian 1.1.2.1 import harpoon.Temp.Temp; 48 cananian 1.1.2.1 import harpoon.Temp.TempMap; 49 cananian 1.8 import net.cscott.jutil.GenericInvertibleMultiMap; 50 cananian 1.8 import net.cscott.jutil.InvertibleMultiMap; 51 cananian 1.8 import net.cscott.jutil.MultiMap; 52 cananian 1.8 import net.cscott.jutil.Default; 53 cananian 1.1.2.9 import harpoon.Util.Collections.WorkSet; 54 cananian 1.1.2.1 import harpoon.Util.Worklist; 55 cananian 1.1.2.1 import harpoon.Util.Util; 56 cananian 1.1.2.1 57 cananian 1.1.2.1 import java.util.Comparator; 58 cananian 1.1.2.1 import java.util.Enumeration; 59 cananian 1.1.2.1 import java.util.HashMap; 60 cananian 1.1.2.1 import java.util.HashSet; 61 cananian 1.1.2.8 import java.util.Iterator; 62 cananian 1.1.2.1 import java.util.Map; 63 cananian 1.1.2.1 import java.util.Set; 64 cananian 1.1.2.1 import java.util.SortedMap; 65 cananian 1.1.2.1 import java.util.TreeMap; 66 cananian 1.1.2.1 /** 67 cananian 1.1.2.1 * <code>DeadCode</code> removes dead code 68 cananian 1.1.2.1 * (unused definitions/useless jmps/one-argument phi functions/all moves) from 69 cananian 1.1.2.1 * a method. The analysis is optimistic; that is, it assumes that all code is 70 cananian 1.1.2.1 * unused and seeks to prove otherwise. Also works on LowQuads. 71 cananian 1.1.2.1 * 72 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 73 cananian 1.8 * @version $Id: DeadCode.java,v 1.8 2004/02/08 01:53:14 cananian Exp $ 74 cananian 1.1.2.1 */ 75 cananian 1.1.2.1 76 cananian 1.1.2.1 public abstract class DeadCode { 77 cananian 1.1.2.1 78 cananian 1.1.2.4 public static void optimize(harpoon.IR.Quads.Code hc, 79 cananian 1.1.2.4 AllocationInformationMap aim) { 80 cananian 1.1.2.4 AllocationInformation oldaim = hc.getAllocationInformation(); 81 cananian 1.1.2.1 // Assume everything's useless. 82 cananian 1.1.2.1 Set useful = new HashSet(); // empty set. 83 cananian 1.1.2.1 // make a renaming table 84 cananian 1.1.2.1 NameMap nm = new NameMap(); 85 cananian 1.1.2.1 // keep track of defs. 86 cananian 1.1.2.1 Map defMap = new HashMap(); 87 cananian 1.1.2.8 // keep track of PHI/SIGMAs which use certain temps. 88 cananian 1.5 InvertibleMultiMap useMap = new GenericInvertibleMultiMap(); 89 cananian 1.1.2.1 // we'll have a coupla visitors 90 cananian 1.1.2.3 LowQuadVisitor v; 91 cananian 1.1.2.1 92 cananian 1.1.2.1 // make a worklist (which everything's on, at the beginning) 93 cananian 1.1.2.8 WorkSet W = new WorkSet(); 94 cananian 1.1.2.1 Quad[] ql = (Quad[]) hc.getElements(); 95 cananian 1.1.2.1 for (int i=0; i<ql.length; i++) { 96 cananian 1.1.2.1 W.push(ql[i]); 97 cananian 1.1.2.1 // build our defMap while we're at it. 98 cananian 1.1.2.1 Temp d[] = ql[i].def(); 99 cananian 1.1.2.1 for (int j=0; j<d.length; j++) 100 cananian 1.1.2.1 defMap.put(d[j], ql[i]); 101 cananian 1.1.2.8 // and keep track of phis/sigmas which use certain temps. 102 cananian 1.1.2.8 if (ql[i] instanceof PHI || ql[i] instanceof SIGMA) 103 cananian 1.1.2.8 for (Iterator it=ql[i].useC().iterator(); it.hasNext(); ) 104 cananian 1.1.2.8 useMap.add((Temp)it.next(), ql[i]); 105 cananian 1.1.2.1 } 106 cananian 1.1.2.1 // ...and a visitor 107 cananian 1.1.2.1 v = new UsefulVisitor(W, useful, defMap, nm); 108 cananian 1.1.2.1 // look for useful stuff. 109 cananian 1.1.2.1 while (!W.isEmpty()) { 110 cananian 1.1.2.1 Quad q = (Quad) W.pull(); 111 cananian 1.1.2.2 q.accept(v); 112 cananian 1.1.2.1 } 113 cananian 1.1.2.1 114 cananian 1.1.2.1 // remove the useless stuff, including useless cjmps/phis 115 cananian 1.1.2.1 for (int i=0; i<ql.length; i++) 116 salcianu 1.6 W.push(ql[i]); 117 cananian 1.1.2.8 v = new EraserVisitor(W, useful, useMap, nm); 118 cananian 1.1.2.1 while (!W.isEmpty()) { 119 cananian 1.1.2.1 Quad q = (Quad) W.pull(); 120 cananian 1.1.2.2 q.accept(v); 121 cananian 1.1.2.1 } 122 cananian 1.1.2.1 123 cananian 1.1.2.1 // Finally, do all the necessary renaming 124 cananian 1.1.2.3 ql = (Quad[]) hc.getElements(); // put them all in an array. 125 cananian 1.1.2.1 // evil: can't replace the header node. [ack] 126 cananian 1.1.2.3 for (int i=0; i<ql.length; i++) 127 cananian 1.1.2.3 if (!(ql[i] instanceof HEADER)) 128 cananian 1.1.2.4 replace(ql[i], ql[i].rename(nm, nm), oldaim, aim, nm); 129 cananian 1.1.2.1 130 cananian 1.1.2.1 } // end OPTIMIZE METHOD. 131 cananian 1.1.2.4 static void replace(Quad oldquad, Quad newquad, 132 cananian 1.1.2.4 AllocationInformation oldaim, 133 cananian 1.1.2.4 AllocationInformationMap newaim, TempMap tm) { 134 salcianu 1.7 oldquad.getFactory().getParent().notifyReplace(oldquad, newquad, tm); 135 cananian 1.1.2.4 Quad.replace(oldquad, newquad); 136 cananian 1.1.2.4 // update allocation properties, too. 137 cananian 1.1.2.4 if (newaim!=null && (oldquad instanceof ANEW||oldquad instanceof NEW)) 138 cananian 1.1.2.4 newaim.transfer(newquad, oldquad, tm, oldaim); 139 cananian 1.1.2.4 } 140 cananian 1.1.2.1 141 cananian 1.1.2.1 static class EraserVisitor extends LowQuadVisitor { 142 cananian 1.1.2.8 WorkSet W; 143 cananian 1.1.2.1 Set useful; 144 cananian 1.5 InvertibleMultiMap useMap; 145 cananian 1.1.2.1 NameMap nm; 146 cananian 1.5 EraserVisitor(WorkSet W, Set useful, InvertibleMultiMap useMap, NameMap nm) { 147 cananian 1.1.2.6 super(false/*non-strict*/); 148 cananian 1.1.2.8 this.W= W; this.useful= useful; this.useMap= useMap; this.nm= nm; 149 cananian 1.1.2.1 } 150 cananian 1.1.2.1 void unlink(Quad q) { 151 cananian 1.1.2.1 Edge before = q.prevEdge(0); 152 cananian 1.1.2.1 Edge after = q.nextEdge(0); 153 cananian 1.1.2.1 Quad.addEdge((Quad)before.from(), before.which_succ(), 154 cananian 1.1.2.1 (Quad)after.to(), after.which_pred() ); 155 cananian 1.5 useMap.invert().remove(q); 156 cananian 1.1.2.1 } 157 cananian 1.1.2.1 158 cananian 1.1.2.1 public void visit(Quad q) { 159 cananian 1.1.2.1 // generally, remove it if it's worthless. 160 cananian 1.1.2.1 if (useful.contains(q)) return; // safe. 161 cananian 1.1.2.1 // removing this statement could make its predecessor useless. 162 cananian 1.1.2.1 if (q.prev(0) instanceof CJMP) W.push(q.prev(0)); 163 cananian 1.1.2.1 // unlink with vigor. 164 cananian 1.3.2.1 assert q.next().length==1 && q.prev().length==1; 165 cananian 1.1.2.1 unlink(q); 166 cananian 1.1.2.1 } 167 cananian 1.1.2.1 public void visit(PHI q) { 168 cananian 1.1.2.1 // arity-1 phis are useless. 169 cananian 1.1.2.1 if (q.prev().length == 1) { 170 cananian 1.1.2.1 // make a pseudo-MOVE for every useful function in this useless phi. 171 cananian 1.1.2.1 for (int i=0; i<q.numPhis(); i++) 172 cananian 1.1.2.1 if (useful.contains(q.dst(i))) 173 cananian 1.1.2.1 for (int j=0; j<q.arity(); j++) 174 cananian 1.1.2.1 nm.map(q.dst(i), q.src(i,j)); 175 cananian 1.1.2.1 // could make a CJMP useless. 176 cananian 1.1.2.1 if (q.prev(0) instanceof CJMP) W.push(q.prev(0)); 177 cananian 1.1.2.1 // unlink it. (fun for the whole family) 178 cananian 1.1.2.1 unlink(q); 179 cananian 1.1.2.1 } else { 180 cananian 1.1.2.1 // check for unused functions in the phi. 181 cananian 1.1.2.1 for (int i=0; i < q.numPhis(); i++) { 182 cananian 1.1.2.1 if (useful.contains(q.dst(i))) continue; 183 cananian 1.1.2.1 // shrink the phi! (secret headhunter's ritual) 184 cananian 1.1.2.1 q.removePhi(i); 185 cananian 1.1.2.1 // decrement i so we're at the right place still; 186 cananian 1.1.2.1 i--; 187 cananian 1.1.2.1 } 188 cananian 1.1.2.1 // check for phis whose sources are identical 189 cananian 1.1.2.1 // and coalesce them. 190 cananian 1.1.2.1 phidup.clear(); 191 cananian 1.1.2.1 for (int i=0; i < q.numPhis(); i++) { 192 cananian 1.1.2.1 Temp[] src = q.src(i); 193 cananian 1.1.2.1 if (phidup.containsKey(src)) { // delete it! 194 cananian 1.1.2.1 int prev = ((Integer) phidup.get(src)).intValue(); 195 cananian 1.1.2.1 nm.map(q.dst(i), q.dst(prev)); 196 cananian 1.1.2.1 q.removePhi(i--); 197 cananian 1.1.2.8 // this could enable more merging in PHI/SIGMAs that 198 cananian 1.1.2.8 // use q.dst(i) or q.dst(prev) 199 cananian 1.1.2.8 W.addAll(useMap.getValues(q.dst(i))); 200 cananian 1.1.2.8 W.addAll(useMap.getValues(q.dst(prev))); 201 cananian 1.1.2.1 } else phidup.put(src, new Integer(i)); 202 cananian 1.1.2.1 } 203 cananian 1.1.2.1 } 204 cananian 1.1.2.1 } 205 cananian 1.1.2.1 private final SortedMap phidup = new TreeMap(new Comparator() { 206 cananian 1.1.2.1 public int compare(Object o1, Object o2) { 207 cananian 1.1.2.1 Temp[] ta1 = (Temp[])o1, ta2 = (Temp[])o2; 208 cananian 1.1.2.1 if (ta1.length!=ta2.length) return ta1.length-ta2.length; 209 cananian 1.1.2.1 for (int i=0; i<ta1.length; i++) { 210 cananian 1.1.2.1 int c = Default.comparator.compare(nm.tempMap(ta1[i]), 211 cananian 1.1.2.1 nm.tempMap(ta2[i])); 212 cananian 1.1.2.1 if (c!=0) return c; 213 cananian 1.1.2.1 } 214 cananian 1.1.2.1 return 0; 215 cananian 1.1.2.1 } 216 cananian 1.1.2.1 }); 217 cananian 1.1.2.1 218 cananian 1.1.2.1 public void visit(SIGMA q) { 219 cananian 1.1.2.1 // check for unused function in the sigma 220 cananian 1.1.2.1 L1: 221 cananian 1.1.2.1 for (int i=0; i < q.numSigmas(); i++) { 222 cananian 1.1.2.1 // if any dst is used, skip. 223 cananian 1.1.2.1 for (int j=0; j < q.arity(); j++) 224 cananian 1.1.2.1 if (useful.contains(q.dst(i,j))) continue L1; 225 cananian 1.1.2.1 // safe to delete. ERASER MAN appears. 226 cananian 1.1.2.1 // shrink the sigma function in our secret laboratory. 227 cananian 1.1.2.1 q.removeSigma(i); 228 cananian 1.1.2.1 // decrement index to keep us steady. 229 cananian 1.1.2.1 i--; 230 cananian 1.1.2.1 } 231 cananian 1.1.2.1 // find SIGMAs whose sources are identical, and coalesce them. 232 cananian 1.1.2.1 sigdup.clear(); 233 cananian 1.1.2.1 for (int i=0; i < q.numSigmas(); i++) { 234 cananian 1.1.2.1 Temp src = nm.tempMap(q.src(i)); 235 cananian 1.1.2.1 if (sigdup.containsKey(src)) { // delete it! 236 cananian 1.1.2.1 int prev = ((Integer) sigdup.get(src)).intValue(); 237 cananian 1.1.2.8 for (int j=0; j<q.arity(); j++) { 238 cananian 1.1.2.1 nm.map(q.dst(i,j), q.dst(prev,j)); 239 cananian 1.1.2.8 // this could enable more merging in PHI/SIGMAs that 240 cananian 1.1.2.8 // use q.dst(i,j) or q.dst(prev,j) 241 cananian 1.1.2.8 W.addAll(useMap.getValues(q.dst(i,j))); 242 cananian 1.1.2.8 W.addAll(useMap.getValues(q.dst(prev,j))); 243 cananian 1.1.2.8 } 244 cananian 1.1.2.1 q.removeSigma(i--); 245 cananian 1.1.2.1 } else sigdup.put(src, new Integer(i)); 246 cananian 1.1.2.1 } 247 cananian 1.1.2.1 } 248 cananian 1.1.2.1 private final SortedMap sigdup = new TreeMap(new Comparator() { 249 cananian 1.1.2.1 public int compare(Object o1, Object o2) { 250 cananian 1.1.2.1 Temp t1 = (Temp)o1, t2 = (Temp)o2; 251 cananian 1.1.2.1 return Default.comparator.compare(nm.tempMap(t1), 252 cananian 1.1.2.1 nm.tempMap(t2)); 253 cananian 1.1.2.1 } 254 cananian 1.1.2.1 }); 255 cananian 1.1.2.1 256 cananian 1.1.2.1 public void visit(CJMP q) { 257 cananian 1.1.2.1 if (q.next(0)==q.next(1) && !matchPS(q, (PHI)q.next(0))) { 258 cananian 1.1.2.1 // Mu-ha-ha-ha! KILL THE CJMP! 259 cananian 1.1.2.1 // make a pseudo-MOVE for every useful function in this useless sigma. 260 cananian 1.1.2.1 for (int i=0; i<q.numSigmas(); i++) 261 cananian 1.1.2.1 for (int j=0; j<q.arity(); j++) 262 cananian 1.1.2.1 if (useful.contains(q.dst(i,j))) 263 cananian 1.1.2.1 nm.map(q.dst(i,j), q.src(i)); 264 cananian 1.1.2.1 // removing this might make a preceding CJMP useless. 265 cananian 1.1.2.1 if (q.prev(0) instanceof CJMP) W.push(q.prev(0)); 266 cananian 1.1.2.1 // shrink the phi (and put it on the worklist) 267 cananian 1.1.2.1 ((PHI)q.next(0)).removePred(q.nextEdge(1).which_pred()); 268 cananian 1.1.2.1 W.push(q.next(0)); 269 cananian 1.1.2.1 // link out the CJMP 270 cananian 1.1.2.1 Quad.addEdge(q.prev(0), q.prevEdge(0).which_succ(), 271 cananian 1.1.2.1 q.next(0), q.nextEdge(0).which_pred()); 272 cananian 1.5 useMap.invert().remove(q); 273 cananian 1.1.2.1 } else { 274 cananian 1.1.2.1 // just shrink the functions. 275 cananian 1.1.2.1 visit((SIGMA)q); 276 cananian 1.1.2.1 } 277 cananian 1.1.2.1 } 278 cananian 1.1.2.1 // Determine if (useful) cjmp and phi args match. 279 cananian 1.1.2.1 boolean matchPS(CJMP cj, PHI ph) { 280 cananian 1.1.2.1 // a hashtable makes this easier. 281 cananian 1.1.2.1 PSdup.clear(); 282 cananian 1.1.2.1 for (int i=0; i<cj.numSigmas(); i++) 283 cananian 1.1.2.1 for (int j=0; j<cj.arity(); j++) 284 cananian 1.1.2.1 PSdup.put(nm.tempMap(cj.dst(i,j)), 285 cananian 1.1.2.1 nm.tempMap(cj.src(i))); 286 cananian 1.1.2.1 287 cananian 1.1.2.1 int which_pred0 = cj.nextEdge(0).which_pred(); 288 cananian 1.1.2.1 int which_pred1 = cj.nextEdge(1).which_pred(); 289 cananian 1.1.2.1 for (int i=0; i<ph.numPhis(); i++) { 290 cananian 1.1.2.1 if (!useful.contains(nm.tempMap(ph.dst(i)))) 291 cananian 1.1.2.1 continue; // not useful, skip. 292 cananian 1.1.2.1 if (PSdup.get(nm.tempMap(ph.src(i,which_pred0))) != 293 cananian 1.1.2.1 PSdup.get(nm.tempMap(ph.src(i,which_pred1))) ) 294 cananian 1.1.2.1 return true; // cjmp matters, either in sig or phi. 295 cananian 1.1.2.1 } 296 cananian 1.1.2.1 return false; // not useful! 297 cananian 1.1.2.1 } 298 cananian 1.1.2.1 private final Map PSdup = new HashMap(); 299 cananian 1.1.2.1 } 300 cananian 1.1.2.1 301 cananian 1.1.2.1 static class NameMap implements TempMap { 302 cananian 1.1.2.1 Map h = new HashMap(); 303 cananian 1.1.2.1 public Temp tempMap(Temp t) { 304 cananian 1.1.2.1 while (h.containsKey(t)) 305 cananian 1.1.2.1 t = (Temp) h.get(t); 306 cananian 1.1.2.1 return t; 307 cananian 1.1.2.1 } 308 cananian 1.1.2.1 public void map(Temp Told, Temp Tnew) { h.put(Told, Tnew); } 309 cananian 1.1.2.1 public String toString() { return h.toString(); } 310 cananian 1.1.2.1 } 311 cananian 1.1.2.1 312 cananian 1.1.2.1 static class UsefulVisitor extends LowQuadVisitor { 313 cananian 1.1.2.1 Worklist W; 314 cananian 1.1.2.1 Set useful; 315 cananian 1.1.2.1 Map defMap; 316 cananian 1.1.2.1 NameMap nm; 317 cananian 1.1.2.1 // maps cjmp targets past useless cjmps/phis 318 cananian 1.1.2.1 Map jmpMap = new HashMap(); 319 cananian 1.1.2.1 // maps phi sources past useless cjmps/phis 320 cananian 1.1.2.1 Map phiMap = new HashMap(); 321 cananian 1.1.2.1 322 cananian 1.1.2.1 UsefulVisitor(Worklist W, Set useful, Map defMap, NameMap nm) { 323 cananian 1.1.2.6 super(false/*non-strict*/); 324 cananian 1.1.2.1 this.W = W; 325 cananian 1.1.2.1 this.useful = useful; 326 cananian 1.1.2.1 this.defMap = defMap; 327 cananian 1.1.2.1 this.nm = nm; 328 cananian 1.1.2.1 } 329 cananian 1.1.2.1 void markUseful(Quad q) { 330 cananian 1.1.2.1 if (useful.contains(q)) return; // no change. 331 cananian 1.1.2.1 useful.add(q); 332 cananian 1.1.2.1 // all variables used by a useful quad are useful. 333 cananian 1.1.2.1 Temp u[] = q.use(); 334 cananian 1.1.2.1 for (int i=0; i<u.length; i++) 335 cananian 1.1.2.1 markUseful(u[i]); 336 cananian 1.1.2.1 } 337 cananian 1.1.2.1 void markUseful(Temp t) { 338 cananian 1.1.2.1 if (useful.contains(t)) return; // no change. 339 cananian 1.1.2.1 useful.add(t); 340 cananian 1.1.2.1 // the quad defining this temp is now useful, too. 341 cananian 1.1.2.1 if (defMap.containsKey(t)) // undefined vars possible. 342 cananian 1.1.2.1 W.push(defMap.get(t)); 343 cananian 1.1.2.1 } 344 cananian 1.1.2.1 public void visit(Quad q) { 345 cananian 1.1.2.1 boolean usefound = false; 346 cananian 1.1.2.1 // by default, a quad is useful iff what it defines is useful. 347 cananian 1.1.2.1 Temp d[] = q.def(); 348 cananian 1.1.2.1 for (int i=0; i<d.length; i++) 349 cananian 1.1.2.1 if (useful.contains(d[i])) 350 cananian 1.1.2.1 usefound = true; 351 cananian 1.1.2.1 // statements that define no variables are safe, however. 352 cananian 1.1.2.1 if (d.length==0) usefound = true; 353 cananian 1.1.2.1 // if it's useful, mark it. 354 cananian 1.1.2.1 if (usefound) 355 cananian 1.1.2.1 markUseful(q); 356 cananian 1.1.2.1 } 357 cananian 1.1.2.1 358 cananian 1.1.2.1 public void visit(ARRAYINIT q) { // always useful. 359 cananian 1.1.2.1 markUseful(q); 360 cananian 1.1.2.1 } 361 cananian 1.1.2.1 362 cananian 1.1.2.1 public void visit(PSET q) { 363 cananian 1.1.2.1 // Pointer writes may be useful 364 cananian 1.1.2.1 markUseful(q); 365 cananian 1.1.2.1 } 366 cananian 1.1.2.1 367 cananian 1.1.2.3 public void visit(PCALL q) { 368 cananian 1.1.2.3 // all PCALLs are useful (may have side-effects) 369 cananian 1.1.2.3 useful.add(q); 370 cananian 1.1.2.3 // any variables used are useful. 371 cananian 1.1.2.3 for (int i=0; i<q.paramsLength(); i++) 372 cananian 1.1.2.3 markUseful(q.params(i)); 373 cananian 1.1.2.3 markUseful(q.retex()); 374 bdemsky 1.1.2.5 markUseful(q.ptr()); 375 cananian 1.1.2.3 if (q.retval()!=null) markUseful(q.retval()); 376 cananian 1.1.2.3 // process sigmas normally 377 cananian 1.1.2.3 visit((SIGMA)q); 378 cananian 1.1.2.3 } 379 cananian 1.1.2.3 public void visit(CALL q) { 380 cananian 1.1.2.3 // all CALLs are useful (may have side-effects) 381 cananian 1.1.2.3 useful.add(q); 382 cananian 1.1.2.3 // any variables used are useful. 383 cananian 1.1.2.3 for (int i=0; i<q.paramsLength(); i++) 384 cananian 1.1.2.3 markUseful(q.params(i)); 385 cananian 1.1.2.3 markUseful(q.retex()); 386 cananian 1.1.2.3 if (q.retval()!=null) markUseful(q.retval()); 387 cananian 1.1.2.3 // process sigmas normally 388 cananian 1.1.2.3 visit((SIGMA)q); 389 cananian 1.1.2.3 } 390 cananian 1.1.2.1 public void visit(CJMP q) { 391 cananian 1.1.2.1 // assume all CJMPs are useful (we'll remove useless ones later) 392 cananian 1.1.2.1 useful.add(q); 393 cananian 1.1.2.1 // if this is useful, the condition is useful 394 cananian 1.1.2.1 markUseful(q.test()); 395 cananian 1.1.2.1 // process sigmas normally. 396 cananian 1.1.2.1 visit((SIGMA)q); 397 cananian 1.1.2.1 } 398 cananian 1.1.2.1 public void visit(FOOTER q) { // always useful. 399 cananian 1.1.2.1 markUseful(q); 400 cananian 1.1.2.1 } 401 cananian 1.1.2.1 public void visit(HANDLER q) { // ACK! never should find. 402 cananian 1.3.2.1 assert false : "DeadCode doesn't work with HANDLERs."; 403 cananian 1.1.2.1 } 404 cananian 1.1.2.1 public void visit(HEADER q) { // always useful. 405 cananian 1.1.2.1 markUseful(q); 406 cananian 1.1.2.1 } 407 cananian 1.1.2.1 public void visit(METHOD q) { // always useful. 408 cananian 1.1.2.1 markUseful(q); 409 cananian 1.1.2.1 } 410 cananian 1.1.2.1 public void visit(MONITORENTER q) { // always useful. 411 cananian 1.1.2.1 markUseful(q); 412 cananian 1.1.2.1 } 413 cananian 1.1.2.1 public void visit(MONITOREXIT q) { // always useful. 414 cananian 1.1.2.1 markUseful(q); 415 cananian 1.1.2.1 } 416 cananian 1.1.2.1 public void visit(MOVE q) { // moves are never useful (add to rename map) 417 cananian 1.1.2.1 if (useful.contains(q.dst())) { 418 cananian 1.1.2.1 markUseful(q.src()); 419 cananian 1.1.2.1 nm.map(q.dst(), q.src()); 420 cananian 1.1.2.1 } 421 cananian 1.1.2.1 } 422 cananian 1.1.2.1 public void visit(NOP q) { // never useful. 423 cananian 1.1.2.1 } 424 cananian 1.1.2.1 public void visit(PHI q) { 425 cananian 1.1.2.1 // Assume all phis are useful (will remove arity-1 phis later) 426 cananian 1.1.2.1 useful.add(q); 427 cananian 1.1.2.1 // check the individual phi functions for usefulness. 428 cananian 1.1.2.1 for (int i=0; i < q.numPhis(); i++) 429 cananian 1.1.2.1 if (useful.contains(q.dst(i))) 430 cananian 1.1.2.1 for (int j=0; j<q.arity(); j++) 431 cananian 1.1.2.1 markUseful(q.src(i,j)); 432 cananian 1.1.2.1 } 433 cananian 1.1.2.1 public void visit(RETURN q) { // always useful. 434 cananian 1.1.2.1 markUseful(q); 435 cananian 1.1.2.1 } 436 cananian 1.1.2.1 public void visit(SET q) { // always useful. 437 cananian 1.1.2.1 markUseful(q); 438 cananian 1.1.2.1 } 439 cananian 1.1.2.1 public void visit(SIGMA q) { 440 cananian 1.1.2.1 // Sigmas are useful iff one of the definitions is useful. 441 cananian 1.1.2.1 for (int i=0; i<q.numSigmas(); i++) { 442 cananian 1.1.2.1 if (useful.contains(q.src(i))) continue; //skip already useful sigs. 443 cananian 1.1.2.1 for (int j=0; j<q.arity(); j++) 444 cananian 1.1.2.1 if (useful.contains(q.dst(i,j))) // this one's (newly) useful. 445 cananian 1.1.2.1 markUseful(q.src(i)); 446 cananian 1.1.2.1 } 447 cananian 1.1.2.1 } 448 cananian 1.1.2.1 public void visit(SWITCH q) { 449 cananian 1.1.2.1 // I'm too lazy to see if the switch actually does anything, so assume 450 cananian 1.1.2.7 // it's always useful. 451 cananian 1.1.2.7 useful.add(q); 452 cananian 1.1.2.7 markUseful(q.index()); 453 cananian 1.1.2.7 visit((SIGMA)q); 454 cananian 1.1.2.7 } 455 cananian 1.1.2.7 public void visit(TYPESWITCH q) { 456 cananian 1.1.2.7 // I'm too lazy to see if the typeswitch actually does anything, so assume 457 cananian 1.1.2.1 // it's always useful. 458 cananian 1.1.2.1 useful.add(q); 459 cananian 1.1.2.1 markUseful(q.index()); 460 cananian 1.1.2.1 visit((SIGMA)q); 461 cananian 1.1.2.1 } 462 cananian 1.1.2.1 public void visit(THROW q) { // always useful. 463 cananian 1.1.2.1 markUseful(q); 464 cananian 1.1.2.1 } 465 cananian 1.1.2.1 } 466 cananian 1.2 }