1 pnkfelix 1.1.2.1  // RegAlloc.java, created Mon Mar 29 16:47:25 1999 by pnkfelix
  2 cananian 1.1.2.16 // Copyright (C) 1999 Felix S. Klock II <pnkfelix@mit.edu>
  3 pnkfelix 1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 pnkfelix 1.1.2.1  package harpoon.Analysis.Instr;
  5 pnkfelix 1.1.2.1  
  6 pnkfelix 1.1.2.1  import harpoon.Temp.Temp;
  7 pnkfelix 1.1.2.1  import harpoon.IR.Assem.Instr;
  8 pnkfelix 1.1.2.11 import harpoon.Backend.Generic.RegFileInfo;
  9 pnkfelix 1.1.2.1  import harpoon.Backend.Generic.Frame;
 10 pnkfelix 1.1.2.1  import harpoon.Backend.Generic.Code;
 11 cananian 1.1.2.14 import harpoon.Analysis.Maps.UseDefMap;
 12 pnkfelix 1.1.2.8  import harpoon.Analysis.BasicBlock;
 13 pnkfelix 1.1.2.13 import harpoon.Analysis.Maps.Derivation;
 14 pnkfelix 1.1.2.1  
 15 pnkfelix 1.1.2.1  import java.util.Hashtable;
 16 pnkfelix 1.1.2.1  import java.util.Set;
 17 pnkfelix 1.1.2.1  import java.util.Vector;
 18 pnkfelix 1.1.2.1  import java.util.ListIterator;
 19 pnkfelix 1.1.2.1  import java.util.HashSet;
 20 pnkfelix 1.1.2.1  import java.util.Map;
 21 pnkfelix 1.1.2.1  import java.util.HashMap;
 22 pnkfelix 1.1.2.1  
 23 pnkfelix 1.1.2.1  /** <code>DemandDrivenRegAlloc</code> performs 
 24 pnkfelix 1.1.2.2      <A HREF="http://lm.lcs.mit.edu/~pnkfelix/DemandDrivenRegAlloc.pdf"> 
 25 pnkfelix 1.1.2.1      Demand-Driven Register Allocation</A> for a set of
 26 pnkfelix 1.1.2.1      <code>Instr</code>s in a <code>Code</code>.
 27 pnkfelix 1.1.2.1  
 28 cananian 1.1.2.16     @author  Felix S. Klock II <pnkfelix@mit.edu>
 29 cananian 1.2          @version $Id: DemandDrivenRegAlloc.java,v 1.2 2002/02/25 20:57:30 cananian Exp $ 
 30 pnkfelix 1.1.2.1  */
 31 pnkfelix 1.1.2.1  public class DemandDrivenRegAlloc extends RegAlloc {
 32 pnkfelix 1.1.2.1  
 33 cananian 1.1.2.14     UseDefMap uses;
 34 pnkfelix 1.1.2.3  
 35 pnkfelix 1.1.2.3      // maps basicblocks to the variables allocated to registers
 36 pnkfelix 1.1.2.3      // entering the block
 37 pnkfelix 1.1.2.3      private Map bbToAllocatedMap;
 38 pnkfelix 1.1.2.3  
 39 pnkfelix 1.1.2.3      // maps basicblocks to the live variables entering the block
 40 pnkfelix 1.1.2.3      private Map bbToLiveVarMap;
 41 pnkfelix 1.1.2.3      
 42 pnkfelix 1.1.2.3      // TODO: should probably add a local var storing info on
 43 pnkfelix 1.1.2.3      // LiveVarAnalysis. 
 44 pnkfelix 1.1.2.3  
 45 pnkfelix 1.1.2.1      
 46 pnkfelix 1.1.2.1      /** Creates a <code>DemandDrivenRegAlloc</code>. 
 47 pnkfelix 1.1.2.1          
 48 pnkfelix 1.1.2.1          <BR> <B>Design Issue:</B> should there be a RegAlloc object
 49 pnkfelix 1.1.2.1               for every method, or just for every machine target?  For
 50 pnkfelix 1.1.2.1               now it seems associating a new one with every method will
 51 pnkfelix 1.1.2.1               save a lot of headaches.
 52 pnkfelix 1.1.2.1  
 53 pnkfelix 1.1.2.1          <BR> <B>requires:</B> 
 54 pnkfelix 1.1.2.1               1. Local register allocation has been run on
 55 pnkfelix 1.1.2.1                  <code>code</code> already. 
 56 pnkfelix 1.1.2.1      */
 57 pnkfelix 1.1.2.6      protected DemandDrivenRegAlloc(Code code) {
 58 pnkfelix 1.1.2.6          super(code);
 59 cananian 1.1.2.14         uses = new harpoon.Analysis.UseDef( /*code*/ );
 60 pnkfelix 1.1.2.3  
 61 pnkfelix 1.1.2.3          bbToAllocatedMap = new HashMap(); // built during allocation 
 62 pnkfelix 1.1.2.3  
 63 pnkfelix 1.1.2.3          bbToLiveVarMap = findLiveVars(code); // invariant during allocation
 64 pnkfelix 1.1.2.1      }
 65 pnkfelix 1.1.2.13     
 66 pnkfelix 1.1.2.13     /** stub implementation. */
 67 pnkfelix 1.1.2.13     protected Derivation getDerivation() { return null; }
 68 pnkfelix 1.1.2.1     
 69 pnkfelix 1.1.2.9      protected void generateRegAssignment() {
 70 pnkfelix 1.1.2.2  
 71 pnkfelix 1.1.2.2          /* procedure for register allocation for a procedure (taken from
 72 pnkfelix 1.1.2.2             Demand-Driven Register Allocation):
 73 pnkfelix 1.1.2.2  
 74 pnkfelix 1.1.2.2             (assumes that Local Allocation has already been performed)
 75 pnkfelix 1.1.2.2          */
 76 pnkfelix 1.1.2.2          
 77 pnkfelix 1.1.2.2          /*
 78 pnkfelix 1.1.2.2             2. For all loops, l. in the procedure, from innermost to
 79 pnkfelix 1.1.2.2             outermost do the following: 
 80 pnkfelix 1.1.2.2             (a) Attempt to remove loads in l: 
 81 pnkfelix 1.1.2.1                i.   Compute delta-estimates for all instructions in the
 82 pnkfelix 1.1.2.1                     loop (with ComputeDeltas() ).
 83 pnkfelix 1.1.2.1                ii.  For each load of a register candidate in the loop,
 84 pnkfelix 1.1.2.1                     estimate the chance that the value will reach the
 85 pnkfelix 1.1.2.1                     load in a register.  This is the product of all the
 86 pnkfelix 1.1.2.1                     delta-estimates for that candidate in the load's
 87 pnkfelix 1.1.2.1                     register-live-range.  
 88 pnkfelix 1.1.2.1                iii. If no loads have an estimate greater than 0, then
 89 pnkfelix 1.1.2.1                     quit processing loads.
 90 pnkfelix 1.1.2.1                iv.  Otherwise, remove the load with the greatest figure
 91 pnkfelix 1.1.2.1                     of merit, and allocate the candidate a register
 92 pnkfelix 1.1.2.1                     across its entire register-live-range.  (This may
 93 pnkfelix 1.1.2.1                     require putting a load in the loop's preheader.)
 94 pnkfelix 1.1.2.1            (b) Attempt to remove stores in l:
 95 pnkfelix 1.1.2.1                i.   Compute delta-estimates for all instructions in the
 96 pnkfelix 1.1.2.1                     loop (with ComputeDeltas() ).
 97 pnkfelix 1.1.2.1                ii.  For each store of a register candidate in the loop,
 98 pnkfelix 1.1.2.1                     estimate the chance that the stored value will
 99 pnkfelix 1.1.2.1                     reach *all* remaining reachable loads in l, and
100 pnkfelix 1.1.2.1                     those postexits in which the value is live in a
101 pnkfelix 1.1.2.1                     register.  This is the product of all the
102 pnkfelix 1.1.2.1                     delta-estimates for that candidate along all paths
103 pnkfelix 1.1.2.1                     to these loads and postexits.
104 pnkfelix 1.1.2.1                iii. If no stores have an estimate greater than 0, then
105 pnkfelix 1.1.2.1                     quit processing stores.
106 pnkfelix 1.1.2.1                iv.  Otherwise, remove the store with the greatest
107 pnkfelix 1.1.2.1                     figure of merit, and allocate the candidate a
108 pnkfelix 1.1.2.1                     register along all paths to the postexits.  This
109 pnkfelix 1.1.2.1                     requires putting stores in the loop's postexits.
110 pnkfelix 1.1.2.2          */
111 pnkfelix 1.1.2.2  
112 pnkfelix 1.1.2.2  
113 pnkfelix 1.1.2.2          /*
114 pnkfelix 1.1.2.2          
115 pnkfelix 1.1.2.2          3. Remove loads that are not in any loop (Use techniques
116 pnkfelix 1.1.2.2             described in (2a) above.)
117 pnkfelix 1.1.2.2          4. Remove stores that are not in any loop (Use techniques
118 pnkfelix 1.1.2.2             described in (2b) above).
119 pnkfelix 1.1.2.2  
120 pnkfelix 1.1.2.2          */
121 pnkfelix 1.1.2.2  
122 pnkfelix 1.1.2.2  
123 pnkfelix 1.1.2.2          /*
124 pnkfelix 1.1.2.2  
125 pnkfelix 1.1.2.2         5. Assign registers to all candidates allocated registers using 
126 pnkfelix 1.1.2.1            the Graph Coloring Framework.
127 pnkfelix 1.1.2.2  
128 pnkfelix 1.1.2.2          */
129 pnkfelix 1.1.2.2  
130 pnkfelix 1.1.2.11         return;
131 pnkfelix 1.1.2.2      }
132 pnkfelix 1.1.2.2      
133 pnkfelix 1.1.2.1  
134 pnkfelix 1.1.2.1      /** Delta computing function. Taken from the paper "Demand-Driven
135 pnkfelix 1.1.2.1          Register Allocation." 
136 pnkfelix 1.1.2.1          <BR> <B>requires:</B> <code>BasicBlock</code> is a set of
137 pnkfelix 1.1.2.1                <code>Instr</code>s. 
138 pnkfelix 1.1.2.1          <BR> <B>effects:</B> returns a 
139 pnkfelix 1.1.2.1          Map[TempInstrPair, Double] mapping 
140 pnkfelix 1.1.2.1          (instr x temp) -> deltaValue
141 pnkfelix 1.1.2.1      */
142 pnkfelix 1.1.2.1      private Map computeDeltas(BasicBlock block) {
143 pnkfelix 1.1.2.1          // initialize configuration
144 pnkfelix 1.1.2.1          
145 pnkfelix 1.1.2.3          // { variables allocated registers entering block };
146 pnkfelix 1.1.2.3          Set allocated = (Set) bbToAllocatedMap.get(block);
147 pnkfelix 1.1.2.3          
148 pnkfelix 1.1.2.3          // { live variables entering block } - allocated
149 pnkfelix 1.1.2.1          Set candidates = new HashSet();
150 pnkfelix 1.1.2.3          candidates.addAll((Set)bbToLiveVarMap.get(block));
151 pnkfelix 1.1.2.3  
152 pnkfelix 1.1.2.3          candidates.removeAll(allocated);
153 pnkfelix 1.1.2.1          
154 pnkfelix 1.1.2.3          // min( REGISTERS - |allocated|, |candidates| )
155 pnkfelix 1.1.2.17         int possibly = Math.min(frame.getRegFileInfo().getAllRegisters().length - 
156 pnkfelix 1.1.2.3                                  allocated.size(), candidates.size() );
157 pnkfelix 1.1.2.1          
158 pnkfelix 1.1.2.3          // REGISTERS - ( |allocated| + possibly )
159 pnkfelix 1.1.2.17         int unallocated = frame.getRegFileInfo().getAllRegisters().length - 
160 pnkfelix 1.1.2.1              (allocated.size() + possibly);
161 pnkfelix 1.1.2.1  
162 pnkfelix 1.1.2.1          // *** Implementation Specific local variables *** 
163 pnkfelix 1.1.2.3          
164 pnkfelix 1.1.2.3          // maps register uses in a particular instruction to the
165 pnkfelix 1.1.2.3          // variable that the register is storing.
166 pnkfelix 1.1.2.3          Map regXinstrToVarMap = new HashMap();
167 pnkfelix 1.1.2.1          
168 pnkfelix 1.1.2.1  
169 pnkfelix 1.1.2.1          // Iterate over instructions in order 
170 pnkfelix 1.1.2.1          
171 pnkfelix 1.1.2.10         ListIterator instrs = block.statements().listIterator();
172 pnkfelix 1.1.2.1          while(instrs.hasNext()) { 
173 pnkfelix 1.1.2.1              Instr instr = (Instr) instrs.next();
174 pnkfelix 1.1.2.1              double delta;
175 pnkfelix 1.1.2.3              
176 pnkfelix 1.1.2.1              { // BELOW: Last use of a register frees it
177 pnkfelix 1.1.2.3                  Vector regsFreedByInstr = new Vector(); 
178 pnkfelix 1.1.2.1                  for (int i=0; i<instr.use().length; i++) {
179 pnkfelix 1.1.2.12                     if (isRegister(instr.use()[i]) &&  
180 pnkfelix 1.1.2.1                          lastUse( instr.use()[i], instr, instrs)){ 
181 pnkfelix 1.1.2.3                          regsFreedByInstr.addElement(instr.use()[i]);
182 pnkfelix 1.1.2.1                      }
183 pnkfelix 1.1.2.1                  }
184 pnkfelix 1.1.2.1                  // for all f of { registers freed by instr }
185 pnkfelix 1.1.2.3                  for (int i=0;i<regsFreedByInstr.size();i++) { 
186 pnkfelix 1.1.2.3                      Temp f = (Temp) regsFreedByInstr.get(i);
187 pnkfelix 1.1.2.3                      
188 pnkfelix 1.1.2.1                      // Let t be value held in f
189 pnkfelix 1.1.2.1                      Temp t= (Temp) 
190 pnkfelix 1.1.2.3                          regXinstrToVarMap.get
191 pnkfelix 1.1.2.1                          (new TempInstrPair(instr, f)) ; 
192 pnkfelix 1.1.2.3                      
193 pnkfelix 1.1.2.1                      if (t != null) {
194 pnkfelix 1.1.2.1                          allocated.remove(t);
195 pnkfelix 1.1.2.1                          if(true) { // if t is a live variable
196 pnkfelix 1.1.2.1                              candidates.add(t);
197 pnkfelix 1.1.2.1                              possibly++;
198 pnkfelix 1.1.2.1                          } else {
199 pnkfelix 1.1.2.1                              unallocated++;
200 pnkfelix 1.1.2.1                          }
201 pnkfelix 1.1.2.1                      } else {
202 pnkfelix 1.1.2.1                          unallocated++;
203 pnkfelix 1.1.2.1                      }
204 pnkfelix 1.1.2.1                  }
205 pnkfelix 1.1.2.1              }
206 pnkfelix 1.1.2.1  
207 pnkfelix 1.1.2.1  
208 pnkfelix 1.1.2.1              { // BELOW: First use of a register allocates it
209 pnkfelix 1.1.2.1                  if (true) { // if instr allocated r, a register 
210 pnkfelix 1.1.2.1                      Temp v=null; // Let v be value held in r
211 pnkfelix 1.1.2.1                      allocated.add(v);
212 pnkfelix 1.1.2.1                      if (true) { // if v holds the value of variable
213 pnkfelix 1.1.2.1                                  // (ie not a Temporary)  
214 pnkfelix 1.1.2.1                          candidates.remove(v);
215 pnkfelix 1.1.2.1                      }
216 pnkfelix 1.1.2.1                      if (possibly > candidates.size() ) {
217 pnkfelix 1.1.2.1                          // Only occurs when possibly == |candidates| prior
218 pnkfelix 1.1.2.1                          // to satisfying preceding conditional
219 pnkfelix 1.1.2.1                          delta = 1.0;
220 pnkfelix 1.1.2.1                          possibly--;
221 pnkfelix 1.1.2.1                      } else if (unallocated > 0) {
222 pnkfelix 1.1.2.1                          // Allocating an empty register cannot kill
223 pnkfelix 1.1.2.1                          // anything
224 pnkfelix 1.1.2.1                          delta = 1.0;
225 pnkfelix 1.1.2.1                          unallocated--;
226 pnkfelix 1.1.2.1                      } else {
227 pnkfelix 1.1.2.1                          delta = ((double)(possibly-1)) /
228 pnkfelix 1.1.2.1                              ((double)possibly);
229 pnkfelix 1.1.2.1                          possibly--;
230 pnkfelix 1.1.2.1                      }
231 pnkfelix 1.1.2.1                  } else {
232 pnkfelix 1.1.2.1                      delta = 1.0;
233 pnkfelix 1.1.2.1                  }
234 pnkfelix 1.1.2.1              }
235 pnkfelix 1.1.2.1              
236 pnkfelix 1.1.2.1              for (;;) { // for all v elem candidates
237 pnkfelix 1.1.2.1                  // deltaTable[instr][v] = delta
238 pnkfelix 1.1.2.1              }
239 pnkfelix 1.1.2.1          }
240 pnkfelix 1.1.2.1  
241 pnkfelix 1.1.2.1          return null;
242 pnkfelix 1.1.2.1  
243 pnkfelix 1.1.2.1      }       
244 pnkfelix 1.1.2.3  
245 pnkfelix 1.1.2.3      private Map findLiveVars(Code code) {
246 cananian 1.1.2.14         UseDefMap useMap = new harpoon.Analysis.UseDef(/*code*/);
247 pnkfelix 1.1.2.3          return null;
248 pnkfelix 1.1.2.3      }
249 pnkfelix 1.1.2.1  
250 pnkfelix 1.1.2.1  }
251 cananian 1.2