1 //***************************************************************************
8 // 7/15/01 - Vikram Adve - Created
9 //**************************************************************************/
11 #include "llvm/Target/Sparc.h"
12 #include "SparcInternals.h"
13 #include "llvm/Method.h"
14 #include "llvm/CodeGen/InstrScheduling.h"
15 #include "llvm/CodeGen/InstrSelection.h"
17 #include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
18 #include "llvm/CodeGen/PhyRegAlloc.h"
21 // allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
22 // that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
24 TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); }
27 //---------------------------------------------------------------------------
28 // class UltraSparcInstrInfo
31 // Information about individual instructions.
32 // Most information is stored in the SparcMachineInstrDesc array above.
33 // Other information is computed on demand, and most such functions
34 // default to member functions in base class MachineInstrInfo.
35 //---------------------------------------------------------------------------
38 UltraSparcInstrInfo::UltraSparcInstrInfo()
39 : MachineInstrInfo(SparcMachineInstrDesc,
40 /*descSize = */ NUM_TOTAL_OPCODES,
41 /*numRealOpCodes = */ NUM_REAL_OPCODES)
46 //---------------------------------------------------------------------------
47 // class UltraSparcSchedInfo
50 // Scheduling information for the UltraSPARC.
51 // Primarily just initializes machine-dependent parameters in
52 // class MachineSchedInfo.
53 //---------------------------------------------------------------------------
56 UltraSparcSchedInfo::UltraSparcSchedInfo(const MachineInstrInfo* mii)
57 : MachineSchedInfo((unsigned int) SPARC_NUM_SCHED_CLASSES,
60 SparcInstrUsageDeltas,
61 SparcInstrIssueDeltas,
62 sizeof(SparcInstrUsageDeltas)/sizeof(InstrRUsageDelta),
63 sizeof(SparcInstrIssueDeltas)/sizeof(InstrIssueDelta))
66 longestIssueConflict = 0; // computed from issuesGaps[]
68 branchMispredictPenalty = 4; // 4 for SPARC IIi
69 branchTargetUnknownPenalty = 2; // 2 for SPARC IIi
70 l1DCacheMissPenalty = 8; // 7 or 9 for SPARC IIi
71 l1ICacheMissPenalty = 8; // ? for SPARC IIi
73 inOrderLoads = true; // true for SPARC IIi
74 inOrderIssue = true; // true for SPARC IIi
75 inOrderExec = false; // false for most architectures
76 inOrderRetire= true; // true for most architectures
78 // must be called after above parameters are initialized.
79 this->initializeResources();
83 UltraSparcSchedInfo::initializeResources()
85 // Compute MachineSchedInfo::instrRUsages and MachineSchedInfo::issueGaps
86 MachineSchedInfo::initializeResources();
88 // Machine-dependent fixups go here. None for now.
93 //---------------------------------------------------------------------------
94 // class UltraSparcRegInfo
97 // This class provides info about sparc register classes.
98 //--------------------------------------------------------------------------
101 UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc *const USI ) :
106 MachineRegClassArr.push_back( new SparcIntRegClass(IntRegClassID) );
107 MachineRegClassArr.push_back( new SparcFloatRegClass(FloatRegClassID) );
108 MachineRegClassArr.push_back( new SparcIntCCRegClass(IntCCRegClassID) );
109 MachineRegClassArr.push_back( new SparcFloatCCRegClass(FloatCCRegClassID));
111 assert( SparcFloatRegOrder::StartOfNonVolatileRegs == 6 &&
112 "6 Float regs are used for float arg passing");
115 // ***** TODO insert deletes for reg classes
116 UltraSparcRegInfo::~UltraSparcRegInfo(void) { } // empty destructor
120 //---------------------------------------------------------------------------
123 // This method will color incoming args to a method. If there are more
124 // args than that can fit in regs, code will be inserted to pop them from
126 //---------------------------------------------------------------------------
129 void UltraSparcRegInfo::colorArgs(const Method *const Meth,
130 LiveRangeInfo& LRI) const
133 // get the argument list
134 const Method::ArgumentListType& ArgList = Meth->getArgumentList();
135 // get an iterator to arg list
136 Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
139 // to keep track of which float regs are allocated for argument passing
140 bool FloatArgUsedArr[NumOfFloatArgRegs];
142 // init float arg used array
143 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
144 FloatArgUsedArr[i] = false;
147 for( ; ArgIt != ArgList.end() ; ++ArgIt) {
150 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt);
151 unsigned RegClassID = (LR->getRegClass())->getID();
153 // if the arg is in int class - allocate a reg for an int arg
154 if( RegClassID == IntRegClassID ) {
156 if( intArgNo < NumOfIntArgRegs) {
157 LR->setColor( SparcIntRegOrder::i0 + intArgNo );
159 if( DEBUG_RA) printReg( LR );
163 // TODO: Insert push code here
164 assert( 0 && "Insert push code here!");
169 // if the arg is float/double
170 else if ( RegClassID == FloatRegClassID) {
172 if( LR->getTypeID() == Type::DoubleTyID ) {
174 // find the first reg # we can pass a double arg
175 for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
176 if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
177 LR->setColor( SparcFloatRegOrder::f0 + i );
178 FloatArgUsedArr[i] = true;
179 FloatArgUsedArr[i+1] = true;
180 if( DEBUG_RA) printReg( LR );
184 if( ! LR->hasColor() ) { // if LR was not colored above
186 assert(0 && "insert push code here for a double");
191 else if( LR->getTypeID() == Type::FloatTyID ) {
193 // find the first reg # we can pass a float arg
194 for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
195 if ( !FloatArgUsedArr[i] ) {
196 LR->setColor( SparcFloatRegOrder::f0 + i );
197 FloatArgUsedArr[i] = true;
198 if( DEBUG_RA) printReg( LR );
202 if( ! LR->hasColor() ) { // if LR was not colored above
203 assert(0 && "insert push code here for a float");
208 assert(0 && "unknown float type in method arg");
210 } // float register class
213 assert(0 && "Unknown RegClassID");
223 void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
225 unsigned RegClassID = (LR->getRegClass())->getID();
227 cout << " *Node " << (LR->getUserIGNode())->getIndex();
229 if( ! LR->hasColor() ) {
230 cout << " - could not find a color" << endl;
234 // if a color is found
236 cout << " colored with color "<< LR->getColor();
238 if( RegClassID == IntRegClassID ) {
240 cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
243 else if ( RegClassID == FloatRegClassID) {
244 cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
245 if( LR->getTypeID() == Type::DoubleTyID )
246 cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);
254 void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
255 CallInstrList, LiveRangeInfo& LRI,
256 AddedInstrMapType &AddedInstrMap) const
259 vector<const Instruction *>::const_iterator InstIt = CallInstrList.begin();
261 for( ; InstIt != CallInstrList.end(); ++InstIt) {
263 // Inst = LLVM call instruction
264 const Instruction *const CallI = *InstIt;
266 MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec();
267 MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
269 // find the CALL/JMMPL machine instruction
270 for( ; MIIt != MInstVec.end() &&
271 ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode());
274 assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found");
276 // CallMI = CALL/JMPL machine isntruction
277 const MachineInstr *const CallMI = *MIIt;
279 Instruction::op_const_iterator OpIt = CallI->op_begin();
282 //unsigned NumOfCallInterfs = LR->getNumOfCallInterferences();
284 // to keep track of which float regs are allocated for argument passing
285 bool FloatArgUsedArr[NumOfFloatArgRegs];
287 // init float arg used array
288 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
289 FloatArgUsedArr[i] = false;
291 // go thru all the operands of LLVM instruction
292 for( ; OpIt != CallI->op_end(); ++OpIt ) {
294 // get the LR of call operand (parameter)
295 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt);
298 cout << " Warning: In call instr, no LR for arg: " ;
304 unsigned RegClassID = (LR->getRegClass())->getID();
306 // if the arg is in int class - allocate a reg for an int arg
307 if( RegClassID == IntRegClassID ) {
309 if( intArgNo < NumOfIntArgRegs) {
310 setCallArgColor( LR, SparcIntRegOrder::o0 + intArgNo );
314 // TODO: Insert push code here
315 assert( 0 && "Insert push code here!");
317 AddedInstrns * AI = AddedInstrMap[ CallMI ];
318 if( ! AI ) AI = new AddedInstrns();
320 // AI->InstrnsBefore.push_back( getStackPushInstr(LR) );
321 AddedInstrMap[ CallMI ] = AI;
327 // if the arg is float/double
328 else if ( RegClassID == FloatRegClassID) {
330 if( LR->getTypeID() == Type::DoubleTyID ) {
332 // find the first reg # we can pass a double arg
333 for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
334 if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
335 setCallArgColor(LR, SparcFloatRegOrder::f0 + i );
336 FloatArgUsedArr[i] = true;
337 FloatArgUsedArr[i+1] = true;
338 //if( DEBUG_RA) printReg( LR );
342 if( ! LR->hasColor() ) { // if LR was not colored above
344 assert(0 && "insert push code here for a double");
349 else if( LR->getTypeID() == Type::FloatTyID ) {
351 // find the first reg # we can pass a float arg
352 for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
353 if ( !FloatArgUsedArr[i] ) {
354 setCallArgColor(LR, SparcFloatRegOrder::f0 + i );
355 FloatArgUsedArr[i] = true;
356 // LR->setColor( SparcFloatRegOrder::f0 + i );
357 // if( DEBUG_RA) printReg( LR );
361 if( ! LR->hasColor() ) { // if LR was not colored above
362 assert(0 && "insert push code here for a float");
367 assert(0 && "unknown float type in method arg");
369 } // float register class
372 assert(0 && "Unknown RegClassID");
375 } // for each operand in a call instruction
380 } // for all call instrctions in CallInstrList
385 void UltraSparcRegInfo::setCallArgColor(LiveRange *const LR,
386 const unsigned RegNo) const {
388 // if no call interference and LR is NOT previously colored (e.g., as an
390 if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) {
391 // we can directly allocate a %o register
392 LR->setColor( RegNo);
393 if( DEBUG_RA) printReg( LR );
395 else { // there are call interferences
398 // insert a copy machine instr to copy from LR to %o(reg)
399 PreMInstrMap[ CallMI ] =
400 getNewCopyMInstr( LR->, SparcIntRegOrder::o0 + intArgNo );
402 cout << " $$$ TODO: Insert a copy for call argument!: " << endl;
404 // We don't color LR here. It's colored as any other normal LR
413 //---------------------------------------------------------------------------
414 // class UltraSparcMachine
417 // Primary interface to machine description for the UltraSPARC.
418 // Primarily just initializes machine-dependent parameters in
419 // class TargetMachine, and creates machine-dependent subclasses
420 // for classes such as MachineInstrInfo.
422 //---------------------------------------------------------------------------
424 UltraSparc::UltraSparc() : TargetMachine("UltraSparc-Native"),
425 InstSchedulingInfo(&InstInfo),
427 optSizeForSubWordData = 4;
428 minMemOpWordSize = 8;
429 maxAtomicMemOpWordSize = 8;
430 zeroRegNum = 0; // %g0 always gives 0 on Sparc
435 //----------------------------------------------------------------------------
436 // Entry point for register allocation for a module
437 //----------------------------------------------------------------------------
439 void AllocateRegisters(Method *M, TargetMachine &TM)
442 if ( (M)->isExternal() ) // don't process prototypes
446 cout << endl << "******************** Method "<< (M)->getName();
447 cout << " ********************" <<endl;
450 MethodLiveVarInfo LVI(M ); // Analyze live varaibles
454 PhyRegAlloc PRA(M, TM , &LVI); // allocate registers
455 PRA.allocateRegisters();
458 if( DEBUG_RA ) cout << endl << "Register allocation complete!" << endl;
466 bool UltraSparc::compileMethod(Method *M) {
467 if (SelectInstructionsForMethod(M, *this)) {
468 cerr << "Instruction selection failed for method " << M->getName()
473 if (ScheduleInstructionsWithSSA(M, *this, InstSchedulingInfo)) {
474 cerr << "Instruction scheduling before allocation failed for method "
475 << M->getName() << "\n\n";
479 AllocateRegisters(M, *this); // allocate registers