1 kkz      1.1.2.1  // QuadLiveness.java, created Wed Oct 27 17:17:49 1999 by kkz
  2 cananian 1.1.2.11 // Copyright (C) 1999 Karen K. Zee <kkz@alum.mit.edu>
  3 kkz      1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 kkz      1.1.2.1  package harpoon.Analysis.Quads;
  5 kkz      1.1.2.1  
  6 kkz      1.1.2.1  import harpoon.Analysis.Liveness;
  7 kkz      1.1.2.1  import harpoon.ClassFile.HCode;
  8 kkz      1.1.2.1  import harpoon.ClassFile.HCodeEdge;
  9 kkz      1.1.2.1  import harpoon.ClassFile.HCodeElement;
 10 kkz      1.1.2.1  import harpoon.IR.Quads.Quad;
 11 bdemsky  1.1.2.7  import harpoon.IR.Quads.PHI;
 12 cananian 1.4      import harpoon.Temp.Temp;
 13 bdemsky  1.1.2.4  import harpoon.Util.Util;
 14 kkz      1.1.2.1  
 15 cananian 1.4      import java.util.ArrayList;
 16 cananian 1.4      import java.util.Collections;
 17 cananian 1.2.2.1  import java.util.HashMap;
 18 kkz      1.1.2.1  import java.util.Iterator;
 19 cananian 1.4      import java.util.List;
 20 cananian 1.2.2.1  import java.util.Map;
 21 kkz      1.1.2.1  import java.util.Set;
 22 kkz      1.1.2.1  
 23 cananian 1.4      import net.cscott.jutil.Default;
 24 cananian 1.4      import net.cscott.jutil.WorkSet;
 25 kkz      1.1.2.1  /**
 26 kkz      1.1.2.1   * <code>QuadLiveness</code> performs live variable analysis for a given
 27 kkz      1.1.2.1   * <code>HCode</code>. Since it caches results, you should create a new
 28 kkz      1.1.2.1   * <code>QuadLiveness</code> if you have changed the <code>HCode</code>.
 29 kkz      1.1.2.1   * 
 30 cananian 1.1.2.11  * @author Karen K. Zee <kkz@alum.mit.edu>
 31 cananian 1.4       * @version $Id: QuadLiveness.java,v 1.4 2004/02/08 01:53:14 cananian Exp $
 32 kkz      1.1.2.1   */
 33 cananian 1.2.2.1  public class QuadLiveness extends Liveness<Quad> {
 34 cananian 1.2.2.1      final Map<Quad,Set<Temp>> livein, liveout;
 35 cananian 1.2.2.1      final Map<Quad,Temp[]> tempin, tempout, tempinout;
 36 kkz      1.1.2.1  
 37 kkz      1.1.2.1      /** Creates a <code>QuadLiveness</code>. Requires 
 38 kkz      1.1.2.1       *  that the <code>HCode</code> be quad-no-ssa.
 39 kkz      1.1.2.1       */
 40 cananian 1.2.2.1      public QuadLiveness(HCode<Quad> hc) {
 41 kkz      1.1.2.1          super(hc);
 42 cananian 1.4              List<Map<Quad,Set<Temp>>> live = this.analyze();
 43 cananian 1.4              this.livein = live.get(0);
 44 cananian 1.4              this.liveout = live.get(1);
 45 cananian 1.2.2.1          this.tempin = new HashMap<Quad,Temp[]>();
 46 cananian 1.2.2.1          this.tempout = new HashMap<Quad,Temp[]>();
 47 cananian 1.2.2.1          this.tempinout = new HashMap<Quad,Temp[]>();
 48 kkz      1.1.2.1      }
 49 kkz      1.1.2.1  
 50 kkz      1.1.2.1      /** Returns the <code>Set</code> of <code>Temp</code>s 
 51 kkz      1.1.2.1       *  that are live-in at the <code>HCodeElement</code>. 
 52 kkz      1.1.2.1       *  Requires that the <code>HCodeElement</code> be in 
 53 kkz      1.1.2.1       *  quad-no-ssa form. Returns <code>null</code> if there
 54 kkz      1.1.2.1       *  no live-in variables.
 55 kkz      1.1.2.1       */
 56 cananian 1.2.2.1      public Set<Temp> getLiveIn(Quad hce) {
 57 cananian 1.2.2.1          return new WorkSet<Temp>(livein.get(hce));
 58 kkz      1.1.2.1      }
 59 bdemsky  1.1.2.4      /** Same as getLiveIn, but returns array of <code>Temp</code>s.  This
 60 bdemsky  1.1.2.4          array is guaranteed to have the Temp's in the same order for a given
 61 bdemsky  1.1.2.4          QuadLiveness object,Quad pair.**/
 62 kkz      1.1.2.1  
 63 cananian 1.2.2.1      public Temp[] getLiveInArray(Quad hce) {
 64 bdemsky  1.1.2.4          if (tempin.containsKey(hce))
 65 cananian 1.2.2.1              return Util.safeCopy(Temp.arrayFactory, tempin.get(hce));
 66 bdemsky  1.1.2.4          else {
 67 cananian 1.2.2.1              Set<Temp> set = this.livein.get(hce);
 68 cananian 1.2.2.1              Temp[] retval = set.toArray(new Temp[set.size()]);
 69 bdemsky  1.1.2.4              tempin.put(hce,retval);
 70 cananian 1.2.2.1              return Util.safeCopy(Temp.arrayFactory, retval);
 71 bdemsky  1.1.2.4          }
 72 bdemsky  1.1.2.3      }
 73 kkz      1.1.2.1      /** Returns the <code>Set</code> of <code>Temp</code>s 
 74 kkz      1.1.2.1       *  that are live-out at the <code>HCodeElement</code>. 
 75 kkz      1.1.2.1       *  Requires that the <code>HCodeElement</code> be in 
 76 kkz      1.1.2.1       *  quad-no-ssa form. Returns <code>null</code> if there
 77 kkz      1.1.2.1       *  no live-in variables.
 78 kkz      1.1.2.1       */
 79 cananian 1.2.2.1      public Set<Temp> getLiveOut(Quad hce) {
 80 cananian 1.2.2.1          return new WorkSet<Temp>(liveout.get(hce));
 81 bdemsky  1.1.2.3      }
 82 bdemsky  1.1.2.3  
 83 bdemsky  1.1.2.4      /** Same as getLiveOut, but returns array of <code>Temp</code>s.
 84 bdemsky  1.1.2.4          Makes the same order guarantees as <code>getLiveInArray</code>.**/
 85 cananian 1.2.2.1      public Temp[] getLiveOutArray(Quad hce) {
 86 bdemsky  1.1.2.4          if (tempout.containsKey(hce))
 87 cananian 1.2.2.1              return Util.safeCopy(Temp.arrayFactory, tempout.get(hce));
 88 bdemsky  1.1.2.4          else {
 89 cananian 1.2.2.1              Set<Temp> set = this.liveout.get(hce);
 90 cananian 1.2.2.1              Temp[] retval = set.toArray(new Temp[set.size()]);
 91 bdemsky  1.1.2.4              tempout.put(hce, retval);
 92 cananian 1.2.2.1              return Util.safeCopy(Temp.arrayFactory, retval);
 93 cananian 1.1.2.5          }
 94 cananian 1.1.2.5      }
 95 cananian 1.1.2.5  
 96 cananian 1.2.2.1      public Temp[] getLiveInandOutArray(Quad hce) {
 97 cananian 1.1.2.5          if (tempinout.containsKey(hce))
 98 cananian 1.2.2.1              return Util.safeCopy(Temp.arrayFactory, tempinout.get(hce));
 99 cananian 1.1.2.5          else {
100 cananian 1.2.2.1              Set<Temp> set = this.liveout.get(hce);
101 cananian 1.2.2.1              Set<Temp> setin = this.livein.get(hce);
102 cananian 1.2.2.1              Iterator<Temp> iter=set.iterator();
103 cananian 1.1.2.5              int count=0;
104 cananian 1.1.2.5              while (iter.hasNext())
105 cananian 1.1.2.5                  if (setin.contains(iter.next()))
106 cananian 1.1.2.5                      count++;
107 cananian 1.1.2.5              Temp[] retval=new Temp[count];
108 cananian 1.1.2.5              iter=set.iterator();
109 cananian 1.1.2.5              count=0;
110 cananian 1.1.2.5              while (iter.hasNext()) {
111 cananian 1.2.2.1                  Temp tt = iter.next();
112 cananian 1.1.2.5                  if (setin.contains(tt))
113 cananian 1.1.2.5                      retval[count++]=tt;
114 cananian 1.1.2.5              }
115 cananian 1.1.2.5              tempinout.put(hce, retval);
116 cananian 1.2.2.1              return Util.safeCopy(Temp.arrayFactory, retval);
117 bdemsky  1.1.2.4          }
118 kkz      1.1.2.1      }
119 kkz      1.1.2.1  
120 cananian 1.4          private List<Map<Quad,Set<Temp>>> analyze() {
121 cananian 1.1.2.6          //System.err.println("Entering QuadLiveness.analyze()");
122 cananian 1.2.2.1          WorkSet<Quad> ws = new WorkSet<Quad>(this.hc.getElementsL());
123 kkz      1.1.2.1  
124 kkz      1.1.2.1          if (ws.isEmpty()) {
125 cananian 1.1.2.6              //System.err.println("Leaving QuadLiveness.analyze()");
126 cananian 1.4                  return Collections.<Map<Quad,Set<Temp>>>nCopies
127 cananian 1.4                      (2, Default.<Quad,Set<Temp>>EMPTY_MAP());
128 kkz      1.1.2.1          }
129 kkz      1.1.2.1  
130 cananian 1.2.2.1          Quad[] leaves = this.hc.getLeafElements();
131 kkz      1.1.2.1          
132 kkz      1.1.2.1          // For efficiency reasons, we want to start w/ a leaf
133 kkz      1.1.2.1          // element if one exists. Otherwise, just start w/
134 kkz      1.1.2.1          // any element.
135 kkz      1.1.2.1          Quad hce = null;
136 kkz      1.1.2.1          if (leaves != null) {
137 cananian 1.2.2.1              hce = leaves[0];
138 kkz      1.1.2.1              ws.remove(hce);
139 kkz      1.1.2.1          } else {
140 cananian 1.4                  hce = ws.removeLast();
141 kkz      1.1.2.1          }
142 kkz      1.1.2.1  
143 cananian 1.2.2.1          Map<Quad,Set<Temp>> in = new HashMap<Quad,Set<Temp>>();
144 cananian 1.2.2.1          Map<Quad,Set<Temp>> out = new HashMap<Quad,Set<Temp>>();
145 kkz      1.1.2.1  
146 kkz      1.1.2.1          while (true) {
147 cananian 1.2.2.1              Set<Temp> out_ = new WorkSet<Temp>();
148 kkz      1.1.2.1  
149 kkz      1.1.2.1  
150 bdemsky  1.1.2.7              for (int i=0;i<hce.nextLength();i++) {
151 bdemsky  1.1.2.7                  Quad successor=hce.next(i);
152 kkz      1.1.2.1                  if (in.containsKey(successor)) {
153 bdemsky  1.1.2.7                      if (successor instanceof PHI) {
154 cananian 1.2.2.1                          WorkSet<Temp> w=new WorkSet<Temp>(out.get(successor));
155 bdemsky  1.1.2.9                          
156 bdemsky  1.1.2.9                          //search for successor
157 bdemsky  1.1.2.9                          int edge=hce.nextEdge(i).which_pred();
158 bdemsky  1.1.2.9                          PHI phi=(PHI)successor;
159 bdemsky  1.1.2.9                          
160 bdemsky  1.1.2.9                          for (int j=0;j<phi.numPhis();j++)
161 bdemsky  1.1.2.9                              w.remove(phi.dst(j));
162 bdemsky  1.1.2.9                          
163 bdemsky  1.1.2.9                          for (int j=0;j<phi.numPhis();j++)
164 bdemsky  1.1.2.9                              w.add(phi.src(j,edge));
165 bdemsky  1.1.2.9                          out_.addAll(w);
166 bdemsky  1.1.2.9                      } else
167 cananian 1.2.2.1                          out_.addAll(in.get(successor));
168 kkz      1.1.2.1                  }
169 kkz      1.1.2.1              }
170 kkz      1.1.2.1  
171 kkz      1.1.2.8              // Calculate "in" Set
172 cananian 1.2.2.1              Set<Temp> in_ = new WorkSet<Temp>(out_);
173 kkz      1.1.2.8              in_.removeAll(hce.defC());
174 kkz      1.1.2.8              in_.addAll(hce.useC());
175 kkz      1.1.2.1  
176 kkz      1.1.2.1              // If we have grown our live-in or live-out variables,
177 kkz      1.1.2.1              // we need to update all of its predecessors.
178 cananian 1.2.2.1              // TRICK: doing a put on a Map returns the previous mapping
179 cananian 1.2.2.1              Set<Temp> old_in = in.put(hce, in_);
180 cananian 1.2.2.1              Set<Temp> old_out = out.put(hce, out_);
181 bdemsky  1.1.2.7              if ((old_in == null)|| (old_in.size() < in_.size())) {
182 bdemsky  1.1.2.7                  for (int i=0;i<hce.prevLength();i++)
183 kkz      1.1.2.8                      ws.push(hce.prev(i));
184 bdemsky  1.1.2.7              } else if ((old_out == null)|| ( old_out.size() < out_.size())) {
185 bdemsky  1.1.2.7                  for (int i=0;i<hce.prevLength();i++)
186 kkz      1.1.2.8                      ws.push(hce.prev(i));
187 kkz      1.1.2.1              }
188 kkz      1.1.2.1  
189 kkz      1.1.2.8              if (ws.isEmpty()) break;
190 cananian 1.4                  hce = ws.removeLast();
191 kkz      1.1.2.1          }
192 cananian 1.4              List<Map<Quad,Set<Temp>>> retval=new ArrayList<Map<Quad,Set<Temp>>>(2);
193 cananian 1.4              retval.add(in); retval.add(out);
194 cananian 1.4              return retval;
195 kkz      1.1.2.1      }
196 kkz      1.1.2.1  }
197 cananian 1.2