A def. operand of a machine instruction may be an ordinary Value*,
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9RegClassInfo.cpp
1 //===-- SparcRegClassInfo.cpp - Register class def'ns for Sparc -----------===//
2 //
3 //  This file defines the register classes used by the Sparc target description.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "SparcRegClassInfo.h"
8 #include "llvm/Type.h"
9 #include "../../CodeGen/RegAlloc/RegAllocCommon.h"   // FIXME!
10
11 //-----------------------------------------------------------------------------
12 // Int Register Class - method for coloring a node in the interference graph.
13 //
14 // Algorithm:
15 //     Record the colors/suggested colors of all neighbors.
16 //
17 //     If there is a suggested color, try to allocate it
18 //     If there is no call interf, try to allocate volatile, then non volatile
19 //     If there is call interf, try to allocate non-volatile. If that fails
20 //     try to allocate a volatile and insert save across calls
21 //     If both above fail, spill.
22 //  
23 //-----------------------------------------------------------------------------
24 void SparcIntRegClass::colorIGNode(IGNode * Node,
25                                    std::vector<bool> &IsColorUsedArr) const
26 {
27   LiveRange *LR = Node->getParentLR();
28
29   if (DEBUG_RA) {
30     std::cerr << "\nColoring LR [CallInt=" << LR->isCallInterference() <<"]:"; 
31     printSet(*LR);
32   }
33
34   if (LR->hasSuggestedColor()) {
35     unsigned SugCol = LR->getSuggestedColor();
36     if (!IsColorUsedArr[SugCol]) {
37       if (LR->isSuggestedColorUsable()) {
38         // if the suggested color is volatile, we should use it only if
39         // there are no call interferences. Otherwise, it will get spilled.
40         if (DEBUG_RA)
41           std::cerr << "\n  -Coloring with sug color: " << SugCol;
42
43         LR->setColor(LR->getSuggestedColor());
44         return;
45       } else if(DEBUG_RA) {
46         std::cerr << "\n Couldn't alloc Sug col - LR volatile & calls interf";
47       }
48     } else if (DEBUG_RA) {                // can't allocate the suggested col
49       std::cerr << "\n  Could NOT allocate the suggested color (already used) ";
50       printSet(*LR); std::cerr << "\n";
51     }
52   }
53
54   unsigned SearchStart;                 // start pos of color in pref-order
55   bool ColorFound= false;               // have we found a color yet?
56
57   //if this Node is between calls
58   if (! LR->isCallInterference()) { 
59     // start with volatiles (we can  allocate volatiles safely)
60     SearchStart = SparcIntRegClass::StartOfAllRegs;  
61   } else {           
62     // start with non volatiles (no non-volatiles)
63     SearchStart =  SparcIntRegClass::StartOfNonVolatileRegs;  
64   }
65
66   unsigned c=0;                         // color
67  
68   // find first unused color
69   for (c=SearchStart; c < SparcIntRegClass::NumOfAvailRegs; c++) { 
70     if (!IsColorUsedArr[c]) {
71       ColorFound = true;
72       break;
73     }
74   }
75
76   if (ColorFound) {
77     LR->setColor(c);                  // first color found in preffered order
78     if (DEBUG_RA) std::cerr << "\n  Colored after first search with col " << c;
79   }
80
81   // if color is not found because of call interference
82   // try even finding a volatile color and insert save across calls
83   //
84   else if (LR->isCallInterference()) {
85     // start from 0 - try to find even a volatile this time
86     SearchStart = SparcIntRegClass::StartOfAllRegs;  
87
88     // find first unused volatile color
89     for(c=SearchStart; c < SparcIntRegClass::StartOfNonVolatileRegs; c++) { 
90       if (! IsColorUsedArr[c]) {
91         ColorFound = true;
92         break;
93       }
94     }
95
96     if (ColorFound) { 
97       LR->setColor(c);  
98       //  get the live range corresponding to live var
99       // since LR span across calls, must save across calls 
100       //
101       LR->markForSaveAcrossCalls();       
102       if (DEBUG_RA)
103         std::cerr << "\n  Colored after SECOND search with col " << c;
104     }
105   }
106
107
108   // If we couldn't find a color regardless of call interference - i.e., we
109   // don't have either a volatile or non-volatile color left
110   //
111   if (!ColorFound)  
112     LR->markForSpill();               // no color found - must spill
113 }
114
115
116 //-----------------------------------------------------------------------------
117 // Float Register Class - method for coloring a node in the interference graph.
118 //
119 // Algorithm:
120 //
121 //     If the LR is a double try to allocate f32 - f63
122 //     If the above fails or LR is single precision
123 //        If the LR does not interfere with a call
124 //         start allocating from f0
125 //      Else start allocating from f6
126 //     If a color is still not found because LR interferes with a call
127 //        Search in f0 - f6. If found mark for spill across calls.
128 //     If a color is still not fond, mark for spilling
129 //
130 //----------------------------------------------------------------------------
131 void SparcFloatRegClass::colorIGNode(IGNode * Node,
132                                      std::vector<bool> &IsColorUsedArr) const
133 {
134   LiveRange *LR = Node->getParentLR();
135
136   // Mark the second color for double-precision registers:
137   // This is UGLY and should be merged into nearly identical code
138   // in RegClass::colorIGNode that handles the first color.
139   // 
140   unsigned NumNeighbors =  Node->getNumOfNeighbors();   // total # of neighbors
141   for(unsigned n=0; n < NumNeighbors; n++) {            // for each neigh 
142     IGNode *NeighIGNode = Node->getAdjIGNode(n);
143     LiveRange *NeighLR = NeighIGNode->getParentLR();
144     
145     if (NeighLR->hasColor() &&
146         NeighLR->getType() == Type::DoubleTy) {
147       IsColorUsedArr[ (NeighLR->getColor()) + 1 ] = true;  
148       
149     } else if (NeighLR->hasSuggestedColor() &&
150                NeighLR-> isSuggestedColorUsable() ) {
151
152       // if the neighbour can use the suggested color 
153       IsColorUsedArr[ NeighLR->getSuggestedColor() ] = true;
154       if (NeighLR->getType() == Type::DoubleTy)
155         IsColorUsedArr[ (NeighLR->getSuggestedColor()) + 1 ] = true;  
156     }
157   }
158
159   // **NOTE: We don't check for call interferences in allocating suggested
160   // color in this class since ALL registers are volatile. If this fact
161   // changes, we should change the following part 
162   //- see SparcIntRegClass::colorIGNode()
163   // 
164   if( LR->hasSuggestedColor() ) {
165     if( ! IsColorUsedArr[ LR->getSuggestedColor() ] ) {
166       LR->setColor(  LR->getSuggestedColor() );
167       return;
168     } else if (DEBUG_RA)  {                 // can't allocate the suggested col
169       std::cerr << " Could NOT allocate the suggested color for LR ";
170       printSet(*LR); std::cerr << "\n";
171     }
172   }
173
174
175   int ColorFound = -1;               // have we found a color yet?
176   bool isCallInterf = LR->isCallInterference();
177
178   // if value is a double - search the double only region (f32 - f63)
179   // i.e. we try to allocate f32 - f63 first for doubles since singles
180   // cannot go there. By doing that, we provide more space for singles
181   // in f0 - f31
182   //
183   if (LR->getType() == Type::DoubleTy)       
184     ColorFound = findFloatColor( LR, 32, 64, IsColorUsedArr );
185
186   if (ColorFound >= 0) {               // if we could find a color
187     LR->setColor(ColorFound);                
188     return;
189   } else { 
190
191     // if we didn't find a color becuase the LR was single precision or
192     // all f32-f63 range is filled, we try to allocate a register from
193     // the f0 - f31 region 
194
195     unsigned SearchStart;                 // start pos of color in pref-order
196
197     //if this Node is between calls (i.e., no call interferences )
198     if (! isCallInterf) {
199       // start with volatiles (we can  allocate volatiles safely)
200       SearchStart = SparcFloatRegClass::StartOfAllRegs;  
201     } else {
202       // start with non volatiles (no non-volatiles)
203       SearchStart =  SparcFloatRegClass::StartOfNonVolatileRegs;  
204     }
205     
206     ColorFound = findFloatColor(LR, SearchStart, 32, IsColorUsedArr);
207   }
208
209   if (ColorFound >= 0) {               // if we could find a color
210     LR->setColor(ColorFound);                  
211     return;
212   } else if (isCallInterf) { 
213     // We are here because there is a call interference and no non-volatile
214     // color could be found.
215     // Now try to allocate even a volatile color
216     ColorFound = findFloatColor(LR, SparcFloatRegClass::StartOfAllRegs, 
217                                 SparcFloatRegClass::StartOfNonVolatileRegs,
218                                 IsColorUsedArr);
219   }
220
221   if (ColorFound >= 0) {
222     LR->setColor(ColorFound);         // first color found in prefered order
223     LR->markForSaveAcrossCalls();  
224   } else {
225     // we are here because no color could be found
226     LR->markForSpill();               // no color found - must spill
227   }
228 }
229
230
231 //-----------------------------------------------------------------------------
232 // Helper method for coloring a node of Float Reg class.
233 // Finds the first available color in the range [Start,End] depending on the
234 // type of the Node (i.e., float/double)
235 //-----------------------------------------------------------------------------
236
237 int SparcFloatRegClass::findFloatColor(const LiveRange *LR, 
238                                        unsigned Start,
239                                        unsigned End, 
240                                        std::vector<bool> &IsColorUsedArr) const
241 {
242   bool ColorFound = false;
243   unsigned c;
244
245   if (LR->getType() == Type::DoubleTy) { 
246     // find first unused color for a double 
247     for (c=Start; c < End ; c+= 2)
248       if (!IsColorUsedArr[c] && !IsColorUsedArr[c+1]) 
249         return c;
250   } else {
251     // find first unused color for a single
252     for (c = Start; c < End; c++)
253       if (!IsColorUsedArr[c])
254         return c;
255   }
256   
257   return -1;
258 }