1 cananian 1.1.2.1 // Unreachable.java, created Wed Feb 24 20:03:06 1999 by cananian
  2 cananian 1.1.2.1 // Copyright (C) 1999 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 package harpoon.Analysis.Quads;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.3 import harpoon.Analysis.Maps.Derivation;
  7 cananian 1.1.2.3 
  8 cananian 1.1.2.3 import harpoon.ClassFile.HCode;
  9 cananian 1.1.2.3 
 10 cananian 1.1.2.3 import harpoon.IR.LowQuad.DerivationMap;
 11 cananian 1.1.2.2 import harpoon.IR.LowQuad.LowQuadVisitor;
 12 cananian 1.1.2.1 import harpoon.IR.Quads.Edge;
 13 cananian 1.1.2.1 import harpoon.IR.Quads.Quad;
 14 cananian 1.1.2.1 import harpoon.IR.Quads.FOOTER;
 15 cananian 1.1.2.1 import harpoon.IR.Quads.HEADER;
 16 cananian 1.1.2.3 import harpoon.IR.Quads.MOVE;
 17 cananian 1.1.2.1 import harpoon.IR.Quads.PHI;
 18 cananian 1.1.2.1 
 19 cananian 1.1.2.3 import harpoon.Temp.Temp;
 20 cananian 1.1.2.3 
 21 cananian 1.1.2.1 import harpoon.Util.Util;
 22 cananian 1.6     import net.cscott.jutil.WorkSet;
 23 cananian 1.1.2.1 
 24 cananian 1.1.2.1 import java.util.ArrayList;
 25 cananian 1.1.2.1 import java.util.Collections;
 26 cananian 1.1.2.1 import java.util.HashSet;
 27 cananian 1.1.2.1 import java.util.Iterator;
 28 cananian 1.1.2.1 import java.util.List;
 29 cananian 1.1.2.1 import java.util.Set;
 30 cananian 1.1.2.1 import java.util.Stack;
 31 cananian 1.1.2.1 /**
 32 cananian 1.1.2.1  * <code>Unreachable</code> gets rid of unreachable code.
 33 cananian 1.1.2.1  * <b>CAUTION</b>: it modifies code in-place.
 34 cananian 1.1.2.1  * 
 35 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 36 cananian 1.6      * @version $Id: Unreachable.java,v 1.6 2004/02/08 01:53:14 cananian Exp $
 37 cananian 1.1.2.1  */
 38 cananian 1.1.2.1 public abstract class Unreachable  {
 39 cananian 1.1.2.1 
 40 cananian 1.1.2.3     /** Prunes unreachable code from a quad graph in-place.  Also updates
 41 cananian 1.1.2.3      *  the derivation for the <code>HCode</code>, if present. */
 42 cananian 1.5         public static final void prune(harpoon.IR.Quads.Code hc) {
 43 cananian 1.1.2.3         // fetch or invalidate mutable derivation information.
 44 cananian 1.5             DerivationMap<Quad> dm = null;
 45 cananian 1.5             if (hc.getDerivation()!=null) {
 46 cananian 1.1.2.3             harpoon.IR.LowQuad.Code c = (harpoon.IR.LowQuad.Code) hc;
 47 cananian 1.1.2.3             if (c.getDerivation() instanceof DerivationMap)
 48 cananian 1.5                     dm = (DerivationMap<Quad>) c.getDerivation();
 49 cananian 1.1.2.3             else {
 50 cananian 1.1.2.3                 //c.setDerivation(null); // clear derivation information.
 51 cananian 1.3.2.1                 assert false; // can't invalidate, can't update, abort!
 52 cananian 1.1.2.3             }
 53 cananian 1.1.2.3         }
 54 cananian 1.5             prune(hc.getRootElement(), dm);
 55 cananian 1.1.2.3     }
 56 cananian 1.1.2.3     /** Prunes unreachable code *without updating the derivation*. */
 57 cananian 1.1.2.1     public static final void prune(HEADER header) {
 58 cananian 1.1.2.3         prune(header, null);
 59 cananian 1.1.2.3     }
 60 cananian 1.1.2.3     /** private pruning method. */
 61 cananian 1.5         private static final void prune(HEADER header, DerivationMap<Quad> dm) {
 62 cananian 1.1.2.3         // okay, now find the unreachable code and prune it.
 63 cananian 1.5             Set<Quad> reachable = (new ReachabilityVisitor(header)).reachableSet();
 64 cananian 1.1.2.3         (new PruningVisitor(reachable, dm)).prune();
 65 cananian 1.1.2.1     }
 66 cananian 1.1.2.1 
 67 cananian 1.1.2.1     /** Class to do reachability analysis. */
 68 cananian 1.1.2.2     static private class ReachabilityVisitor extends LowQuadVisitor {
 69 cananian 1.5             final Set<Quad> reachable = new HashSet<Quad>();
 70 cananian 1.5             WorkSet<Quad> todo = new WorkSet<Quad>();
 71 cananian 1.1.2.1         ReachabilityVisitor(HEADER h) {
 72 cananian 1.1.2.2             super(false); /* not strict low quad */
 73 cananian 1.1.2.1             todo.add(h);
 74 cananian 1.1.2.1             while (!todo.isEmpty())
 75 cananian 1.5                     todo.pop().accept(this);
 76 cananian 1.1.2.1 
 77 cananian 1.1.2.1             todo = null; // free space.
 78 cananian 1.1.2.1         }
 79 cananian 1.5             public Set<Quad> reachableSet() { return reachable; }
 80 cananian 1.1.2.1 
 81 cananian 1.1.2.1         public void visit(Quad q) {
 82 cananian 1.1.2.1             reachable.add(q);
 83 cananian 1.1.2.1             Quad[] nxt = q.next();
 84 cananian 1.1.2.1             for (int i=0; i<nxt.length; i++)
 85 cananian 1.1.2.1                 if (!reachable.contains(nxt[i]))
 86 cananian 1.1.2.1                     todo.add(nxt[i]);
 87 cananian 1.1.2.1         }
 88 cananian 1.1.2.1     }
 89 cananian 1.1.2.1 
 90 cananian 1.1.2.1     /** Class to do the pruning of unreachable edges. */
 91 cananian 1.1.2.2     static private class PruningVisitor extends LowQuadVisitor {
 92 cananian 1.5             final Set<Quad> reachable;
 93 cananian 1.5             final DerivationMap<Quad> dm;
 94 cananian 1.5             PruningVisitor(Set<Quad> reachable, DerivationMap<Quad> dm) {
 95 cananian 1.1.2.2             super(false); /* not strict low quad */
 96 cananian 1.1.2.2             this.reachable = reachable;
 97 cananian 1.1.2.3             this.dm = dm;
 98 cananian 1.1.2.2         }
 99 cananian 1.1.2.1         void prune() {
100 cananian 1.1.2.1             // dump the original live elements into a list.
101 cananian 1.5                 List<Quad> l = new ArrayList<Quad>(reachable);
102 cananian 1.5                 for (Iterator<Quad> it=l.iterator(); it.hasNext(); )
103 cananian 1.5                     it.next().accept(this);
104 cananian 1.1.2.1         }
105 cananian 1.1.2.1         public void visit(Quad q) { /* do nothing. */ }
106 cananian 1.1.2.1         public void visit(PHI q) {
107 cananian 1.1.2.1             // remove unused inputs to PHI.
108 cananian 1.1.2.3             PHI oldphi = q;
109 cananian 1.1.2.1             for (int i=q.prevLength()-1; i>=0; i--)
110 cananian 1.1.2.1                 if (!reachable.contains(q.prev(i)))
111 cananian 1.1.2.1                     q = q.shrink(i);
112 cananian 1.1.2.3             if (oldphi != q) { // update derivation/make reachable
113 cananian 1.1.2.3                 if (dm!=null) updateDM(oldphi, q);
114 cananian 1.1.2.3                 reachable.add(q);
115 cananian 1.1.2.3             }
116 cananian 1.1.2.1                 
117 cananian 1.1.2.1             // if it shrinks too small, then remove it.
118 cananian 1.1.2.3             if (q.arity()==1) { // make arity-1 PHI into MOVEs.
119 cananian 1.1.2.1                 Edge in = q.prevEdge(0), out = q.nextEdge(0);
120 cananian 1.5                     Quad header = in.from();
121 cananian 1.1.2.3                 int which_succ = in.which_succ();
122 cananian 1.1.2.3                 for (int i=0; i<q.numPhis(); i++) {
123 cananian 1.1.2.3                     MOVE m=new MOVE(q.getFactory(), q, q.dst(i), q.src(i, 0));
124 cananian 1.1.2.3                     Quad.addEdge(header, which_succ, m, 0);
125 cananian 1.1.2.3                     header = m; which_succ = 0;
126 cananian 1.1.2.3                     reachable.add(m);
127 cananian 1.1.2.3                     if (dm!=null) dm.update(q, q.dst(i), m, m.dst());
128 cananian 1.1.2.3                 }
129 cananian 1.1.2.3                 Quad.addEdge(header, which_succ,
130 cananian 1.1.2.1                              (Quad)out.to(), out.which_pred());
131 cananian 1.1.2.3             }
132 cananian 1.1.2.1         }
133 cananian 1.1.2.1         public void visit(FOOTER q) {
134 cananian 1.1.2.1             // remove unused inputs to footer.
135 cananian 1.1.2.1             for (int i=q.prevLength()-1; i>=0; i--)
136 cananian 1.1.2.1                 if (!reachable.contains(q.prev(i)))
137 cananian 1.1.2.1                     q = q.remove(i);
138 cananian 1.1.2.1 
139 cananian 1.1.2.1             // make sure new quad is marked as reachable.
140 cananian 1.1.2.1             reachable.add(q);
141 cananian 1.1.2.3         }
142 cananian 1.1.2.3 
143 cananian 1.1.2.3         private void updateDM(Quad oldq, Quad newq) {
144 cananian 1.1.2.3             // transfer derivations of temps defined in newq
145 cananian 1.1.2.3             Temp[] defs = newq.def();
146 cananian 1.1.2.3             for (int i=0; i<defs.length; i++)
147 cananian 1.1.2.3                 dm.update(oldq, defs[i], newq, defs[i]);
148 cananian 1.1.2.3             // clear out any left over derivations from oldq
149 cananian 1.1.2.3             defs = oldq.def();
150 cananian 1.1.2.3             for (int i=0; i<defs.length; i++)
151 cananian 1.1.2.3                 dm.remove(oldq, defs[i]);
152 cananian 1.1.2.1         }
153 cananian 1.1.2.1     }
154 cananian 1.2     }