1 bdemsky  1.1.2.1  // BasicInduction.java, created Mon Jun 28 13:38:30 1999 by bdemsky
  2 bdemsky  1.1.2.1  // Copyright (C) 1999 Brian Demsky <bdemsky@mit.edu>
  3 bdemsky  1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 bdemsky  1.1.2.1  package harpoon.Analysis.LowQuad.Loop;
  5 bdemsky  1.1.2.1  
  6 bdemsky  1.1.2.1  import harpoon.Analysis.Loops.LoopFinder;
  7 bdemsky  1.1.2.1  import harpoon.Analysis.Loops.Loops;
  8 bdemsky  1.1.2.1  import harpoon.Analysis.LowQuad.Loop.Induction;
  9 bdemsky  1.1.2.1  import harpoon.Analysis.UseDef;
 10 cananian 1.1.2.8  import harpoon.ClassFile.HCode;
 11 cananian 1.1.2.8  import harpoon.ClassFile.HCodeEdge;
 12 cananian 1.1.2.8  import harpoon.ClassFile.HCodeElement;
 13 cananian 1.1.2.8  import harpoon.IR.LowQuad.LQop;
 14 cananian 1.1.2.8  import harpoon.IR.LowQuad.LowQuadVisitor;
 15 cananian 1.1.2.8  import harpoon.IR.LowQuad.POPER;
 16 cananian 1.1.2.7  import harpoon.IR.Properties.CFGraphable;
 17 cananian 1.1.2.8  import harpoon.IR.Quads.AGET;
 18 cananian 1.1.2.8  import harpoon.IR.Quads.ASET;
 19 cananian 1.1.2.8  import harpoon.IR.Quads.GET;
 20 cananian 1.1.2.8  import harpoon.IR.Quads.HANDLER;
 21 cananian 1.1.2.8  import harpoon.IR.Quads.OPER;
 22 cananian 1.1.2.8  import harpoon.IR.Quads.PHI;
 23 cananian 1.1.2.8  import harpoon.IR.Quads.Qop;
 24 cananian 1.1.2.8  import harpoon.IR.Quads.Quad;
 25 cananian 1.1.2.8  import harpoon.IR.Quads.SET;
 26 cananian 1.5      import net.cscott.jutil.WorkSet;
 27 bdemsky  1.1.2.14 import harpoon.Util.Util;
 28 bdemsky  1.1.2.1  import harpoon.Temp.Temp;
 29 bdemsky  1.1.2.1  import harpoon.Temp.TempMap;
 30 bdemsky  1.1.2.1  
 31 bdemsky  1.1.2.1  
 32 bdemsky  1.1.2.1  import java.util.HashMap;
 33 bdemsky  1.1.2.1  import java.util.Iterator;
 34 bdemsky  1.1.2.1  
 35 bdemsky  1.1.2.1  
 36 bdemsky  1.1.2.1  /**
 37 bdemsky  1.1.2.1   * <code>BasicInductions</code>
 38 bdemsky  1.1.2.1   * 
 39 bdemsky  1.1.2.1   * @author  Brian Demsky <bdemsky@mit.edu>
 40 cananian 1.5       * @version $Id: BasicInductions.java,v 1.5 2004/02/08 01:52:54 cananian Exp $
 41 bdemsky  1.1.2.1   */
 42 bdemsky  1.1.2.1  public class BasicInductions {
 43 bdemsky  1.1.2.1      HCode hc;
 44 bdemsky  1.1.2.1      TempMap tm;
 45 bdemsky  1.1.2.1  
 46 bdemsky  1.1.2.1      /**  Creates a <code>BasicInductions</code> object. */
 47 bdemsky  1.1.2.1      public BasicInductions(TempMap tm, HCode hc) {
 48 bdemsky  1.1.2.1          this.hc=hc;
 49 bdemsky  1.1.2.1          this.tm=tm;
 50 bdemsky  1.1.2.1      }
 51 bdemsky  1.1.2.1  
 52 bdemsky  1.1.2.1      /** Creates a <code>HashMap</code> mapping <code>Temp</code>s to 
 53 bdemsky  1.1.2.1       *  <code>Induction</code> classes describing the induction variable. 
 54 bdemsky  1.1.2.1       *  This code only finds basic induction variables. */
 55 bdemsky  1.1.2.1  
 56 bdemsky  1.1.2.1      public HashMap doInduction(Loops lp, WorkSet invariants) {
 57 bdemsky  1.1.2.1          HashMap basicinductions=new HashMap();
 58 bdemsky  1.1.2.1          
 59 bdemsky  1.1.2.1          /*Get the loop header and
 60 bdemsky  1.1.2.1            make sure that this is a single entrance loop.*/
 61 bdemsky  1.1.2.1          Iterator iterate=(lp.loopEntrances()).iterator();
 62 ovy      1.1.2.13 
 63 bdemsky  1.1.2.15         /* throw assertion if loop has no entrance (root loop) */
 64 cananian 1.3.2.1          assert !lp.loopEntrances().isEmpty();
 65 ovy      1.1.2.13         
 66 bdemsky  1.1.2.1          Quad header=(Quad) iterate.next();
 67 bdemsky  1.1.2.1          if (iterate.hasNext())
 68 bdemsky  1.1.2.1              System.out.println("This routine doesn't work on multiple entrance loops"); 
 69 bdemsky  1.1.2.1          
 70 bdemsky  1.1.2.1          /*Set up Sets and the UseDef map*/
 71 bdemsky  1.1.2.1          
 72 cananian 1.1.2.11         WorkSet excelements=(WorkSet) lp.loopExcElements();
 73 cananian 1.1.2.11         WorkSet incelements=(WorkSet) lp.loopIncElements();
 74 bdemsky  1.1.2.1          UseDef ud= new UseDef();
 75 bdemsky  1.1.2.1          WorkSet adds=new WorkSet();
 76 bdemsky  1.1.2.1          WorkSet addp=new WorkSet();
 77 bdemsky  1.1.2.1          WorkSet phis=new WorkSet();
 78 bdemsky  1.1.2.1  
 79 bdemsky  1.1.2.1          /* Find phi's and adds in this loop's elements.*/
 80 bdemsky  1.1.2.1          BasicVisitor visitor=new BasicVisitor(adds, addp, phis);
 81 bdemsky  1.1.2.1          iterate=excelements.iterator();
 82 bdemsky  1.1.2.1          while (iterate.hasNext()) {
 83 bdemsky  1.1.2.1              Quad q=(Quad)iterate.next();
 84 cananian 1.1.2.3              q.accept(visitor);
 85 bdemsky  1.1.2.1          }
 86 bdemsky  1.1.2.1  
 87 bdemsky  1.1.2.1  
 88 bdemsky  1.1.2.1          /* Now lets iterate over the add statements.*/
 89 bdemsky  1.1.2.1          iterate=adds.iterator();
 90 bdemsky  1.1.2.1          while (iterate.hasNext()) {
 91 bdemsky  1.1.2.1  
 92 bdemsky  1.1.2.1              //Get the add statement
 93 bdemsky  1.1.2.6              OPER q=(OPER) iterate.next();
 94 bdemsky  1.1.2.1              //debug
 95 bdemsky  1.1.2.1              //Find the number of operands it has
 96 bdemsky  1.1.2.1              int numofoperands=q.operandsLength();
 97 bdemsky  1.1.2.1  
 98 bdemsky  1.1.2.1              //Set the flag that this is a basic induction
 99 bdemsky  1.1.2.1              boolean basicinduction=true;
100 bdemsky  1.1.2.1  
101 bdemsky  1.1.2.1              //Make sure the phi links back to us
102 bdemsky  1.1.2.1              boolean tous=false;
103 bdemsky  1.1.2.1              
104 bdemsky  1.1.2.1              //Set the corresponding phi pointer to null
105 bdemsky  1.1.2.1              PHI phi=null;
106 bdemsky  1.1.2.1              int k=0;
107 bdemsky  1.1.2.1  
108 bdemsky  1.1.2.1              //Loop over the operands in the add statement
109 bdemsky  1.1.2.1              for (int i=0;i<numofoperands;i++) {
110 bdemsky  1.1.2.1  
111 bdemsky  1.1.2.1                  //Find the SSA temp for the operand
112 bdemsky  1.1.2.1                  Temp origin=tm.tempMap(q.operands(i));
113 bdemsky  1.1.2.1                  HCodeElement []sources=ud.defMap(hc,origin);
114 bdemsky  1.1.2.1  
115 bdemsky  1.1.2.1                  //See if our list of phis contains sources[0]
116 bdemsky  1.1.2.1                  if (phis.contains(sources[0])) {
117 bdemsky  1.1.2.1  
118 bdemsky  1.1.2.1                      //Have we already seen a different phi?
119 bdemsky  1.1.2.1                      if ((phi!=sources[0])&&(phi!=null)) {
120 bdemsky  1.1.2.1  
121 bdemsky  1.1.2.1                          //Yep...this isn't a basic induction variable
122 bdemsky  1.1.2.1                          basicinduction=false;
123 bdemsky  1.1.2.1                          break;
124 bdemsky  1.1.2.1                      } else if (phi==null) {
125 bdemsky  1.1.2.1  
126 bdemsky  1.1.2.1                          //Haven't seen a phi yet!
127 bdemsky  1.1.2.1  
128 bdemsky  1.1.2.1                          //Set the phi pointer here
129 bdemsky  1.1.2.1                          phi=(PHI)sources[0];
130 bdemsky  1.1.2.1  
131 bdemsky  1.1.2.1                          //If the phi isn't the header, it isn't a basic induction variable
132 bdemsky  1.1.2.1  
133 bdemsky  1.1.2.1                          if (phi!=header) {
134 bdemsky  1.1.2.1                              basicinduction=false;
135 bdemsky  1.1.2.1                              break;
136 bdemsky  1.1.2.1                          }
137 bdemsky  1.1.2.1  
138 bdemsky  1.1.2.1                          //We need to search for the phi statement...
139 bdemsky  1.1.2.1                          k=0; //Get the right phi statement
140 bdemsky  1.1.2.1                          while (origin!=phi.dst(k)) k++;
141 bdemsky  1.1.2.1  
142 bdemsky  1.1.2.1                          //Get an array of the predecessor edges
143 cananian 1.1.2.7                          HCodeEdge[] pred=((CFGraphable) phi).pred();
144 bdemsky  1.1.2.1                          //Loop through the edges of this phi
145 bdemsky  1.1.2.1                          for (int j=0; j<phi.arity();j++) {
146 bdemsky  1.1.2.1  
147 bdemsky  1.1.2.1                              //If the loop contians the incoming edge,
148 bdemsky  1.1.2.1                              //the phi needs to use our 
149 bdemsky  1.1.2.1                              if(incelements.contains(pred[j].from())) {
150 bdemsky  1.1.2.1  
151 bdemsky  1.1.2.1                                  //Needs to be  = to us!
152 bdemsky  1.1.2.1                                  if(tm.tempMap(phi.src(k,j))!=q.dst()) {
153 bdemsky  1.1.2.1                                      //Else it isn't a basic induction variable
154 bdemsky  1.1.2.1                                      basicinduction=false;
155 bdemsky  1.1.2.1                                      break;
156 bdemsky  1.1.2.1                                  } else {
157 bdemsky  1.1.2.1                                      tous=true;
158 bdemsky  1.1.2.1                                  }
159 bdemsky  1.1.2.1                              }
160 bdemsky  1.1.2.1                          }
161 bdemsky  1.1.2.1                      }
162 bdemsky  1.1.2.1                  } else {
163 bdemsky  1.1.2.1                      //If it isn't from a phi, it needs to be loop invariant!!!
164 bdemsky  1.1.2.1                      //Look to see if this is loop invariant!
165 bdemsky  1.1.2.1                      if ((!invariants.contains(sources[0]))&&(incelements.contains(sources[0]))) {
166 bdemsky  1.1.2.1                          //Conditions are that it comes from inside the loop and it isn't
167 bdemsky  1.1.2.1                          //loop invariant
168 bdemsky  1.1.2.1  
169 bdemsky  1.1.2.1                          //We don't have an invariant...no go!
170 bdemsky  1.1.2.1                          basicinduction=false;
171 bdemsky  1.1.2.1                          break;
172 bdemsky  1.1.2.1                      }
173 bdemsky  1.1.2.1                  }
174 bdemsky  1.1.2.1              }
175 bdemsky  1.1.2.1              //If it made it through the checks, it is a basic induction variable...
176 bdemsky  1.1.2.1              if (basicinduction&&(phi!=null)&&tous) {
177 bdemsky  1.1.2.1                  Induction tmp;
178 bdemsky  1.1.2.1                  if (addp.contains(q)) 
179 bdemsky  1.1.2.2                      tmp=new Induction(phi.dst(k),null,true);
180 bdemsky  1.1.2.1                      else
181 bdemsky  1.1.2.1                      tmp=new Induction(phi.dst(k),0,1);
182 bdemsky  1.1.2.1                  basicinductions.put(phi.dst(k),tmp);
183 bdemsky  1.1.2.1              }
184 bdemsky  1.1.2.1          }
185 bdemsky  1.1.2.1          return basicinductions;
186 bdemsky  1.1.2.1      }
187 bdemsky  1.1.2.1  
188 bdemsky  1.1.2.1      /** BasicVisitor finds ADD and <code>PHI</code> quads.  These
189 bdemsky  1.1.2.1       *  are used to find basic induction variables.*/
190 bdemsky  1.1.2.1  
191 bdemsky  1.1.2.1      class BasicVisitor extends LowQuadVisitor {
192 bdemsky  1.1.2.1          WorkSet adds,addp;
193 bdemsky  1.1.2.1          WorkSet phis;
194 bdemsky  1.1.2.1  
195 bdemsky  1.1.2.1          BasicVisitor(WorkSet adds, WorkSet addp, WorkSet phis) {
196 cananian 1.1.2.9              super(false/*non-strict*/);
197 bdemsky  1.1.2.1              this.adds=adds;
198 bdemsky  1.1.2.1              this.addp=addp;
199 bdemsky  1.1.2.1              this.phis=phis;
200 bdemsky  1.1.2.1          }
201 bdemsky  1.1.2.1          
202 bdemsky  1.1.2.1          public void visit(Quad q) {
203 bdemsky  1.1.2.1              //Do nothing
204 bdemsky  1.1.2.1          }
205 bdemsky  1.1.2.4  
206 bdemsky  1.1.2.1          public void visit(OPER q) {
207 bdemsky  1.1.2.4              switch (q.opcode()) {
208 bdemsky  1.1.2.4              case Qop.IADD:
209 bdemsky  1.1.2.4                  //          case Qop.LADD:
210 bdemsky  1.1.2.4                  adds.push(q);
211 bdemsky  1.1.2.4                  break;
212 bdemsky  1.1.2.4              default:
213 bdemsky  1.1.2.4              } 
214 bdemsky  1.1.2.1          }
215 bdemsky  1.1.2.1  
216 bdemsky  1.1.2.1          public void visit(POPER q) {
217 bdemsky  1.1.2.1              switch (q.opcode()) {
218 bdemsky  1.1.2.1              case LQop.PADD:
219 bdemsky  1.1.2.1                  addp.push(q);//put in both list!
220 bdemsky  1.1.2.1              case Qop.IADD:
221 bdemsky  1.1.2.1                  //          case Qop.LADD:
222 bdemsky  1.1.2.1                  adds.push(q);
223 bdemsky  1.1.2.1                  break;
224 bdemsky  1.1.2.1              default:
225 bdemsky  1.1.2.1              }
226 bdemsky  1.1.2.1          }
227 bdemsky  1.1.2.1  
228 bdemsky  1.1.2.1          public void visit(PHI q) {
229 bdemsky  1.1.2.1              phis.push(q);
230 bdemsky  1.1.2.1          }
231 bdemsky  1.1.2.1      }
232 bdemsky  1.1.2.1  }
233 cananian 1.2