ec4868b938dce1dcb424d87ec978c49c59ad1818
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9RegInfo.cpp
1 #include "llvm/Target/Sparc.h"
2 #include "SparcInternals.h"
3 #include "llvm/Method.h"
4 #include "llvm/iTerminators.h"
5 #include "llvm/CodeGen/InstrScheduling.h"
6 #include "llvm/CodeGen/InstrSelection.h"
7
8 #include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
9 #include "llvm/CodeGen/PhyRegAlloc.h"
10
11
12
13
14 //---------------------------------------------------------------------------
15 // UltraSparcRegInfo
16 //---------------------------------------------------------------------------
17
18 /*
19 Rules for coloring values with sepcial registers:
20 =================================================
21
22 The following are the cases we color values with special regs:
23
24 1) Incoming Method Arguements
25 2) Outgoing Call Arguments
26 3) Return Value of a call
27 4) Return Value of a return statement
28
29 Both 1 and 3 are defs. Therefore, they can be set directly. For case 1, 
30 incoming args are colored to %i0-%i5 and %f0 - %fx. For case 3, the return
31 value of the call must be colored to %o0 or %f0.
32
33 For case 2 we can use %o0-%o6 and %f0- %fx and for case 4 we can use %i0 or
34 %f0. However, we cannot pre-color them directly to those regs
35 if there are call interferences or they can be already colred by case 1.
36 (Note that a return value is call is already colored and it is registered
37 as a call interference as well if it is live after the call). Otherwise, they
38 can be precolored. In cases where we cannot precolor, we just have to insert 
39 a copy instruction to copy the LR to the required register.
40
41 */
42
43
44
45 //---------------------------------------------------------------------------
46 //   This method will color incoming args to a method. If there are more
47 //   args than that can fit in regs, code will be inserted to pop them from
48 //   stack
49 //---------------------------------------------------------------------------
50
51 void UltraSparcRegInfo::colorArgs(const Method *const Meth, 
52                                   LiveRangeInfo& LRI) const 
53 {
54
55                                                  // get the argument list
56   const Method::ArgumentListType& ArgList = Meth->getArgumentList();           
57                                                  // get an iterator to arg list
58   Method::ArgumentListType::const_iterator ArgIt = ArgList.begin(); 
59   unsigned intArgNo=0;
60
61   // to keep track of which float regs are allocated for argument passing
62   bool FloatArgUsedArr[NumOfFloatArgRegs];
63
64   // init float arg used array
65   for(unsigned i=0; i < NumOfFloatArgRegs; ++i) 
66     FloatArgUsedArr[i] = false;
67
68   // for each argument
69   for( ; ArgIt != ArgList.end() ; ++ArgIt) {    
70
71     // get the LR of arg
72     LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt); 
73     unsigned RegClassID = (LR->getRegClass())->getID();
74
75     // if the arg is in int class - allocate a reg for an int arg
76     if( RegClassID == IntRegClassID ) {
77
78       if( intArgNo < NumOfIntArgRegs) {
79         LR->setColor( SparcIntRegOrder::i0 + intArgNo );
80
81         if( DEBUG_RA) printReg( LR );
82       }
83   
84       else {
85         // TODO: Insert push code here
86         assert( 0 && "Insert push code here!");
87       }
88       ++intArgNo;
89     }
90
91     // if the arg is float/double 
92     else if ( RegClassID == FloatRegClassID) {
93
94       if( LR->getTypeID() == Type::DoubleTyID ) {
95
96         // find the first reg # we can pass a double arg
97         for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
98           if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
99             LR->setColor( SparcFloatRegOrder::f0 + i );
100             FloatArgUsedArr[i] = true;
101             FloatArgUsedArr[i+1] = true;
102             if( DEBUG_RA) printReg( LR );
103             break;
104           }
105         }
106         if( ! LR->hasColor() ) { // if LR was not colored above
107
108           assert(0 && "insert push code here for a double");
109
110         }
111
112       }
113       else if( LR->getTypeID() == Type::FloatTyID ) { 
114
115         // find the first reg # we can pass a float arg
116         for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
117           if ( !FloatArgUsedArr[i] ) {
118             LR->setColor( SparcFloatRegOrder::f0 + i );
119             FloatArgUsedArr[i] = true;
120             if( DEBUG_RA) printReg( LR );
121             break;
122           }
123         }
124         if( ! LR->hasColor() ) { // if LR was not colored above
125           assert(0 && "insert push code here for a float");
126         }
127
128       }
129       else 
130         assert(0 && "unknown float type in method arg");
131
132     } // float register class
133
134     else 
135       assert(0 && "Unknown RegClassID");
136   }
137   
138 }
139
140
141
142
143
144
145 void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> & 
146                                       CallInstrList, LiveRangeInfo& LRI,
147                                       AddedInstrMapType &AddedInstrMap) const
148 {
149
150   vector<const Instruction *>::const_iterator InstIt;
151
152   // First color the return value of all call instructions. The return value
153   // will be in %o0 if the value is an integer type, or in %f0 if the 
154   // value is a float type.
155
156   for(InstIt=CallInstrList.begin(); InstIt != CallInstrList.end(); ++InstIt) {
157
158     const Instruction *const CallI = *InstIt;
159
160     // get the live range of return value of this call
161     LiveRange *const LR = LRI.getLiveRangeForValue( CallI ); 
162
163     if ( LR ) {
164
165       // Since the call is a def, it cannot be colored by some other instr.
166       // Therefore, we can definitely set a color here.
167       // However, this def can be used by some other instr like another call
168       // or return which places that in a special register. In that case
169       // it has to put a copy. Note that, the def will have a call interference
170       // with this call instr itself if it is live after this call.
171
172       assert( ! LR->hasColor() && "Can't have a color since this is a def");
173
174       unsigned RegClassID = (LR->getRegClass())->getID();
175       
176       if( RegClassID == IntRegClassID ) {
177         LR->setColor(SparcIntRegOrder::o0);
178       }
179       else if (RegClassID == FloatRegClassID ) {
180         LR->setColor(SparcFloatRegOrder::f0 );
181       }
182     }
183     else {
184       cout << "Warning: No Live Range for return value of CALL" << endl;
185     }
186   }
187
188
189   for( InstIt=CallInstrList.begin(); InstIt != CallInstrList.end(); ++InstIt) {
190
191     // Inst = LLVM call instruction
192     const Instruction *const CallI = *InstIt;
193
194     // find the CALL/JMMPL machine instruction
195     MachineCodeForVMInstr &  MInstVec = CallI->getMachineInstrVec();
196     MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
197
198     /*
199     for( ; MIIt != MInstVec.end() && 
200            ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode()); 
201          ++MIIt );
202
203     assert( (MIIt != MInstVec.end())  && "CALL/JMPL not found");
204     */
205
206     assert(getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode()) &&
207            "First machine instruction is not a Call/JMPL Machine Instr");
208
209     // CallMI = CALL/JMPL machine isntruction
210     const MachineInstr *const CallMI = *MIIt;
211
212     Instruction::op_const_iterator OpIt = CallI->op_begin();
213
214     unsigned intArgNo=0;
215
216
217     // to keep track of which float regs are allocated for argument passing
218     bool FloatArgUsedArr[NumOfFloatArgRegs];
219
220     // init float arg used array
221     for(unsigned i=0; i < NumOfFloatArgRegs; ++i) 
222       FloatArgUsedArr[i] = false;
223
224     // go thru all the operands of LLVM instruction
225     for( ; OpIt != CallI->op_end(); ++OpIt ) {
226
227       // get the LR of call operand (parameter)
228       LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt); 
229
230       if ( !LR ) {
231         cout << " Warning: In call instr, no LR for arg: " ;
232         printValue(*OpIt);
233         cout << endl;
234         continue;
235       }
236
237       unsigned RegClassID = (LR->getRegClass())->getID();
238       
239       // if the arg is in int class - allocate a reg for an int arg
240       if( RegClassID == IntRegClassID ) {
241         
242         if( intArgNo < NumOfIntArgRegs) {
243           setCallOrRetArgCol( LR, SparcIntRegOrder::o0 + intArgNo, 
244                               CallMI, AddedInstrMap);
245         }
246         
247         else {
248           // TODO: Insert push code here
249           assert( 0 && "Insert push code here!");
250
251           AddedInstrns * AI = AddedInstrMap[ CallMI ];
252           if( ! AI ) AI = new AddedInstrns();
253
254           // AI->InstrnsBefore.push_back( getStackPushInstr(LR) );
255           AddedInstrMap[ CallMI ] = AI;
256           
257         }
258         ++intArgNo;
259       }
260       
261       // if the arg is float/double 
262       else if ( RegClassID == FloatRegClassID) {
263         
264         if( LR->getTypeID() == Type::DoubleTyID ) {
265           
266           // find the first reg # we can pass a double arg
267           for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
268             if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
269               setCallOrRetArgCol(LR, SparcFloatRegOrder::f0 + i,
270                                  CallMI, AddedInstrMap);                    
271               FloatArgUsedArr[i] = true;
272               FloatArgUsedArr[i+1] = true;
273               //if( DEBUG_RA) printReg( LR );
274               break;
275             }
276           }
277           if( ! LR->hasColor() ) { // if LR was not colored above
278             
279             assert(0 && "insert push code here for a double");
280             
281           }
282           
283         }
284         else if( LR->getTypeID() == Type::FloatTyID ) { 
285           
286           // find the first reg # we can pass a float arg
287           for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
288             if ( !FloatArgUsedArr[i] ) {
289               setCallOrRetArgCol(LR, SparcFloatRegOrder::f0 + i,
290                                  CallMI, AddedInstrMap);
291               FloatArgUsedArr[i] = true;
292               // LR->setColor( SparcFloatRegOrder::f0 + i );
293               // if( DEBUG_RA) printReg( LR );
294               break;
295             }
296           }
297           if( ! LR->hasColor() ) { // if LR was not colored above
298             assert(0 && "insert push code here for a float");
299           }
300           
301         }
302         else 
303           assert(0 && "unknown float type in method arg");
304         
305       } // float register class
306       
307       else 
308         assert(0 && "Unknown RegClassID");
309
310
311     } // for each operand in a call instruction
312
313
314
315
316
317   } // for all call instrctions in CallInstrList
318
319 }
320
321
322
323
324
325 void UltraSparcRegInfo::colorRetArg(vector<const Instruction *> & 
326                                     RetInstrList, LiveRangeInfo& LRI,
327                                     AddedInstrMapType &AddedInstrMap) const
328 {
329
330   vector<const Instruction *>::const_iterator InstIt;
331
332
333   for(InstIt=RetInstrList.begin(); InstIt != RetInstrList.end(); ++InstIt) {
334
335     const ReturnInst *const RetI = (ReturnInst *) *InstIt;
336
337     // get the return value of this return instruction
338     const Value *RetVal =  (RetI)->getReturnValue();
339
340     if( RetVal ) {
341
342       // find the CALL/JMMPL machine instruction
343       MachineCodeForVMInstr &  MInstVec = RetI->getMachineInstrVec();
344       MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
345
346       assert(getUltraSparcInfo().getInstrInfo().isReturn((*MIIt)->getOpCode())
347              && "First machine instruction is not a RET Machine Instr");
348       // RET machine isntruction
349       const MachineInstr *const RetMI = *MIIt;
350
351       LiveRange *const LR = LRI.getLiveRangeForValue( RetVal ); 
352       unsigned RegClassID = (LR->getRegClass())->getID();
353
354       if ( LR ) {      
355         if( RegClassID == IntRegClassID ) {
356           setCallOrRetArgCol( LR, SparcIntRegOrder::i0, RetMI, AddedInstrMap);
357         }
358         else if (RegClassID==FloatRegClassID ) {
359           setCallOrRetArgCol(LR, SparcFloatRegOrder::f0, RetMI, AddedInstrMap);
360         }
361         
362       }
363       else {
364         cout << "Warning: No LR for return value" << endl;
365       }
366
367     }
368
369   }
370
371 }
372
373
374
375 void UltraSparcRegInfo::setCallOrRetArgCol(LiveRange *const LR, 
376                                            const unsigned RegNo,
377                                            const MachineInstr *MI,
378                                            AddedInstrMapType &AIMap) const {
379
380   // if no call interference and LR is NOT previously colored (e.g., as an 
381   // incoming arg)
382   if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) { 
383     // we can directly allocate a %o register
384     LR->setColor( RegNo);
385     if( DEBUG_RA) printReg( LR );
386   }
387   else {        
388
389     // there are call interferences (e.g., live across a call or produced
390     // by a call instr) or this LR is already colored as an incoming argument
391
392     MachineInstr *MI = getCopy2RegMI((*(LR->begin())), RegNo, 
393                                      (LR->getRegClass())->getID());
394
395     AddedInstrns * AI = AIMap[ MI ];    // get already added instrns for MI
396     if( ! AI ) AI = new AddedInstrns(); 
397
398     AI->InstrnsBefore.push_back( MI );  // add the new MI yp AMI
399     AIMap[ MI ] = AI;
400
401     
402     cout << "Inserted a copy instr for a RET/CALL instr " << endl;
403
404     // We don't color LR here. It's colored as any other normal LR or
405     // as an incoming arg or a return value of a call.
406   }
407
408 }
409
410 // Generates a copy machine instruction to copy a value to a given
411 // register.
412
413 MachineInstr * UltraSparcRegInfo::getCopy2RegMI(const Value *SrcVal,
414                                                 const unsigned Reg,
415                                                 unsigned RegClassID) const {
416   MachineInstr * MI;
417
418   if(  RegClassID == IntRegClassID ) {  // if integer move
419
420     MI = new MachineInstr(ADD, 3);
421  
422     MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal);
423     MI->SetMachineOperand(1, SparcIntRegOrder::g0, false);
424     MI->SetMachineOperand(2, Reg, true);
425   }
426   else {                                // if FP move
427
428     if(SrcVal->getType()-> getPrimitiveID() == Type::FloatTyID )
429       MI = new MachineInstr(FMOVS, 2);
430     else if(SrcVal->getType()-> getPrimitiveID() == Type::DoubleTyID)
431       MI = new MachineInstr(FMOVD, 2);
432     else assert( 0 && "Unknown Type");
433
434     MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal);
435     MI->SetMachineOperand(1, Reg, true);
436   }
437
438   return MI;
439
440 }
441
442
443 //---------------------------------------------------------------------------
444 // Print the register assigned to a LR
445 //---------------------------------------------------------------------------
446
447 void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
448
449   unsigned RegClassID = (LR->getRegClass())->getID();
450
451   cout << " *Node " << (LR->getUserIGNode())->getIndex();
452
453   if( ! LR->hasColor() ) {
454     cout << " - could not find a color" << endl;
455     return;
456   }
457   
458   // if a color is found
459
460   cout << " colored with color "<< LR->getColor();
461
462   if( RegClassID == IntRegClassID ) {
463
464     cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
465     cout << "]" << endl;
466   }
467   else if ( RegClassID == FloatRegClassID) {
468     cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
469     if( LR->getTypeID() == Type::DoubleTyID )
470       cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);
471     cout << "]" << endl;
472   }
473
474
475 }