1 cananian 1.1 // QuadFlowGraph.java, created Fri May  9 18:34:48 2003 by cananian
  2 cananian 1.1 // Copyright (C) 2003 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1 package harpoon.Analysis.Companions;
  5 cananian 1.1 
  6 cananian 1.2 import harpoon.IR.Quads.CALL;
  7 cananian 1.2 import harpoon.IR.Quads.CJMP;
  8 cananian 1.1 import harpoon.IR.Quads.PHI;
  9 cananian 1.1 import harpoon.IR.Quads.Quad;
 10 cananian 1.1 import harpoon.IR.Quads.SIGMA;
 11 cananian 1.2 import harpoon.IR.Quads.SWITCH;
 12 cananian 1.2 import harpoon.IR.Quads.TYPESWITCH;
 13 cananian 1.2 import harpoon.Temp.Temp;
 14 cananian 1.1 import harpoon.Util.Collections.AbstractGraph;
 15 cananian 1.3 import net.cscott.jutil.WorkSet;
 16 cananian 1.2 import java.util.ArrayList;
 17 cananian 1.2 import java.util.Arrays;
 18 cananian 1.2 import java.util.Collection;
 19 cananian 1.2 import java.util.Collections;
 20 cananian 1.1 import java.util.HashMap;
 21 cananian 1.1 import java.util.Iterator;
 22 cananian 1.2 import java.util.List;
 23 cananian 1.1 import java.util.Map;
 24 cananian 1.1 /**
 25 cananian 1.1  * <code>QuadFlowGraph</code> is an expanded flow graphs for Quads, where
 26 cananian 1.1  * additional nodes are added before PHI and after SIGMA nodes to make the
 27 cananian 1.1  * dataflow corresponding to the phi and sigma functions easier to express.
 28 cananian 1.1  * Move operations corresponding to a PHI (SIGMA) can now take place
 29 cananian 1.1  * conceptually before (after) the node, on the incoming (outgoing) edge.
 30 cananian 1.1  * 
 31 cananian 1.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 32 cananian 1.3  * @version $Id: QuadFlowGraph.java,v 1.3 2004/02/08 01:50:55 cananian Exp $
 33 cananian 1.1  */
 34 cananian 1.1 public class QuadFlowGraph extends AbstractGraph<QNode,QEdge> {
 35 cananian 1.1     
 36 cananian 1.1     /** Creates a <code>QuadFlowGraph</code>. */
 37 cananian 1.1     public QuadFlowGraph(harpoon.IR.Quads.Code c) {
 38 cananian 1.1         Map<Quad,QNode> map = new HashMap<Quad,QNode>();
 39 cananian 1.1         WorkSet<harpoon.IR.Quads.Edge> ws=new WorkSet<harpoon.IR.Quads.Edge>();
 40 cananian 1.1         // make nodes for all Quads.
 41 cananian 1.1         for (Iterator<Quad> it=c.getElementsI(); it.hasNext(); ) {
 42 cananian 1.1             Quad q = it.next();
 43 cananian 1.1             QNode qn = new NormalNode(this, q);
 44 cananian 1.1             map.put(q, qn);
 45 cananian 1.1             addNode(qn);
 46 cananian 1.1             ws.addAll(q.edgeC());
 47 cananian 1.1         }
 48 cananian 1.1         // make QEdges for all Edges
 49 cananian 1.1         while (!ws.isEmpty()) {
 50 cananian 1.1             harpoon.IR.Quads.Edge e = ws.removeFirst();
 51 cananian 1.1             QNode fr = map.get(e.from());
 52 cananian 1.1             if (fr.baseQuad() instanceof SIGMA) { // split Sigma edge
 53 cananian 1.1                 QNode qn = new SigmaExitNode(this, (SIGMA) fr.baseQuad(),
 54 cananian 1.1                                              e.which_succ());
 55 cananian 1.1                 addNode(qn);
 56 cananian 1.1                 addEdge(fr, qn);
 57 cananian 1.1                 fr = qn;
 58 cananian 1.1             }
 59 cananian 1.1             QNode to = map.get(e.to());
 60 cananian 1.1             if (to.baseQuad() instanceof PHI) { // split phi edge
 61 cananian 1.1                 QNode qn = new PhiEntranceNode(this, (PHI) to.baseQuad(),
 62 cananian 1.1                                                e.which_pred());
 63 cananian 1.1                 addNode(qn);
 64 cananian 1.1                 addEdge(qn, to);
 65 cananian 1.1                 to = qn;
 66 cananian 1.1             }
 67 cananian 1.1             addEdge(fr, to);
 68 cananian 1.1         }
 69 cananian 1.1         // done!
 70 cananian 1.1     }
 71 cananian 1.1     public QEdge addEdge(QNode from, QNode to) {
 72 cananian 1.1         QEdge qe = new QEdge(from, to);
 73 cananian 1.1         this.addEdge(qe);
 74 cananian 1.1         return qe;
 75 cananian 1.1     }
 76 cananian 1.1 }
 77 cananian 1.1 // Bug in JSR-14 compiler prevents these from being inner classes, as they
 78 cananian 1.1 // ought be.
 79 cananian 1.1 /** A <code>QNode</code> is an element of the <code>QuadFlowGraph</code>.
 80 cananian 1.1  *  Most <code>QNode</code> correspond to <code>Quad</code>s in the underlying
 81 cananian 1.1  *  flowgraph (these are instances of the <code>QNode</code> subclass
 82 cananian 1.1  *  <code>NormalNode</code>, but there are also <code>QNode</code>s
 83 cananian 1.1  *  representing artificial nodes before <code>PHI</code>s
 84 cananian 1.1  *  (<code>PhiEntranceNode</code>) and after <code>SIGMA</code>s
 85 cananian 1.1  *  (<code>SigmaExitNode</code>).  Because of this, the <code>QNode</code>
 86 cananian 1.1  *  may have different edges than the underlying <code>Quad</code>
 87 cananian 1.1  *  returned by the <code>baseQuad()</code> method.
 88 cananian 1.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 89 cananian 1.3  * @version $Id: QuadFlowGraph.java,v 1.3 2004/02/08 01:50:55 cananian Exp $
 90 cananian 1.1  */
 91 cananian 1.1 abstract class QNode extends AbstractGraph.Node<QNode,QEdge> {
 92 cananian 1.1     QNode(QuadFlowGraph parent) { super(parent); }
 93 cananian 1.1     abstract Quad baseQuad();
 94 cananian 1.1     abstract boolean isPhiEntrance();
 95 cananian 1.1     abstract boolean isSigmaExit();
 96 cananian 1.1     abstract int whichEdge();
 97 cananian 1.2     abstract Collection<Temp> useC();
 98 cananian 1.2     abstract Collection<Temp> defC();
 99 cananian 1.1 }
