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.
95 //---------------------------------------------------------------------------
98 // This method will color incoming args to a method. If there are more
99 // args than that can fit in regs, code will be inserted to pop them from
101 //---------------------------------------------------------------------------
104 void UltraSparcRegInfo::colorArgs(const Method *const Meth,
105 LiveRangeInfo& LRI) const
108 // get the argument list
109 const Method::ArgumentListType& ArgList = Meth->getArgumentList();
110 // get an iterator to arg list
111 Method::ArgumentListType::const_iterator ArgIt = ArgList.begin();
114 // to keep track of which float regs are allocated for argument passing
115 bool FloatArgUsedArr[NumOfFloatArgRegs];
117 // init float arg used array
118 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
119 FloatArgUsedArr[i] = false;
122 for( ; ArgIt != ArgList.end() ; ++ArgIt) {
125 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt);
126 unsigned RegClassID = (LR->getRegClass())->getID();
128 // if the arg is in int class - allocate a reg for an int arg
129 if( RegClassID == IntRegClassID ) {
131 if( intArgNo < NumOfIntArgRegs) {
132 LR->setColor( SparcIntRegOrder::i0 + intArgNo );
134 if( DEBUG_RA) printReg( LR );
138 // TODO: Insert push code here
139 assert( 0 && "Insert push code here!");
144 // if the arg is float/double
145 else if ( RegClassID == FloatRegClassID) {
147 if( LR->getTypeID() == Type::DoubleTyID ) {
149 // find the first reg # we can pass a double arg
150 for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
151 if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
152 LR->setColor( SparcFloatRegOrder::f0 + i );
153 FloatArgUsedArr[i] = true;
154 FloatArgUsedArr[i+1] = true;
155 if( DEBUG_RA) printReg( LR );
159 if( ! LR->hasColor() ) { // if LR was not colored above
161 assert(0 && "insert push code here for a double");
166 else if( LR->getTypeID() == Type::FloatTyID ) {
168 // find the first reg # we can pass a float arg
169 for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
170 if ( !FloatArgUsedArr[i] ) {
171 LR->setColor( SparcFloatRegOrder::f0 + i );
172 FloatArgUsedArr[i] = true;
173 if( DEBUG_RA) printReg( LR );
177 if( ! LR->hasColor() ) { // if LR was not colored above
178 assert(0 && "insert push code here for a float");
183 assert(0 && "unknown float type in method arg");
185 } // float register class
188 assert(0 && "Unknown RegClassID");
198 void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
200 unsigned RegClassID = (LR->getRegClass())->getID();
202 cout << " *Node " << (LR->getUserIGNode())->getIndex();
204 if( ! LR->hasColor() ) {
205 cout << " - could not find a color" << endl;
209 // if a color is found
211 cout << " colored with color "<< LR->getColor();
213 if( RegClassID == IntRegClassID ) {
215 cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
218 else if ( RegClassID == FloatRegClassID) {
219 cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
220 if( LR->getTypeID() == Type::DoubleTyID )
221 cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);
229 void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
230 CallInstrList, LiveRangeInfo& LRI,
231 AddedInstrMapType &AddedInstrMap) const
234 vector<const Instruction *>::const_iterator InstIt = CallInstrList.begin();
236 for( ; InstIt != CallInstrList.end(); ++InstIt) {
238 // Inst = LLVM call instruction
239 const Instruction *const CallI = *InstIt;
241 MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec();
242 MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
244 // find the CALL/JMMPL machine instruction
245 for( ; MIIt != MInstVec.end() &&
246 ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode());
249 assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found");
251 // CallMI = CALL/JMPL machine isntruction
252 const MachineInstr *const CallMI = *MIIt;
254 Instruction::op_const_iterator OpIt = CallI->op_begin();
257 //unsigned NumOfCallInterfs = LR->getNumOfCallInterferences();
259 // to keep track of which float regs are allocated for argument passing
260 bool FloatArgUsedArr[NumOfFloatArgRegs];
262 // init float arg used array
263 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
264 FloatArgUsedArr[i] = false;
266 // go thru all the operands of LLVM instruction
267 for( ; OpIt != CallI->op_end(); ++OpIt ) {
269 // get the LR of call operand (parameter)
270 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt);
273 cout << " Warning: In call instr, no LR for arg: " ;
279 unsigned RegClassID = (LR->getRegClass())->getID();
281 // if the arg is in int class - allocate a reg for an int arg
282 if( RegClassID == IntRegClassID ) {
284 if( intArgNo < NumOfIntArgRegs) {
285 setCallArgColor( LR, SparcIntRegOrder::o0 + intArgNo );
289 // TODO: Insert push code here
290 assert( 0 && "Insert push code here!");
292 AddedInstrns * AI = AddedInstrMap[ CallMI ];
293 if( ! AI ) AI = new AddedInstrns();
295 // AI->InstrnsBefore.push_back( getStackPushInstr(LR) );
296 AddedInstrMap[ CallMI ] = AI;
302 // if the arg is float/double
303 else if ( RegClassID == FloatRegClassID) {
305 if( LR->getTypeID() == Type::DoubleTyID ) {
307 // find the first reg # we can pass a double arg
308 for(unsigned i=0; i < NumOfFloatArgRegs; i+= 2) {
309 if ( !FloatArgUsedArr[i] && !FloatArgUsedArr[i+1] ) {
310 setCallArgColor(LR, SparcFloatRegOrder::f0 + i );
311 FloatArgUsedArr[i] = true;
312 FloatArgUsedArr[i+1] = true;
313 //if( DEBUG_RA) printReg( LR );
317 if( ! LR->hasColor() ) { // if LR was not colored above
319 assert(0 && "insert push code here for a double");
324 else if( LR->getTypeID() == Type::FloatTyID ) {
326 // find the first reg # we can pass a float arg
327 for(unsigned i=0; i < NumOfFloatArgRegs; ++i) {
328 if ( !FloatArgUsedArr[i] ) {
329 setCallArgColor(LR, SparcFloatRegOrder::f0 + i );
330 FloatArgUsedArr[i] = true;
331 // LR->setColor( SparcFloatRegOrder::f0 + i );
332 // if( DEBUG_RA) printReg( LR );
336 if( ! LR->hasColor() ) { // if LR was not colored above
337 assert(0 && "insert push code here for a float");
342 assert(0 && "unknown float type in method arg");
344 } // float register class
347 assert(0 && "Unknown RegClassID");
350 } // for each operand in a call instruction
355 } // for all call instrctions in CallInstrList
360 void UltraSparcRegInfo::setCallArgColor(LiveRange *const LR,
361 const unsigned RegNo) const {
363 // if no call interference and LR is NOT previously colored (e.g., as an
365 if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) {
366 // we can directly allocate a %o register
367 LR->setColor( RegNo);
368 if( DEBUG_RA) printReg( LR );
370 else { // there are call interferences
373 // insert a copy machine instr to copy from LR to %o(reg)
374 PreMInstrMap[ CallMI ] =
375 getNewCopyMInstr( LR->, SparcIntRegOrder::o0 + intArgNo );
377 cout << " $$$ TODO: Insert a copy for call argument!: " << endl;
379 // We don't color LR here. It's colored as any other normal LR
388 //---------------------------------------------------------------------------
389 // class UltraSparcMachine
392 // Primary interface to machine description for the UltraSPARC.
393 // Primarily just initializes machine-dependent parameters in
394 // class TargetMachine, and creates machine-dependent subclasses
395 // for classes such as MachineInstrInfo.
397 //---------------------------------------------------------------------------
399 UltraSparc::UltraSparc() : TargetMachine("UltraSparc-Native"),
400 InstSchedulingInfo(&InstInfo),
402 optSizeForSubWordData = 4;
403 minMemOpWordSize = 8;
404 maxAtomicMemOpWordSize = 8;
405 zeroRegNum = RegInfo.getZeroReg(); // %g0 always gives 0 on Sparc
410 //----------------------------------------------------------------------------
411 // Entry point for register allocation for a module
412 //----------------------------------------------------------------------------
414 void AllocateRegisters(Method *M, TargetMachine &TM)
417 if ( (M)->isExternal() ) // don't process prototypes
421 cout << endl << "******************** Method "<< (M)->getName();
422 cout << " ********************" <<endl;
425 MethodLiveVarInfo LVI(M ); // Analyze live varaibles
429 PhyRegAlloc PRA(M, TM , &LVI); // allocate registers
430 PRA.allocateRegisters();
433 if( DEBUG_RA ) cout << endl << "Register allocation complete!" << endl;
441 bool UltraSparc::compileMethod(Method *M) {
442 if (SelectInstructionsForMethod(M, *this)) {
443 cerr << "Instruction selection failed for method " << M->getName()
448 if (ScheduleInstructionsWithSSA(M, *this, InstSchedulingInfo)) {
449 cerr << "Instruction scheduling before allocation failed for method "
450 << M->getName() << "\n\n";
454 AllocateRegisters(M, *this); // allocate registers