blob: 8254b00a5b090771106e2ccf8b2db8e5d71d421a [file] [log] [blame]
Ruchira Sasanka94d86e92001-09-14 20:31:39 +00001#include "llvm/Target/Sparc.h"
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +00002#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"
Chris Lattner20b1ea02001-09-14 03:47:57 +00007
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +00008#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
9#include "llvm/CodeGen/PhyRegAlloc.h"
Chris Lattner20b1ea02001-09-14 03:47:57 +000010
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000011
12
13
14//---------------------------------------------------------------------------
15// UltraSparcRegInfo
16//---------------------------------------------------------------------------
17
18/*
19Rules for coloring values with sepcial registers:
20=================================================
21
22The following are the cases we color values with special regs:
23
241) Incoming Method Arguements
252) Outgoing Call Arguments
263) Return Value of a call
274) Return Value of a return statement
28
29Both 1 and 3 are defs. Therefore, they can be set directly. For case 1,
30incoming args are colored to %i0-%i5 and %f0 - %fx. For case 3, the return
31value of the call must be colored to %o0 or %f0.
32
33For 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
35if 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
37as a call interference as well if it is live after the call). Otherwise, they
38can be precolored. In cases where we cannot precolor, we just have to insert
39a 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
51void UltraSparcRegInfo::colorArgs(const Method *const Meth,
52 LiveRangeInfo& LRI) const
Chris Lattner20b1ea02001-09-14 03:47:57 +000053{
54
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000055 // 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;
Chris Lattner20b1ea02001-09-14 03:47:57 +000060
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000061 // to keep track of which float regs are allocated for argument passing
62 bool FloatArgUsedArr[NumOfFloatArgRegs];
Chris Lattner20b1ea02001-09-14 03:47:57 +000063
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000064 // init float arg used array
65 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
66 FloatArgUsedArr[i] = false;
Chris Lattner20b1ea02001-09-14 03:47:57 +000067
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000068 // for each argument
69 for( ; ArgIt != ArgList.end() ; ++ArgIt) {
Chris Lattner20b1ea02001-09-14 03:47:57 +000070
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000071 // get the LR of arg
72 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt);
73 unsigned RegClassID = (LR->getRegClass())->getID();
Chris Lattner20b1ea02001-09-14 03:47:57 +000074
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000075 // if the arg is in int class - allocate a reg for an int arg
76 if( RegClassID == IntRegClassID ) {
Chris Lattner20b1ea02001-09-14 03:47:57 +000077
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000078 if( intArgNo < NumOfIntArgRegs) {
79 LR->setColor( SparcIntRegOrder::i0 + intArgNo );
Chris Lattner20b1ea02001-09-14 03:47:57 +000080
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000081 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;
Chris Lattner20b1ea02001-09-14 03:47:57 +000089 }
90
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000091 // if the arg is float/double
92 else if ( RegClassID == FloatRegClassID) {
Chris Lattner20b1ea02001-09-14 03:47:57 +000093
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000094 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");
Chris Lattner20b1ea02001-09-14 03:47:57 +0000136 }
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000137
Chris Lattner20b1ea02001-09-14 03:47:57 +0000138}
139
140
141
142
143
144
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000145void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
146 CallInstrList, LiveRangeInfo& LRI,
147 AddedInstrMapType &AddedInstrMap) const
Chris Lattner20b1ea02001-09-14 03:47:57 +0000148{
149
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000150 vector<const Instruction *>::const_iterator InstIt;
Chris Lattner20b1ea02001-09-14 03:47:57 +0000151
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000152 // 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();
Chris Lattner20b1ea02001-09-14 03:47:57 +0000175
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000176 if( RegClassID == IntRegClassID ) {
177 LR->setColor(SparcIntRegOrder::o0);
178 }
179 else if (RegClassID == FloatRegClassID ) {
180 LR->setColor(SparcFloatRegOrder::f0 );
181 }
Chris Lattner20b1ea02001-09-14 03:47:57 +0000182 }
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000183 else {
184 cout << "Warning: No Live Range for return value of CALL" << endl;
Chris Lattner20b1ea02001-09-14 03:47:57 +0000185 }
186 }
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000187
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
Chris Lattner20b1ea02001-09-14 03:47:57 +0000319}
320
321
322
323
324
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000325void UltraSparcRegInfo::colorRetArg(vector<const Instruction *> &
326 RetInstrList, LiveRangeInfo& LRI,
327 AddedInstrMapType &AddedInstrMap) const
Chris Lattner20b1ea02001-09-14 03:47:57 +0000328{
329
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000330 vector<const Instruction *>::const_iterator InstIt;
Chris Lattner20b1ea02001-09-14 03:47:57 +0000331
332
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000333 for(InstIt=RetInstrList.begin(); InstIt != RetInstrList.end(); ++InstIt) {
Chris Lattner20b1ea02001-09-14 03:47:57 +0000334
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000335 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
Ruchira Sasankaa5564c62001-09-19 22:40:51 +0000346
347 /*
348 for( ; MIIt != MInstVec.end() &&
349 !getUltraSparcInfo().getInstrInfo().isReturn((*MIIt)->getOpCode());
350 ++MIIt ) {
351
352 cout << "Inst = "<< TargetInstrDescriptors[(*MIIt)->getOpCode()].opCodeString << endl;
353
354
355 }
356 assert((MIIt != MInstVec.end()) &&"No return machine instruction found");
357
358 */
359
360
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000361 assert(getUltraSparcInfo().getInstrInfo().isReturn((*MIIt)->getOpCode())
Ruchira Sasankaa5564c62001-09-19 22:40:51 +0000362 && "First machine inst is not a RETURN Machine Instr");
363
364
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000365 // RET machine isntruction
366 const MachineInstr *const RetMI = *MIIt;
367
368 LiveRange *const LR = LRI.getLiveRangeForValue( RetVal );
369 unsigned RegClassID = (LR->getRegClass())->getID();
370
371 if ( LR ) {
372 if( RegClassID == IntRegClassID ) {
373 setCallOrRetArgCol( LR, SparcIntRegOrder::i0, RetMI, AddedInstrMap);
374 }
375 else if (RegClassID==FloatRegClassID ) {
376 setCallOrRetArgCol(LR, SparcFloatRegOrder::f0, RetMI, AddedInstrMap);
377 }
378
379 }
380 else {
381 cout << "Warning: No LR for return value" << endl;
382 }
383
Chris Lattner20b1ea02001-09-14 03:47:57 +0000384 }
Chris Lattner20b1ea02001-09-14 03:47:57 +0000385
386 }
387
Chris Lattner20b1ea02001-09-14 03:47:57 +0000388}
389
390
391
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000392void UltraSparcRegInfo::setCallOrRetArgCol(LiveRange *const LR,
393 const unsigned RegNo,
394 const MachineInstr *MI,
395 AddedInstrMapType &AIMap) const {
396
397 // if no call interference and LR is NOT previously colored (e.g., as an
398 // incoming arg)
399 if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) {
400 // we can directly allocate a %o register
401 LR->setColor( RegNo);
402 if( DEBUG_RA) printReg( LR );
403 }
404 else {
405
406 // there are call interferences (e.g., live across a call or produced
407 // by a call instr) or this LR is already colored as an incoming argument
408
409 MachineInstr *MI = getCopy2RegMI((*(LR->begin())), RegNo,
410 (LR->getRegClass())->getID());
411
412 AddedInstrns * AI = AIMap[ MI ]; // get already added instrns for MI
413 if( ! AI ) AI = new AddedInstrns();
414
415 AI->InstrnsBefore.push_back( MI ); // add the new MI yp AMI
416 AIMap[ MI ] = AI;
417
418
419 cout << "Inserted a copy instr for a RET/CALL instr " << endl;
420
421 // We don't color LR here. It's colored as any other normal LR or
422 // as an incoming arg or a return value of a call.
423 }
424
425}
426
427// Generates a copy machine instruction to copy a value to a given
428// register.
429
430MachineInstr * UltraSparcRegInfo::getCopy2RegMI(const Value *SrcVal,
431 const unsigned Reg,
432 unsigned RegClassID) const {
433 MachineInstr * MI;
434
435 if( RegClassID == IntRegClassID ) { // if integer move
436
437 MI = new MachineInstr(ADD, 3);
438
439 MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal);
440 MI->SetMachineOperand(1, SparcIntRegOrder::g0, false);
441 MI->SetMachineOperand(2, Reg, true);
442 }
443 else { // if FP move
444
445 if(SrcVal->getType()-> getPrimitiveID() == Type::FloatTyID )
446 MI = new MachineInstr(FMOVS, 2);
447 else if(SrcVal->getType()-> getPrimitiveID() == Type::DoubleTyID)
448 MI = new MachineInstr(FMOVD, 2);
449 else assert( 0 && "Unknown Type");
450
451 MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal);
452 MI->SetMachineOperand(1, Reg, true);
453 }
454
455 return MI;
456
457}
Chris Lattner20b1ea02001-09-14 03:47:57 +0000458
459
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000460//---------------------------------------------------------------------------
461// Print the register assigned to a LR
462//---------------------------------------------------------------------------
463
464void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
465
466 unsigned RegClassID = (LR->getRegClass())->getID();
467
468 cout << " *Node " << (LR->getUserIGNode())->getIndex();
469
470 if( ! LR->hasColor() ) {
471 cout << " - could not find a color" << endl;
472 return;
473 }
474
475 // if a color is found
476
477 cout << " colored with color "<< LR->getColor();
478
479 if( RegClassID == IntRegClassID ) {
480
481 cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
482 cout << "]" << endl;
483 }
484 else if ( RegClassID == FloatRegClassID) {
485 cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
486 if( LR->getTypeID() == Type::DoubleTyID )
487 cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);
488 cout << "]" << endl;
489 }
Chris Lattner20b1ea02001-09-14 03:47:57 +0000490
Ruchira Sasanka94d86e92001-09-14 20:31:39 +0000491
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000492}