blob: 2070af7a7aaf9f37ef174162daea772ec4f42bea [file] [log] [blame]
Chris Lattner20b1ea02001-09-14 03:47:57 +00001//***************************************************************************
2// File:
3// Sparc.cpp
4//
5// Purpose:
6//
7// History:
8// 7/15/01 - Vikram Adve - Created
9//**************************************************************************/
10
Chris Lattner46cbff62001-09-14 16:56:32 +000011#include "llvm/Target/Sparc.h"
Chris Lattner20b1ea02001-09-14 03:47:57 +000012#include "SparcInternals.h"
13#include "llvm/Method.h"
14#include "llvm/CodeGen/InstrScheduling.h"
15#include "llvm/CodeGen/InstrSelection.h"
16
Ruchira Sasankae38bd5332001-09-15 00:30:44 +000017#include "llvm/Analysis/LiveVar/MethodLiveVarInfo.h"
18#include "llvm/CodeGen/PhyRegAlloc.h"
19
20
Chris Lattner46cbff62001-09-14 16:56:32 +000021// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
22// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
23//
24TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); }
Chris Lattner20b1ea02001-09-14 03:47:57 +000025
26
27//---------------------------------------------------------------------------
28// class UltraSparcInstrInfo
29//
30// Purpose:
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//---------------------------------------------------------------------------
36
37/*ctor*/
38UltraSparcInstrInfo::UltraSparcInstrInfo()
39 : MachineInstrInfo(SparcMachineInstrDesc,
40 /*descSize = */ NUM_TOTAL_OPCODES,
41 /*numRealOpCodes = */ NUM_REAL_OPCODES)
42{
43}
44
45
46//---------------------------------------------------------------------------
47// class UltraSparcSchedInfo
48//
49// Purpose:
50// Scheduling information for the UltraSPARC.
51// Primarily just initializes machine-dependent parameters in
52// class MachineSchedInfo.
53//---------------------------------------------------------------------------
54
55/*ctor*/
56UltraSparcSchedInfo::UltraSparcSchedInfo(const MachineInstrInfo* mii)
57 : MachineSchedInfo((unsigned int) SPARC_NUM_SCHED_CLASSES,
58 mii,
59 SparcRUsageDesc,
60 SparcInstrUsageDeltas,
61 SparcInstrIssueDeltas,
62 sizeof(SparcInstrUsageDeltas)/sizeof(InstrRUsageDelta),
63 sizeof(SparcInstrIssueDeltas)/sizeof(InstrIssueDelta))
64{
65 maxNumIssueTotal = 4;
66 longestIssueConflict = 0; // computed from issuesGaps[]
67
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
72
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
77
78 // must be called after above parameters are initialized.
79 this->initializeResources();
80}
81
82void
83UltraSparcSchedInfo::initializeResources()
84{
85 // Compute MachineSchedInfo::instrRUsages and MachineSchedInfo::issueGaps
86 MachineSchedInfo::initializeResources();
87
88 // Machine-dependent fixups go here. None for now.
89}
90
91
Ruchira Sasankae38bd5332001-09-15 00:30:44 +000092
93//---------------------------------------------------------------------------
94// class UltraSparcRegInfo
95//
96// Purpose:
97// This class provides info about sparc register classes.
98//--------------------------------------------------------------------------
99
100#if 0
101UltraSparcRegInfo::UltraSparcRegInfo(const UltraSparc *const USI ) :
102 UltraSparcInfo(USI),
103 NumOfIntArgRegs(6),
104 NumOfFloatArgRegs(6)
105 {
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));
110
111 assert( SparcFloatRegOrder::StartOfNonVolatileRegs == 6 &&
112 "6 Float regs are used for float arg passing");
113 }
114
115 // ***** TODO insert deletes for reg classes
116UltraSparcRegInfo::~UltraSparcRegInfo(void) { } // empty destructor
117
118#endif
119
120//---------------------------------------------------------------------------
121// UltraSparcRegInfo
122// Purpose:
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
125// stack
126//---------------------------------------------------------------------------
127
128
129void UltraSparcRegInfo::colorArgs(const Method *const Meth,
130 LiveRangeInfo& LRI) const
131{
132
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();
137 unsigned intArgNo=0;
138
139 // to keep track of which float regs are allocated for argument passing
140 bool FloatArgUsedArr[NumOfFloatArgRegs];
141
142 // init float arg used array
143 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
144 FloatArgUsedArr[i] = false;
145
146 // for each argument
147 for( ; ArgIt != ArgList.end() ; ++ArgIt) {
148
149 // get the LR of arg
150 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt);
151 unsigned RegClassID = (LR->getRegClass())->getID();
152
153 // if the arg is in int class - allocate a reg for an int arg
154 if( RegClassID == IntRegClassID ) {
155
156 if( intArgNo < NumOfIntArgRegs) {
157 LR->setColor( SparcIntRegOrder::i0 + intArgNo );
158
159 if( DEBUG_RA) printReg( LR );
160 }
161
162 else {
163 // TODO: Insert push code here
164 assert( 0 && "Insert push code here!");
165 }
166 ++intArgNo;
167 }
168
169 // if the arg is float/double
170 else if ( RegClassID == FloatRegClassID) {
171
172 if( LR->getTypeID() == Type::DoubleTyID ) {
173
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 );
181 break;
182 }
183 }
184 if( ! LR->hasColor() ) { // if LR was not colored above
185
186 assert(0 && "insert push code here for a double");
187
188 }
189
190 }
191 else if( LR->getTypeID() == Type::FloatTyID ) {
192
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 );
199 break;
200 }
201 }
202 if( ! LR->hasColor() ) { // if LR was not colored above
203 assert(0 && "insert push code here for a float");
204 }
205
206 }
207 else
208 assert(0 && "unknown float type in method arg");
209
210 } // float register class
211
212 else
213 assert(0 && "Unknown RegClassID");
214 }
215
216}
217
218
219
220
221
222
223void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
224
225 unsigned RegClassID = (LR->getRegClass())->getID();
226
227 cout << " *Node " << (LR->getUserIGNode())->getIndex();
228
229 if( ! LR->hasColor() ) {
230 cout << " - could not find a color" << endl;
231 return;
232 }
233
234 // if a color is found
235
236 cout << " colored with color "<< LR->getColor();
237
238 if( RegClassID == IntRegClassID ) {
239
240 cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
241 cout << "]" << endl;
242 }
243 else if ( RegClassID == FloatRegClassID) {
244 cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
245 if( LR->getTypeID() == Type::DoubleTyID )
246 cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);
247 cout << "]" << endl;
248 }
249
250
251}
252
253
254void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
255 CallInstrList, LiveRangeInfo& LRI,
256 AddedInstrMapType &AddedInstrMap) const
257{
258
259 vector<const Instruction *>::const_iterator InstIt = CallInstrList.begin();
260
261 for( ; InstIt != CallInstrList.end(); ++InstIt) {
262
263 // Inst = LLVM call instruction
264 const Instruction *const CallI = *InstIt;
265
266 MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec();
267 MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
268
269 // find the CALL/JMMPL machine instruction
270 for( ; MIIt != MInstVec.end() &&
271 ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode());
272 ++MIIt );
273
274 assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found");
275
276 // CallMI = CALL/JMPL machine isntruction
277 const MachineInstr *const CallMI = *MIIt;
278
279 Instruction::op_const_iterator OpIt = CallI->op_begin();
280
281 unsigned intArgNo=0;
282 //unsigned NumOfCallInterfs = LR->getNumOfCallInterferences();
283
284 // to keep track of which float regs are allocated for argument passing
285 bool FloatArgUsedArr[NumOfFloatArgRegs];
286
287 // init float arg used array
288 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
289 FloatArgUsedArr[i] = false;
290
291 // go thru all the operands of LLVM instruction
292 for( ; OpIt != CallI->op_end(); ++OpIt ) {
293
294 // get the LR of call operand (parameter)
295 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt);
296
297 if ( !LR ) {
298 cout << " Warning: In call instr, no LR for arg: " ;
299 printValue(*OpIt);
300 cout << endl;
301 continue;
302 }
303
304 unsigned RegClassID = (LR->getRegClass())->getID();
305
306 // if the arg is in int class - allocate a reg for an int arg
307 if( RegClassID == IntRegClassID ) {
308
309 if( intArgNo < NumOfIntArgRegs) {
310 setCallArgColor( LR, SparcIntRegOrder::o0 + intArgNo );
311 }
312
313 else {
314 // TODO: Insert push code here
315 assert( 0 && "Insert push code here!");
316
317 AddedInstrns * AI = AddedInstrMap[ CallMI ];
318 if( ! AI ) AI = new AddedInstrns();
319
320 // AI->InstrnsBefore.push_back( getStackPushInstr(LR) );
321 AddedInstrMap[ CallMI ] = AI;
322
323 }
324 ++intArgNo;
325 }
326
327 // if the arg is float/double
328 else if ( RegClassID == FloatRegClassID) {
329
330 if( LR->getTypeID() == Type::DoubleTyID ) {
331
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 );
339 break;
340 }
341 }
342 if( ! LR->hasColor() ) { // if LR was not colored above
343
344 assert(0 && "insert push code here for a double");
345
346 }
347
348 }
349 else if( LR->getTypeID() == Type::FloatTyID ) {
350
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 );
358 break;
359 }
360 }
361 if( ! LR->hasColor() ) { // if LR was not colored above
362 assert(0 && "insert push code here for a float");
363 }
364
365 }
366 else
367 assert(0 && "unknown float type in method arg");
368
369 } // float register class
370
371 else
372 assert(0 && "Unknown RegClassID");
373
374
375 } // for each operand in a call instruction
376
377
378
379
380 } // for all call instrctions in CallInstrList
381
382}
383
384
385void UltraSparcRegInfo::setCallArgColor(LiveRange *const LR,
386 const unsigned RegNo) const {
387
388 // if no call interference and LR is NOT previously colored (e.g., as an
389 // incoming arg)
390 if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) {
391 // we can directly allocate a %o register
392 LR->setColor( RegNo);
393 if( DEBUG_RA) printReg( LR );
394 }
395 else { // there are call interferences
396
397 /*
398 // insert a copy machine instr to copy from LR to %o(reg)
399 PreMInstrMap[ CallMI ] =
400 getNewCopyMInstr( LR->, SparcIntRegOrder::o0 + intArgNo );
401 */
402 cout << " $$$ TODO: Insert a copy for call argument!: " << endl;
403
404 // We don't color LR here. It's colored as any other normal LR
405 }
406
407}
408
409
410
411
412
Chris Lattner20b1ea02001-09-14 03:47:57 +0000413//---------------------------------------------------------------------------
414// class UltraSparcMachine
415//
416// Purpose:
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.
421//
422//---------------------------------------------------------------------------
423
Chris Lattnerf6e0e282001-09-14 04:32:55 +0000424UltraSparc::UltraSparc() : TargetMachine("UltraSparc-Native"),
Ruchira Sasankae38bd5332001-09-15 00:30:44 +0000425 InstSchedulingInfo(&InstInfo),
426 RegInfo( this ) {
Chris Lattner20b1ea02001-09-14 03:47:57 +0000427 optSizeForSubWordData = 4;
428 minMemOpWordSize = 8;
429 maxAtomicMemOpWordSize = 8;
430 zeroRegNum = 0; // %g0 always gives 0 on Sparc
431}
432
Ruchira Sasankae38bd5332001-09-15 00:30:44 +0000433
434
435//----------------------------------------------------------------------------
436// Entry point for register allocation for a module
437//----------------------------------------------------------------------------
438
439void AllocateRegisters(Method *M, TargetMachine &TM)
440{
441
442 if ( (M)->isExternal() ) // don't process prototypes
443 return;
444
445 if( DEBUG_RA ) {
446 cout << endl << "******************** Method "<< (M)->getName();
447 cout << " ********************" <<endl;
448 }
449
450 MethodLiveVarInfo LVI(M ); // Analyze live varaibles
451 LVI.analyze();
452
453
454 PhyRegAlloc PRA(M, TM , &LVI); // allocate registers
455 PRA.allocateRegisters();
456
457
458 if( DEBUG_RA ) cout << endl << "Register allocation complete!" << endl;
459
460}
461
462
463
464
465
Chris Lattner20b1ea02001-09-14 03:47:57 +0000466bool UltraSparc::compileMethod(Method *M) {
467 if (SelectInstructionsForMethod(M, *this)) {
468 cerr << "Instruction selection failed for method " << M->getName()
469 << "\n\n";
470 return true;
471 }
472
Chris Lattnerf6e0e282001-09-14 04:32:55 +0000473 if (ScheduleInstructionsWithSSA(M, *this, InstSchedulingInfo)) {
Chris Lattner20b1ea02001-09-14 03:47:57 +0000474 cerr << "Instruction scheduling before allocation failed for method "
475 << M->getName() << "\n\n";
476 return true;
477 }
Ruchira Sasankae38bd5332001-09-15 00:30:44 +0000478
479 AllocateRegisters(M, *this); // allocate registers
480
481
Chris Lattner20b1ea02001-09-14 03:47:57 +0000482 return false;
483}
Chris Lattnerf6e0e282001-09-14 04:32:55 +0000484