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"
8 #include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
9 #include "llvm/CodeGen/PhyRegAlloc.h"
14 //---------------------------------------------------------------------------
16 //---------------------------------------------------------------------------
19 Rules for coloring values with sepcial registers:
20 =================================================
22 The following are the cases we color values with special regs:
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
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.
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.
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
49 //---------------------------------------------------------------------------
51 void UltraSparcRegInfo::colorArgs(const Method *const Meth,
52 LiveRangeInfo& LRI) const
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();
61 // to keep track of which float regs are allocated for argument passing
62 bool FloatArgUsedArr[NumOfFloatArgRegs];
64 // init float arg used array
65 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
66 FloatArgUsedArr[i] = false;
69 for( ; ArgIt != ArgList.end() ; ++ArgIt) {
72 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt);
73 unsigned RegClassID = (LR->getRegClass())->getID();
75 // if the arg is in int class - allocate a reg for an int arg
76 if( RegClassID == IntRegClassID ) {
78 if( intArgNo < NumOfIntArgRegs) {
79 LR->setColor( SparcIntRegOrder::i0 + intArgNo );
81 if( DEBUG_RA) printReg( LR );
85 // TODO: Insert push code here
86 assert( 0 && "Insert push code here!");
91 // if the arg is float/double
92 else if ( RegClassID == FloatRegClassID) {
94 if( LR->getTypeID() == Type::DoubleTyID ) {
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 );
106 if( ! LR->hasColor() ) { // if LR was not colored above
108 assert(0 && "insert push code here for a double");
113 else if( LR->getTypeID() == Type::FloatTyID ) {
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 );
124 if( ! LR->hasColor() ) { // if LR was not colored above
125 assert(0 && "insert push code here for a float");
130 assert(0 && "unknown float type in method arg");
132 } // float register class
135 assert(0 && "Unknown RegClassID");
145 void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
146 CallInstrList, LiveRangeInfo& LRI,
147 AddedInstrMapType &AddedInstrMap) const
150 vector<const Instruction *>::const_iterator InstIt;
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.
156 for(InstIt=CallInstrList.begin(); InstIt != CallInstrList.end(); ++InstIt) {
158 const Instruction *const CallI = *InstIt;
160 // get the live range of return value of this call
161 LiveRange *const LR = LRI.getLiveRangeForValue( CallI );
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.
172 assert( ! LR->hasColor() && "Can't have a color since this is a def");
174 unsigned RegClassID = (LR->getRegClass())->getID();
176 if( RegClassID == IntRegClassID ) {
177 LR->setColor(SparcIntRegOrder::o0);
179 else if (RegClassID == FloatRegClassID ) {
180 LR->setColor(SparcFloatRegOrder::f0 );
184 cout << "Warning: No Live Range for return value of CALL" << endl;
189 for( InstIt=CallInstrList.begin(); InstIt != CallInstrList.end(); ++InstIt) {
191 // Inst = LLVM call instruction
192 const Instruction *const CallI = *InstIt;
194 // find the CALL/JMMPL machine instruction
195 MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec();
196 MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
199 for( ; MIIt != MInstVec.end() &&
200 ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode());
203 assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found");
206 assert(getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode()) &&
207 "First machine instruction is not a Call/JMPL Machine Instr");
209 // CallMI = CALL/JMPL machine isntruction
210 const MachineInstr *const CallMI = *MIIt;
212 Instruction::op_const_iterator OpIt = CallI->op_begin();
217 // to keep track of which float regs are allocated for argument passing
218 bool FloatArgUsedArr[NumOfFloatArgRegs];
220 // init float arg used array
221 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
222 FloatArgUsedArr[i] = false;
224 // go thru all the operands of LLVM instruction
225 for( ; OpIt != CallI->op_end(); ++OpIt ) {
227 // get the LR of call operand (parameter)
228 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt);
231 cout << " Warning: In call instr, no LR for arg: " ;
237 unsigned RegClassID = (LR->getRegClass())->getID();
239 // if the arg is in int class - allocate a reg for an int arg
240 if( RegClassID == IntRegClassID ) {
242 if( intArgNo < NumOfIntArgRegs) {
243 setCallOrRetArgCol( LR, SparcIntRegOrder::o0 + intArgNo,
244 CallMI, AddedInstrMap);
248 // TODO: Insert push code here
249 assert( 0 && "Insert push code here!");
251 AddedInstrns * AI = AddedInstrMap[ CallMI ];
252 if( ! AI ) AI = new AddedInstrns();
254 // AI->InstrnsBefore.push_back( getStackPushInstr(LR) );
255 AddedInstrMap[ CallMI ] = AI;
261 // if the arg is float/double
262 else if ( RegClassID == FloatRegClassID) {
264 if( LR->getTypeID() == Type::DoubleTyID ) {
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 );
277 if( ! LR->hasColor() ) { // if LR was not colored above
279 assert(0 && "insert push code here for a double");
284 else if( LR->getTypeID() == Type::FloatTyID ) {
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 );
297 if( ! LR->hasColor() ) { // if LR was not colored above
298 assert(0 && "insert push code here for a float");
303 assert(0 && "unknown float type in method arg");
305 } // float register class
308 assert(0 && "Unknown RegClassID");
311 } // for each operand in a call instruction
317 } // for all call instrctions in CallInstrList
325 void UltraSparcRegInfo::colorRetArg(vector<const Instruction *> &
326 RetInstrList, LiveRangeInfo& LRI,
327 AddedInstrMapType &AddedInstrMap) const
330 vector<const Instruction *>::const_iterator InstIt;
333 for(InstIt=RetInstrList.begin(); InstIt != RetInstrList.end(); ++InstIt) {
335 const ReturnInst *const RetI = (ReturnInst *) *InstIt;
337 // get the return value of this return instruction
338 const Value *RetVal = (RetI)->getReturnValue();
342 // find the CALL/JMMPL machine instruction
343 MachineCodeForVMInstr & MInstVec = RetI->getMachineInstrVec();
344 MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
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;
351 LiveRange *const LR = LRI.getLiveRangeForValue( RetVal );
352 unsigned RegClassID = (LR->getRegClass())->getID();
355 if( RegClassID == IntRegClassID ) {
356 setCallOrRetArgCol( LR, SparcIntRegOrder::i0, RetMI, AddedInstrMap);
358 else if (RegClassID==FloatRegClassID ) {
359 setCallOrRetArgCol(LR, SparcFloatRegOrder::f0, RetMI, AddedInstrMap);
364 cout << "Warning: No LR for return value" << endl;
375 void UltraSparcRegInfo::setCallOrRetArgCol(LiveRange *const LR,
376 const unsigned RegNo,
377 const MachineInstr *MI,
378 AddedInstrMapType &AIMap) const {
380 // if no call interference and LR is NOT previously colored (e.g., as an
382 if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) {
383 // we can directly allocate a %o register
384 LR->setColor( RegNo);
385 if( DEBUG_RA) printReg( LR );
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
392 MachineInstr *MI = getCopy2RegMI((*(LR->begin())), RegNo,
393 (LR->getRegClass())->getID());
395 AddedInstrns * AI = AIMap[ MI ]; // get already added instrns for MI
396 if( ! AI ) AI = new AddedInstrns();
398 AI->InstrnsBefore.push_back( MI ); // add the new MI yp AMI
402 cout << "Inserted a copy instr for a RET/CALL instr " << endl;
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.
410 // Generates a copy machine instruction to copy a value to a given
413 MachineInstr * UltraSparcRegInfo::getCopy2RegMI(const Value *SrcVal,
415 unsigned RegClassID) const {
418 if( RegClassID == IntRegClassID ) { // if integer move
420 MI = new MachineInstr(ADD, 3);
422 MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal);
423 MI->SetMachineOperand(1, SparcIntRegOrder::g0, false);
424 MI->SetMachineOperand(2, Reg, true);
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");
434 MI->SetMachineOperand(0, MachineOperand::MO_VirtualRegister, SrcVal);
435 MI->SetMachineOperand(1, Reg, true);
443 //---------------------------------------------------------------------------
444 // Print the register assigned to a LR
445 //---------------------------------------------------------------------------
447 void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
449 unsigned RegClassID = (LR->getRegClass())->getID();
451 cout << " *Node " << (LR->getUserIGNode())->getIndex();
453 if( ! LR->hasColor() ) {
454 cout << " - could not find a color" << endl;
458 // if a color is found
460 cout << " colored with color "<< LR->getColor();
462 if( RegClassID == IntRegClassID ) {
464 cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
467 else if ( RegClassID == FloatRegClassID) {
468 cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
469 if( LR->getTypeID() == Type::DoubleTyID )
470 cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);