Get rid of calls to void llvm::printSet(const ValueSet &).
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9RegClassInfo.cpp
1 //===-- SparcV9RegClassInfo.cpp - Register class def'ns for SparcV9 -------===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the methods used by the SparcV9 register allocator
11 // to pick registers of various classes.  Most of this code should be
12 // considered part of the register allocator.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm/Type.h"
17 #include "SparcV9RegClassInfo.h"
18 #include "SparcV9Internals.h"
19 #include "SparcV9RegInfo.h"
20 #include "RegAlloc/RegAllocCommon.h"
21 #include "RegAlloc/IGNode.h"
22 #include <iostream>
23
24 namespace llvm {
25
26 //-----------------------------------------------------------------------------
27 // Int Register Class - method for coloring a node in the interference graph.
28 //
29 // Algorithm:
30 //     Record the colors/suggested colors of all neighbors.
31 //
32 //     If there is a suggested color, try to allocate it
33 //     If there is no call interf, try to allocate volatile, then non volatile
34 //     If there is call interf, try to allocate non-volatile. If that fails
35 //     try to allocate a volatile and insert save across calls
36 //     If both above fail, spill.
37 //  
38 //-----------------------------------------------------------------------------
39 void SparcV9IntRegClass::colorIGNode(IGNode * Node,
40                                const std::vector<bool> &IsColorUsedArr) const
41 {
42   LiveRange *LR = Node->getParentLR();
43
44   if (DEBUG_RA)
45     std::cerr << "\nColoring LR [CallInt=" << LR->isCallInterference() <<"]:"
46               << *LR << "\n"; 
47
48   if (LR->hasSuggestedColor()) {
49     unsigned SugCol = LR->getSuggestedColor();
50     if (!IsColorUsedArr[SugCol]) {
51       if (LR->isSuggestedColorUsable()) {
52         // if the suggested color is volatile, we should use it only if
53         // there are no call interferences. Otherwise, it will get spilled.
54         if (DEBUG_RA)
55           std::cerr << "\n  -Coloring with sug color: " << SugCol;
56
57         LR->setColor(LR->getSuggestedColor());
58         return;
59       } else if(DEBUG_RA) {
60         std::cerr << "\n Couldn't alloc Sug col - LR volatile & calls interf";
61       }
62     } else if (DEBUG_RA) {                // can't allocate the suggested col
63       std::cerr << "\n  Could NOT allocate the suggested color (already used) "
64                 << *LR << "\n";
65     }
66   }
67
68   unsigned SearchStart;                 // start pos of color in pref-order
69   bool ColorFound= false;               // have we found a color yet?
70
71   //if this Node is between calls
72   if (! LR->isCallInterference()) { 
73     // start with volatiles (we can  allocate volatiles safely)
74     SearchStart = SparcV9IntRegClass::StartOfAllRegs;  
75   } else {           
76     // start with non volatiles (no non-volatiles)
77     SearchStart =  SparcV9IntRegClass::StartOfNonVolatileRegs;  
78   }
79
80   unsigned c=0;                         // color
81  
82   // find first unused color
83   for (c=SearchStart; c < SparcV9IntRegClass::NumOfAvailRegs; c++) { 
84     if (!IsColorUsedArr[c]) {
85       ColorFound = true;
86       break;
87     }
88   }
89
90   if (ColorFound) {
91     LR->setColor(c);                  // first color found in preferred order
92     if (DEBUG_RA) std::cerr << "\n  Colored after first search with col " << c;
93   }
94
95   // if color is not found because of call interference
96   // try even finding a volatile color and insert save across calls
97   //
98   else if (LR->isCallInterference()) {
99     // start from 0 - try to find even a volatile this time
100     SearchStart = SparcV9IntRegClass::StartOfAllRegs;  
101
102     // find first unused volatile color
103     for(c=SearchStart; c < SparcV9IntRegClass::StartOfNonVolatileRegs; c++) { 
104       if (! IsColorUsedArr[c]) {
105         ColorFound = true;
106         break;
107       }
108     }
109
110     if (ColorFound) { 
111       LR->setColor(c);  
112       //  get the live range corresponding to live var
113       // since LR span across calls, must save across calls 
114       //
115       if (DEBUG_RA)
116         std::cerr << "\n  Colored after SECOND search with col " << c;
117     }
118   }
119
120
121   // If we couldn't find a color regardless of call interference - i.e., we
122   // don't have either a volatile or non-volatile color left
123   //
124   if (!ColorFound)  
125     LR->markForSpill();               // no color found - must spill
126 }
127
128 //-----------------------------------------------------------------------------
129 // Int CC Register Class - method for coloring a node in the interference graph.
130 //
131 // Algorithm:
132 //
133 //     If (node has any interferences)
134 //         /* all interference operations can use only one register! */
135 //         mark the LR for spilling
136 //     else {
137 //         if (the LR is a 64-bit comparison) use %xcc
138 //         else /*32-bit or smaller*/ use %icc
139 //     }
140 // 
141 // Note: The third name (%ccr) is essentially an assembly mnemonic and
142 // depends solely on the opcode, so the name can be chosen in EmitAssembly.
143 //-----------------------------------------------------------------------------
144 void SparcV9IntCCRegClass::colorIGNode(IGNode *Node,
145                                  const std::vector<bool> &IsColorUsedArr) const
146 {
147   if (Node->getNumOfNeighbors() > 0)
148     Node->getParentLR()->markForSpill();
149
150   // Mark the appropriate register in any case (even if it needs to be spilled)
151   // because there is only one possible register, but more importantly, the
152   // spill algorithm cannot find it.  In particular, we have to choose
153   // whether to use %xcc or %icc based on type of value compared
154   // 
155   const LiveRange* ccLR = Node->getParentLR();
156   const Type* setCCType = (* ccLR->begin())->getType(); // any Value in LR
157   assert(setCCType->isIntegral() || isa<PointerType>(setCCType));
158   int ccReg = ((isa<PointerType>(setCCType) || setCCType == Type::LongTy)
159                ? xcc : icc);
160
161 #ifndef NDEBUG
162   // Let's just make sure values of two different types have not been
163   // coalesced into this LR.
164   for (LiveRange::const_iterator I=ccLR->begin(), E=ccLR->end(); I!=E; ++I) {
165     const Type* ccType = (*I)->getType();
166     assert((ccReg == xcc && (isa<PointerType>(ccType)
167                              || ccType == Type::LongTy)) ||
168            (ccReg == icc && ccType->isIntegral() && ccType != Type::LongTy)
169            && "Comparisons needing different intCC regs coalesced in LR!");
170   }
171 #endif
172
173   Node->setColor(ccReg);                // only one int cc reg is available
174 }
175
176
177 void SparcV9FloatCCRegClass::colorIGNode(IGNode *Node,
178                                 const std::vector<bool> &IsColorUsedArr) const {
179   for(unsigned c = 0; c != 4; ++c)
180     if (!IsColorUsedArr[c]) { // find unused color
181       Node->setColor(c);   
182       return;
183     }
184   
185   Node->getParentLR()->markForSpill();
186 }
187
188
189
190 //-----------------------------------------------------------------------------
191 // Float Register Class - method for coloring a node in the interference graph.
192 //
193 // Algorithm:
194 //
195 //     If the LR is a double try to allocate f32 - f63
196 //     If the above fails or LR is single precision
197 //        If the LR does not interfere with a call
198 //         start allocating from f0
199 //      Else start allocating from f6
200 //     If a color is still not found because LR interferes with a call
201 //        Search in f0 - f6. If found mark for spill across calls.
202 //     If a color is still not fond, mark for spilling
203 //
204 //----------------------------------------------------------------------------
205 void SparcV9FloatRegClass::colorIGNode(IGNode * Node,
206                                  const std::vector<bool> &IsColorUsedArr) const
207 {
208   LiveRange *LR = Node->getParentLR();
209
210 #ifndef NDEBUG
211   // Check that the correct colors have been are marked for fp-doubles.
212   // 
213   // FIXME: This is old code that is no longer needed.  Temporarily converting
214   // it into a big assertion just to check that the replacement logic
215   // (invoking SparcV9FloatRegClass::markColorsUsed() directly from
216   // RegClass::colorIGNode) works correctly.
217   // 
218   // In fact, this entire function should be identical to
219   // SparcV9IntRegClass::colorIGNode(), and perhaps can be
220   // made into a general case in CodeGen/RegAlloc/RegClass.cpp.  
221   // 
222   unsigned NumNeighbors =  Node->getNumOfNeighbors();   // total # of neighbors
223   for(unsigned n=0; n < NumNeighbors; n++) {            // for each neigh 
224     IGNode *NeighIGNode = Node->getAdjIGNode(n);
225     LiveRange *NeighLR = NeighIGNode->getParentLR();
226     
227     if (NeighLR->hasColor()) {
228       assert(IsColorUsedArr[ NeighLR->getColor() ]);
229       if (NeighLR->getType() == Type::DoubleTy)
230         assert(IsColorUsedArr[ NeighLR->getColor()+1 ]);
231       
232     } else if (NeighLR->hasSuggestedColor() &&
233                NeighLR-> isSuggestedColorUsable() ) {
234
235       // if the neighbour can use the suggested color 
236       assert(IsColorUsedArr[ NeighLR->getSuggestedColor() ]);
237       if (NeighLR->getType() == Type::DoubleTy)
238         assert(IsColorUsedArr[ NeighLR->getSuggestedColor()+1 ]);
239     }
240   }
241 #endif
242
243   // **NOTE: We don't check for call interferences in allocating suggested
244   // color in this class since ALL registers are volatile. If this fact
245   // changes, we should change the following part 
246   //- see SparcV9IntRegClass::colorIGNode()
247   // 
248   if( LR->hasSuggestedColor() ) {
249     if( ! IsColorUsedArr[ LR->getSuggestedColor() ] ) {
250       LR->setColor(  LR->getSuggestedColor() );
251       return;
252     } else if (DEBUG_RA)  {                 // can't allocate the suggested col
253       std::cerr << " Could NOT allocate the suggested color for LR " << *LR
254                 << "\n";
255     }
256   }
257
258
259   int ColorFound = -1;               // have we found a color yet?
260   bool isCallInterf = LR->isCallInterference();
261
262   // if value is a double - search the double only region (f32 - f63)
263   // i.e. we try to allocate f32 - f63 first for doubles since singles
264   // cannot go there. By doing that, we provide more space for singles
265   // in f0 - f31
266   //
267   if (LR->getType() == Type::DoubleTy)       
268     ColorFound = findFloatColor( LR, 32, 64, IsColorUsedArr );
269
270   if (ColorFound >= 0) {               // if we could find a color
271     LR->setColor(ColorFound);                
272     return;
273   } else { 
274
275     // if we didn't find a color because the LR was single precision or
276     // all f32-f63 range is filled, we try to allocate a register from
277     // the f0 - f31 region 
278
279     unsigned SearchStart;                 // start pos of color in pref-order
280
281     //if this Node is between calls (i.e., no call interferences )
282     if (! isCallInterf) {
283       // start with volatiles (we can  allocate volatiles safely)
284       SearchStart = SparcV9FloatRegClass::StartOfAllRegs;  
285     } else {
286       // start with non volatiles (no non-volatiles)
287       SearchStart =  SparcV9FloatRegClass::StartOfNonVolatileRegs;  
288     }
289     
290     ColorFound = findFloatColor(LR, SearchStart, 32, IsColorUsedArr);
291   }
292
293   if (ColorFound >= 0) {               // if we could find a color
294     LR->setColor(ColorFound);                  
295     return;
296   } else if (isCallInterf) { 
297     // We are here because there is a call interference and no non-volatile
298     // color could be found.
299     // Now try to allocate even a volatile color
300     ColorFound = findFloatColor(LR, SparcV9FloatRegClass::StartOfAllRegs, 
301                                 SparcV9FloatRegClass::StartOfNonVolatileRegs,
302                                 IsColorUsedArr);
303   }
304
305   if (ColorFound >= 0) {
306     LR->setColor(ColorFound);         // first color found in preferred order
307   } else {
308     // we are here because no color could be found
309     LR->markForSpill();               // no color found - must spill
310   }
311 }
312
313 //-----------------------------------------------------------------------------
314 // This method marks the registers used for a given register number.
315 // This marks a single register for Float regs, but the R,R+1 pair
316 // for double-precision registers.
317 //-----------------------------------------------------------------------------
318
319 void SparcV9FloatRegClass::markColorsUsed(unsigned RegInClass,
320                                         int UserRegType,
321                                         int RegTypeWanted,
322                                     std::vector<bool> &IsColorUsedArr) const
323 {
324   if (UserRegType == SparcV9RegInfo::FPDoubleRegType ||
325       RegTypeWanted == SparcV9RegInfo::FPDoubleRegType) {
326     // This register is used as or is needed as a double-precision reg.
327     // We need to mark the [even,odd] pair corresponding to this reg.
328     // Get the even numbered register corresponding to this reg.
329     unsigned EvenRegInClass = RegInClass & ~1u;
330     assert(EvenRegInClass+1 < NumOfAllRegs &&
331            EvenRegInClass+1 < IsColorUsedArr.size());
332     IsColorUsedArr[EvenRegInClass]   = true;
333     IsColorUsedArr[EvenRegInClass+1] = true;
334   }
335   else {
336     assert(RegInClass < NumOfAllRegs && RegInClass < IsColorUsedArr.size());
337     assert(UserRegType == RegTypeWanted
338            && "Something other than FP single/double types share a reg class?");
339     IsColorUsedArr[RegInClass] = true;
340   }
341 }
342
343 // This method finds unused registers of the specified register type,
344 // using the given "used" flag array IsColorUsedArr.  It checks a single
345 // entry in the array directly for float regs, and checks the pair [R,R+1]
346 // for double-precision registers
347 // It returns -1 if no unused color is found.
348 // 
349 int SparcV9FloatRegClass::findUnusedColor(int RegTypeWanted,
350                                 const std::vector<bool> &IsColorUsedArr) const
351 {
352   if (RegTypeWanted == SparcV9RegInfo::FPDoubleRegType) {
353     unsigned NC = 2 * this->getNumOfAvailRegs();
354     assert(IsColorUsedArr.size() == NC && "Invalid colors-used array");
355     for (unsigned c = 0; c < NC; c+=2)
356       if (!IsColorUsedArr[c]) {
357         assert(!IsColorUsedArr[c+1] && "Incorrect used regs for FP double!");
358         return c;
359       }
360     return -1;
361   }
362   else
363     return TargetRegClassInfo::findUnusedColor(RegTypeWanted, IsColorUsedArr);
364 }
365
366 //-----------------------------------------------------------------------------
367 // Helper method for coloring a node of Float Reg class.
368 // Finds the first available color in the range [Start,End] depending on the
369 // type of the Node (i.e., float/double)
370 //-----------------------------------------------------------------------------
371
372 int SparcV9FloatRegClass::findFloatColor(const LiveRange *LR, 
373                                        unsigned Start,
374                                        unsigned End, 
375                                const std::vector<bool> &IsColorUsedArr) const
376 {
377   if (LR->getType() == Type::DoubleTy) { 
378     // find first unused color for a double 
379     assert(Start % 2 == 0 && "Odd register number could be used for double!");
380     for (unsigned c=Start; c < End ; c+= 2)
381       if (!IsColorUsedArr[c]) {
382         assert(!IsColorUsedArr[c+1] &&
383                "Incorrect marking of used regs for SparcV9 FP double!");
384         return c;
385       }
386   } else {
387     // find first unused color for a single
388     for (unsigned c = Start; c < End; c++)
389       if (!IsColorUsedArr[c])
390         return c;
391   }
392
393   return -1;
394
395 }
396
397 } // End llvm namespace