100 cananian 1.1 /** A <code>NormalNode</code> wraps an arbitrary <code>Quad</code> and
101 cananian 1.1  *  corresponds directly to a node in the underlying flow graph,
102 cananian 1.1  *  although the edges may differ if the underlying quad is a
103 cananian 1.1  *  <code>PHI</code> or <code>SIGMA</code>.
104 cananian 1.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
105 cananian 1.3  * @version $Id: QuadFlowGraph.java,v 1.3 2004/02/08 01:50:55 cananian Exp $
106 cananian 1.1  */
107 cananian 1.1 final class NormalNode extends QNode {
108 cananian 1.1     final Quad baseQuad;
109 cananian 1.1     NormalNode(QuadFlowGraph parent, Quad baseQuad) {
110 cananian 1.1         super(parent);
111 cananian 1.1         this.baseQuad = baseQuad;
112 cananian 1.1     }
113 cananian 1.1     Quad baseQuad() { return baseQuad; }
114 cananian 1.1     boolean isPhiEntrance() { return false; }
115 cananian 1.1     boolean isSigmaExit() { return false; }
116 cananian 1.1     int whichEdge() { throw new RuntimeException("a normal quad"); }
117 cananian 1.2     Collection<Temp> useC() {
118 cananian 1.2         if (baseQuad instanceof PHI)
119 cananian 1.2             return Collections.EMPTY_LIST;
120 cananian 1.2         if (baseQuad instanceof CALL)
121 cananian 1.2             return Arrays.asList(((CALL)baseQuad).params());
122 cananian 1.2         if (baseQuad instanceof CJMP)
123 cananian 1.2             return Collections.singletonList(((CJMP)baseQuad).test());
124 cananian 1.2         if (baseQuad instanceof SWITCH)
125 cananian 1.2             return Collections.singletonList(((SWITCH)baseQuad).index());
126 cananian 1.2         if (baseQuad instanceof TYPESWITCH)
127 cananian 1.2             return Collections.singletonList(((TYPESWITCH)baseQuad).index());
128 cananian 1.2         return baseQuad.useC();
129 cananian 1.2     }
130 cananian 1.2     Collection<Temp> defC() {
131 cananian 1.2         if (baseQuad instanceof CALL) {
132 cananian 1.2             CALL call = (CALL) baseQuad;
133 cananian 1.2             List<Temp> defs = new ArrayList<Temp>(2);
134 cananian 1.2             if (call.retval()!=null) defs.add(call.retval());
135 cananian 1.2             if (call.retex()!=null) defs.add(call.retex());
136 cananian 1.2             return defs;
137 cananian 1.2         }
138 cananian 1.2         if (baseQuad instanceof PHI ||
139 cananian 1.2             baseQuad instanceof SIGMA)
140 cananian 1.2             return Collections.EMPTY_LIST;
141 cananian 1.2         return baseQuad.defC();
142 cananian 1.2     }
143 cananian 1.1 }
144 cananian 1.1 /** A <code>PhiEntranceNode</code> is an artificial node in the
145 cananian 1.1  * <code>QuadFlowGraph</code> which is inserted on the incoming
146 cananian 1.1  * edge of a <code>PHI</code>.  It reports its <code>baseQuad()</code>
147 cananian 1.1  * as the affiliated <code>PHI</code>.
148 cananian 1.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
149 cananian 1.3  * @version $Id: QuadFlowGraph.java,v 1.3 2004/02/08 01:50:55 cananian Exp $
150 cananian 1.1  */
151 cananian 1.1 final class PhiEntranceNode extends QNode {
152 cananian 1.1     final PHI baseQuad;  final int whichEdge;
153 cananian 1.1     PhiEntranceNode(QuadFlowGraph parent, PHI baseQuad, int whichEdge) {
154 cananian 1.1         super(parent);
155 cananian 1.1         this.baseQuad = baseQuad; this.whichEdge = whichEdge;
156 cananian 1.1     }
157 cananian 1.1     PHI baseQuad() { return baseQuad; }
158 cananian 1.1     boolean isPhiEntrance() { return true; }
159 cananian 1.1     boolean isSigmaExit() { return false; }
160 cananian 1.1     int whichEdge() { return whichEdge; }
161 cananian 1.2     List<Temp> defC() {
162 cananian 1.2         List<Temp> defs = new ArrayList<Temp>(baseQuad.numPhis());
163 cananian 1.2         for (int i=0; i<baseQuad.numPhis(); i++)
164 cananian 1.2             defs.add(baseQuad.dst(i));
165 cananian 1.2         return defs;
166 cananian 1.2     }
167 cananian 1.2     List<Temp> useC() {
168 cananian 1.2         List<Temp> uses = new ArrayList<Temp>(baseQuad.numPhis());
169 cananian 1.2         for (int i=0; i<baseQuad.numPhis(); i++)
170 cananian 1.2             uses.add(baseQuad.src(i, whichEdge));
171 cananian 1.2         return uses;
172 cananian 1.2     }
173 cananian 1.1 }
174 cananian 1.1 /** A <code>SigmaExitNode</code> is an artificial node in the
175 cananian 1.1  * <code>QuadFlowGraph</code> which is inserted on the outgoing
176 cananian 1.1  * edge of a <code>SIGMA</code>.  It reports its <code>baseQuad()</code>
177 cananian 1.1  * as the affiliated <code>SIGMA</code>.
178 cananian 1.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
179 cananian 1.3  * @version $Id: QuadFlowGraph.java,v 1.3 2004/02/08 01:50:55 cananian Exp $
180 cananian 1.1  */
181 cananian 1.1 final class SigmaExitNode extends QNode {
182 cananian 1.1     final SIGMA baseQuad;  final int whichEdge;
183 cananian 1.1     SigmaExitNode(QuadFlowGraph parent, SIGMA baseQuad, int whichEdge) {
184 cananian 1.1         super(parent);
185 cananian 1.1         this.baseQuad = baseQuad; this.whichEdge = whichEdge;
186 cananian 1.1     }
187 cananian 1.1     SIGMA baseQuad() { return baseQuad; }
188 cananian 1.1     boolean isPhiEntrance() { return false; }
189 cananian 1.1     boolean isSigmaExit() { return true; }
190 cananian 1.1     int whichEdge() { return whichEdge; }
191 cananian 1.2     List<Temp> defC() {
192 cananian 1.2         List<Temp> defs = new ArrayList<Temp>(baseQuad.numSigmas());
193 cananian 1.2         for (int i=0; i<baseQuad.numSigmas(); i++)
194 cananian 1.2             defs.add(baseQuad.dst(i, whichEdge));
195 cananian 1.2         return defs;
196 cananian 1.2     }
197 cananian 1.2     List<Temp> useC() {
198 cananian 1.2         List<Temp> uses = new ArrayList<Temp>(baseQuad.numSigmas());
199 cananian 1.2         for (int i=0; i<baseQuad.numSigmas(); i++)
200 cananian 1.2             uses.add(baseQuad.src(i));
201 cananian 1.2         return uses;
202 cananian 1.2     }
203 cananian 1.1 }
204 cananian 1.1 /**
205 cananian 1.1  * <code>QEdge</code> represents edges between <code>QNode</code>
206 cananian 1.1  * objects.  They usually correspond to <code>Quad.Edge</code> object,
207 cananian 1.1  * but not in the case of inserted <code>PhiEntranceNode</code>s and
208 cananian 1.1  * <code>SigmaExitNode</code>s.
209 cananian 1.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
210 cananian 1.3  * @version $Id: QuadFlowGraph.java,v 1.3 2004/02/08 01:50:55 cananian Exp $
211 cananian 1.1  */
212 cananian 1.1 final class QEdge extends AbstractGraph.Edge<QNode,QEdge> {
213 cananian 1.1     QEdge(QNode from, QNode to) { super(from, to); }
214 cananian 1.1 }