1 cananian 1.1.2.1 // SSIToSSA.java, created Wed May 31 16:35:30 2000 by cananian
  2 cananian 1.1.2.1 // Copyright (C) 2000 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.IR.Quads;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.1 import harpoon.Analysis.AllocationInformationMap;
  7 cananian 1.1.2.1 import harpoon.Analysis.Maps.AllocationInformation;
  8 cananian 1.1.2.1 import harpoon.Analysis.Maps.Derivation;
  9 cananian 1.1.2.1 import harpoon.ClassFile.HCode;
 10 cananian 1.1.2.1 import harpoon.ClassFile.HCodeEdge;
 11 cananian 1.1.2.1 import harpoon.ClassFile.HCodeElement;
 12 cananian 1.1.2.3 import harpoon.IR.Quads.Code;
 13 cananian 1.1.2.1 import harpoon.IR.LowQuad.DerivationMap;
 14 cananian 1.1.2.1 import harpoon.IR.LowQuad.LowQuadFactory;
 15 cananian 1.1.2.1 import harpoon.IR.LowQuad.LowQuadVisitor;
 16 cananian 1.1.2.1 import harpoon.IR.LowQuad.PCALL;
 17 cananian 1.1.2.1 import harpoon.Temp.CloningTempMap;
 18 cananian 1.1.2.1 import harpoon.Temp.Temp;
 19 cananian 1.1.2.1 import harpoon.Temp.TempFactory;
 20 cananian 1.1.2.1 import harpoon.Temp.TempMap;
 21 cananian 1.7     import net.cscott.jutil.DisjointSet;
 22 cananian 1.1.2.1 import harpoon.Util.Util;
 23 cananian 1.1.2.1 
 24 cananian 1.1.2.1 import java.util.Collections;
 25 cananian 1.1.2.1 import java.util.HashMap;
 26 cananian 1.1.2.1 import java.util.Iterator;
 27 cananian 1.1.2.1 import java.util.Map;
 28 cananian 1.1.2.1 /**
 29 cananian 1.1.2.1  * <code>SSIToSSA</code> renames variables to eliminate sigma functions
 30 cananian 1.1.2.1  * in an SSI-form codeview, yielding an SSA codeview.
 31 cananian 1.1.2.1  * 
 32 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 33 cananian 1.7      * @version $Id: SSIToSSA.java,v 1.7 2004/02/08 01:55:25 cananian Exp $
 34 cananian 1.1.2.1  */
 35 cananian 1.1.2.1 public class SSIToSSA {
 36 cananian 1.1.2.1     // Return values for the algorithm:
 37 cananian 1.1.2.1 
 38 cananian 1.1.2.5     /** New root element (of the SSA-form graph) */
 39 cananian 1.5         public final HEADER rootQuad;
 40 cananian 1.1.2.1     /** Map from old ssi temps to new ssa temps. */
 41 cananian 1.1.2.1     public final TempMap tempMap;
 42 cananian 1.6         /** Map from new ssa temps to old ssi temps. */
 43 cananian 1.6         public final TempMap revTempMap;
 44 cananian 1.1.2.1     /** Map from old ssi quads to new ssa quads. */
 45 cananian 1.5         public final Map<Quad,Quad> quadMap;
 46 cananian 1.6         /** Map from new ssa quads to old ssi quads. */
 47 cananian 1.6         public final Map<Quad,Quad> revQuadMap;
 48 cananian 1.1.2.1     /** <code>AllocationInformation</code> for the new quads, or
 49 cananian 1.1.2.1      *  <code>null</code> if no allocation information for the old
 50 cananian 1.1.2.1      *  quads was supplied. */
 51 cananian 1.5         public final AllocationInformation<Quad> allocInfo;
 52 cananian 1.1.2.1     /** <code>Derivation</code> for the new quads, or <code>null</code>
 53 cananian 1.1.2.1      *  if no <code>Derivation</code> for the old quads was supplied. */
 54 cananian 1.5         public final Derivation<Quad> derivation;
 55 cananian 1.1.2.1 
 56 cananian 1.1.2.1     /** Converts the given code (in SSI form) to a graph graph in
 57 cananian 1.1.2.1      *  SSA form created using the given code factory <code>nqf</code>. */
 58 cananian 1.1.2.1     public SSIToSSA(final Code c, final QuadFactory nqf) {
 59 cananian 1.5             HEADER oldhead = c.getRootElement();
 60 cananian 1.1.2.1         // first, zip through quads, renaming sigma dests to sources.
 61 cananian 1.1.2.1         Scanner scanner = new Scanner(c, oldhead.getFactory().tempFactory(),
 62 cananian 1.1.2.1                                       nqf.tempFactory());
 63 cananian 1.1.2.1         // now clone quads, doing the renaming and clearing sigma funcs.
 64 cananian 1.1.2.1         Cloner cloner = new Cloner(c, nqf, scanner,
 65 cananian 1.1.2.1                                    c.getDerivation(),
 66 cananian 1.1.2.1                                    c.getAllocationInformation());
 67 cananian 1.1.2.1         // finally, link all the cloned quads together properly.
 68 cananian 1.1.2.1         Linker linker = new Linker(c, cloner.old2new);
 69 cananian 1.1.2.1 
 70 cananian 1.1.2.1         // set instance fields to return values.
 71 cananian 1.1.2.1         this.rootQuad = (HEADER) cloner.old2new.get(oldhead);
 72 cananian 1.1.2.1         this.tempMap = scanner.unmodifiable();
 73 cananian 1.1.2.1         this.quadMap = Collections.unmodifiableMap(cloner.old2new);
 74 cananian 1.6             this.revTempMap = scanner.reverseTempMap();
 75 cananian 1.6             this.revQuadMap = Collections.unmodifiableMap(cloner.new2old);
 76 cananian 1.1.2.1         this.allocInfo = cloner.naim;
 77 cananian 1.1.2.1         this.derivation = cloner.nderiv;
 78 cananian 1.1.2.1     }
 79 cananian 1.1.2.1 
 80 cananian 1.1.2.1     // create map of sigmas dsts to sources.
 81 cananian 1.1.2.1     // use this to implement cloningtempmap with appropriate merges.
 82 cananian 1.1.2.1     static class Scanner extends LowQuadVisitor implements TempMap {
 83 cananian 1.5             final DisjointSet<Temp> map = new DisjointSet<Temp>();
 84 cananian 1.1.2.1         final CloningTempMap ctm;
 85 cananian 1.6             final Map<Temp,Temp> reverseMap = new HashMap<Temp,Temp>();
 86 cananian 1.1.2.1         Scanner(Code c, TempFactory oldtf, TempFactory newtf) {
 87 cananian 1.1.2.1             super(c instanceof harpoon.IR.LowQuad.Code);// strictness.
 88 cananian 1.1.2.1             this.ctm = new CloningTempMap(oldtf, newtf);
 89 cananian 1.1.2.1             // visit all elements.
 90 cananian 1.5                 for (Iterator<Quad> it=c.getElementsI(); it.hasNext(); )
 91 cananian 1.5                     it.next().accept(this);
 92 cananian 1.1.2.1         }
 93 cananian 1.1.2.1         // implement TempMap via CloningTempMap.
 94 cananian 1.6             public Temp tempMap(Temp t) {
 95 cananian 1.6                 Temp r = ctm.tempMap(map.find(t));
 96 cananian 1.6                 reverseMap.put(r, t);
 97 cananian 1.6                 return r;
 98 cananian 1.6             }
 99 cananian 1.1.2.1         public TempMap unmodifiable() {
100 cananian 1.1.2.1             final TempMap uctm = ctm.unmodifiable();
101 cananian 1.1.2.1             return new TempMap() {
102 cananian 1.1.2.1                 public Temp tempMap(Temp t) {
103 cananian 1.5                         return uctm.tempMap(map.find(t));
104 cananian 1.1.2.1                 }
105 cananian 1.1.2.1             };
106 cananian 1.1.2.1         }
107 cananian 1.6             public TempMap reverseTempMap() {
108 cananian 1.6                 return new TempMap() {
109 cananian 1.6                     public Temp tempMap(Temp t) {
110 cananian 1.6                         return reverseMap.get(t);
111 cananian 1.6                     }
112 cananian 1.6                 };
113 cananian 1.6             }
114 cananian 1.1.2.1 
115 cananian 1.1.2.1         // implement visitor.
116 cananian 1.1.2.1         public void visit(Quad q) { /* do nothing. */ }
117 cananian 1.1.2.1         public void visit(SIGMA q) {
118 cananian 1.1.2.1             final int numSigmas = q.numSigmas();
119 cananian 1.1.2.1             final int arity = q.arity();
120 cananian 1.1.2.1             for (int i=0; i<numSigmas; i++)
121 cananian 1.1.2.1                 for (int j=0; j<arity; j++)
122 cananian 1.1.2.1                     map.union(q.dst(i, j), q.src(i));
123 cananian 1.1.2.1         }
124 cananian 1.1.2.1     }
125 cananian 1.1.2.1     // create map of old quads to new quads.
126 cananian 1.1.2.1     static class Cloner extends LowQuadVisitor {
127 cananian 1.1.2.1         /** Maps SSI quads to SSA quads. */
128 cananian 1.5             final Map<Quad,Quad> old2new = new HashMap<Quad,Quad>();
129 cananian 1.6             /** Maps SSA quads to SSI quads. */
130 cananian 1.6             final Map<Quad,Quad> new2old = new HashMap<Quad,Quad>();
131 cananian 1.1.2.1         /** Maps old temps to new temps. */
132 cananian 1.1.2.1         final TempMap tm;
133 cananian 1.1.2.1         /** QuadFactory to use for new Quads. */
134 cananian 1.1.2.1         final QuadFactory nqf;
135 cananian 1.1.2.1         /** AllocationInformation for old Quads */
136 cananian 1.5             final AllocationInformation<Quad> oaim;
137 cananian 1.1.2.1         /** AllocationInformationMap for new Quads */
138 cananian 1.5             final AllocationInformationMap<Quad> naim;
139 cananian 1.1.2.1         /** Derivation for old Quads */
140 cananian 1.5             final Derivation<Quad> oderiv;
141 cananian 1.1.2.1         /** Derivation map for new Quads */
142 cananian 1.5             final DerivationMap<Quad> nderiv;
143 cananian 1.1.2.1 
144 cananian 1.1.2.1         Cloner(Code c, QuadFactory nqf, TempMap tm,
145 cananian 1.5                    Derivation<Quad> oderiv, AllocationInformation<Quad> oaim) {
146 cananian 1.1.2.1             super(c instanceof harpoon.IR.LowQuad.Code);// strictness.
147 cananian 1.1.2.1             // setup cloner fields.
148 cananian 1.1.2.1             this.nqf = nqf; this.tm = tm;
149 cananian 1.1.2.1             this.oaim  = oaim;
150 cananian 1.1.2.1             this.naim  = (oaim==null) ? null : new AllocationInformationMap();
151 cananian 1.1.2.1             this.oderiv= oderiv;
152 cananian 1.1.2.1             this.nderiv= (oderiv==null) ? null : new DerivationMap();
153 cananian 1.1.2.1             // visit all elements.
154 cananian 1.5                 for (Iterator<Quad> it=c.getElementsI(); it.hasNext(); )
155 cananian 1.5                     it.next().accept(this);
156 cananian 1.1.2.1         }
157 cananian 1.1.2.1         private void record(Quad oldq, Quad newq, boolean transferDeriv) {
158 cananian 1.1.2.1             old2new.put(oldq, newq);
159 cananian 1.6                 new2old.put(newq, oldq);
160 cananian 1.1.2.1             if (transferDeriv && nderiv!=null)
161 cananian 1.1.2.1                 nderiv.transfer(newq, oldq, oldq.def(), tm, oderiv);
162 cananian 1.1.2.1             if (newq instanceof ANEW || newq instanceof NEW)
163 cananian 1.1.2.1                 if (naim!=null) naim.transfer(newq, oldq, tm, oaim);
164 cananian 1.1.2.1         }
165 cananian 1.1.2.1         public void visit(Quad q) {
166 cananian 1.1.2.1             Quad nq = q.rename(nqf, tm, tm);
167 cananian 1.1.2.1             record(q, nq, true);
168 cananian 1.1.2.1         }
169 cananian 1.1.2.1         // instances of sigma functions.
170 cananian 1.1.2.1         public void visit(SIGMA q) {
171 cananian 1.1.2.1             // should be caught by specific case.
172 cananian 1.3.2.1             assert false : ("unknown sigma function: "+q); 
173 cananian 1.1.2.1         }
174 cananian 1.1.2.1         public void visit(CALL q) {
175 cananian 1.1.2.1             // create CALL with no sigma functions.
176 cananian 1.1.2.1             CALL nq = new CALL(nqf, q, q.method(), map(q.params()),
177 cananian 1.1.2.1                                map(q.retval()), map(q.retex()),
178 cananian 1.1.2.1                                q.isVirtual(), q.isTailCall(), new Temp[0]);
179 cananian 1.1.2.1             record(q, nq, false);
180 cananian 1.1.2.1             if (nderiv!=null) {
181 cananian 1.1.2.1                 Temp[] odefs = (q.retval()!=null) ?
182 cananian 1.1.2.1                     new Temp[] { q.retval(), q.retex() } :
183 cananian 1.1.2.1                     new Temp[] { q.retex() };
184 cananian 1.1.2.1                 nderiv.transfer(nq, q, odefs, tm, oderiv);
185 cananian 1.1.2.1             }
186 cananian 1.1.2.1         }
187 cananian 1.1.2.1         public void visit(CJMP q) {
188 cananian 1.1.2.1             CJMP nq = new CJMP(nqf, q, map(q.test()), new Temp[0]);
189 cananian 1.1.2.1             record(q, nq, false);
190 cananian 1.1.2.1         }
191 cananian 1.1.2.1         public void visit(PCALL q) {
192 cananian 1.1.2.1             PCALL nq = new PCALL((LowQuadFactory)nqf, q,
193 cananian 1.1.2.1                                  map(q.ptr()), map(q.params()),
194 cananian 1.1.2.1                                  map(q.retval()), map(q.retex()),
195 cananian 1.1.2.1                                  new Temp[0], q.isVirtual(), q.isTailCall());
196 cananian 1.1.2.1             record(q, nq, false);
197 cananian 1.1.2.1             if (nderiv!=null) {
198 cananian 1.1.2.1                 Temp[] odefs = (q.retval()!=null) ?
199 cananian 1.1.2.1                     new Temp[] { q.retval(), q.retex() } :
200 cananian 1.1.2.1                     new Temp[] { q.retex() };
201 cananian 1.1.2.1                 nderiv.transfer(nq, q, odefs, tm, oderiv);
202 cananian 1.1.2.1             }
203 cananian 1.1.2.1         }
204 cananian 1.1.2.1         public void visit(SWITCH q) {
205 cananian 1.1.2.1             SWITCH nq = new SWITCH(nqf, q, map(q.index()), q.keys(),
206 cananian 1.1.2.1                                    new Temp[0]);
207 cananian 1.1.2.2             record(q, nq, false);
208 cananian 1.1.2.2         }
209 cananian 1.1.2.2         public void visit(TYPESWITCH q) {
210 cananian 1.1.2.2             TYPESWITCH nq = new TYPESWITCH(nqf, q, map(q.index()), q.keys(),
211 cananian 1.1.2.4                                            new Temp[0], q.hasDefault());
212 cananian 1.1.2.1             record(q, nq, false);
213 cananian 1.1.2.1         }
214 cananian 1.1.2.1         // convenience mapping functions.
215 cananian 1.1.2.1         private Temp map(Temp t) { return t==null?null:tm.tempMap(t); }
216 cananian 1.1.2.1         private Temp[] map(Temp[] ta) {
217 cananian 1.1.2.1             Temp[] result = new Temp[ta.length];
218 cananian 1.1.2.1             for (int i=0; i<ta.length; i++)
219 cananian 1.1.2.1                 result[i] = map(ta[i]);
220 cananian 1.1.2.1             return result;
221 cananian 1.1.2.1         }
222 cananian 1.1.2.1     }
223 cananian 1.1.2.1     // link quads together.
224 cananian 1.1.2.1     static class Linker {
225 cananian 1.5             Linker(Code c, Map<Quad,Quad> old2new) {
226 cananian 1.1.2.1             // visit all elements, linking together.
227 cananian 1.5                 for (Iterator<Quad> it=c.getElementsI(); it.hasNext(); ) {
228 cananian 1.5                     Quad q = it.next();
229 cananian 1.1.2.1                 int n = q.nextLength();
230 cananian 1.1.2.1                 for (int i=0; i<n; i++) {
231 cananian 1.1.2.1                     Edge e = q.nextEdge(i);
232 cananian 1.5                         Quad nfrm = old2new.get(e.from());
233 cananian 1.5                         Quad nto  = old2new.get(e.to());
234 cananian 1.1.2.1                     Quad.addEdge(nfrm, e.which_succ(), nto, e.which_pred());
235 cananian 1.1.2.1                 }
236 cananian 1.1.2.1             }
237 cananian 1.1.2.1         }
238 cananian 1.1.2.1     }
239 cananian 1.2     }