blob: 3e9998004df5dddd17a1069afc5739bbe5f180ec [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
Ruchira Sasankae38bd5332001-09-15 00:30:44 +000093
Ruchira Sasankae38bd5332001-09-15 00:30:44 +000094
95//---------------------------------------------------------------------------
96// UltraSparcRegInfo
97// Purpose:
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
100// stack
101//---------------------------------------------------------------------------
102
103
104void UltraSparcRegInfo::colorArgs(const Method *const Meth,
105 LiveRangeInfo& LRI) const
106{
107
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();
112 unsigned intArgNo=0;
113
114 // to keep track of which float regs are allocated for argument passing
115 bool FloatArgUsedArr[NumOfFloatArgRegs];
116
117 // init float arg used array
118 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
119 FloatArgUsedArr[i] = false;
120
121 // for each argument
122 for( ; ArgIt != ArgList.end() ; ++ArgIt) {
123
124 // get the LR of arg
125 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *ArgIt);
126 unsigned RegClassID = (LR->getRegClass())->getID();
127
128 // if the arg is in int class - allocate a reg for an int arg
129 if( RegClassID == IntRegClassID ) {
130
131 if( intArgNo < NumOfIntArgRegs) {
132 LR->setColor( SparcIntRegOrder::i0 + intArgNo );
133
134 if( DEBUG_RA) printReg( LR );
135 }
136
137 else {
138 // TODO: Insert push code here
139 assert( 0 && "Insert push code here!");
140 }
141 ++intArgNo;
142 }
143
144 // if the arg is float/double
145 else if ( RegClassID == FloatRegClassID) {
146
147 if( LR->getTypeID() == Type::DoubleTyID ) {
148
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 );
156 break;
157 }
158 }
159 if( ! LR->hasColor() ) { // if LR was not colored above
160
161 assert(0 && "insert push code here for a double");
162
163 }
164
165 }
166 else if( LR->getTypeID() == Type::FloatTyID ) {
167
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 );
174 break;
175 }
176 }
177 if( ! LR->hasColor() ) { // if LR was not colored above
178 assert(0 && "insert push code here for a float");
179 }
180
181 }
182 else
183 assert(0 && "unknown float type in method arg");
184
185 } // float register class
186
187 else
188 assert(0 && "Unknown RegClassID");
189 }
190
191}
192
193
194
195
196
197
198void UltraSparcRegInfo::printReg(const LiveRange *const LR) {
199
200 unsigned RegClassID = (LR->getRegClass())->getID();
201
202 cout << " *Node " << (LR->getUserIGNode())->getIndex();
203
204 if( ! LR->hasColor() ) {
205 cout << " - could not find a color" << endl;
206 return;
207 }
208
209 // if a color is found
210
211 cout << " colored with color "<< LR->getColor();
212
213 if( RegClassID == IntRegClassID ) {
214
215 cout<< " [" << SparcIntRegOrder::getRegName(LR->getColor()) ;
216 cout << "]" << endl;
217 }
218 else if ( RegClassID == FloatRegClassID) {
219 cout << "[" << SparcFloatRegOrder::getRegName(LR->getColor());
220 if( LR->getTypeID() == Type::DoubleTyID )
221 cout << "+" << SparcFloatRegOrder::getRegName(LR->getColor()+1);
222 cout << "]" << endl;
223 }
224
225
226}
227
228
229void UltraSparcRegInfo::colorCallArgs(vector<const Instruction *> &
230 CallInstrList, LiveRangeInfo& LRI,
231 AddedInstrMapType &AddedInstrMap) const
232{
233
234 vector<const Instruction *>::const_iterator InstIt = CallInstrList.begin();
235
236 for( ; InstIt != CallInstrList.end(); ++InstIt) {
237
238 // Inst = LLVM call instruction
239 const Instruction *const CallI = *InstIt;
240
241 MachineCodeForVMInstr & MInstVec = CallI->getMachineInstrVec();
242 MachineCodeForVMInstr::const_iterator MIIt = MInstVec.begin();
243
244 // find the CALL/JMMPL machine instruction
245 for( ; MIIt != MInstVec.end() &&
246 ! getUltraSparcInfo().getInstrInfo().isCall((*MIIt)->getOpCode());
247 ++MIIt );
248
249 assert( (MIIt != MInstVec.end()) && "CALL/JMPL not found");
250
251 // CallMI = CALL/JMPL machine isntruction
252 const MachineInstr *const CallMI = *MIIt;
253
254 Instruction::op_const_iterator OpIt = CallI->op_begin();
255
256 unsigned intArgNo=0;
257 //unsigned NumOfCallInterfs = LR->getNumOfCallInterferences();
258
259 // to keep track of which float regs are allocated for argument passing
260 bool FloatArgUsedArr[NumOfFloatArgRegs];
261
262 // init float arg used array
263 for(unsigned i=0; i < NumOfFloatArgRegs; ++i)
264 FloatArgUsedArr[i] = false;
265
266 // go thru all the operands of LLVM instruction
267 for( ; OpIt != CallI->op_end(); ++OpIt ) {
268
269 // get the LR of call operand (parameter)
270 LiveRange *const LR = LRI.getLiveRangeForValue((const Value *) *OpIt);
271
272 if ( !LR ) {
273 cout << " Warning: In call instr, no LR for arg: " ;
274 printValue(*OpIt);
275 cout << endl;
276 continue;
277 }
278
279 unsigned RegClassID = (LR->getRegClass())->getID();
280
281 // if the arg is in int class - allocate a reg for an int arg
282 if( RegClassID == IntRegClassID ) {
283
284 if( intArgNo < NumOfIntArgRegs) {
285 setCallArgColor( LR, SparcIntRegOrder::o0 + intArgNo );
286 }
287
288 else {
289 // TODO: Insert push code here
290 assert( 0 && "Insert push code here!");
291
292 AddedInstrns * AI = AddedInstrMap[ CallMI ];
293 if( ! AI ) AI = new AddedInstrns();
294
295 // AI->InstrnsBefore.push_back( getStackPushInstr(LR) );
296 AddedInstrMap[ CallMI ] = AI;
297
298 }
299 ++intArgNo;
300 }
301
302 // if the arg is float/double
303 else if ( RegClassID == FloatRegClassID) {
304
305 if( LR->getTypeID() == Type::DoubleTyID ) {
306
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 );
314 break;
315 }
316 }
317 if( ! LR->hasColor() ) { // if LR was not colored above
318
319 assert(0 && "insert push code here for a double");
320
321 }
322
323 }
324 else if( LR->getTypeID() == Type::FloatTyID ) {
325
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 );
333 break;
334 }
335 }
336 if( ! LR->hasColor() ) { // if LR was not colored above
337 assert(0 && "insert push code here for a float");
338 }
339
340 }
341 else
342 assert(0 && "unknown float type in method arg");
343
344 } // float register class
345
346 else
347 assert(0 && "Unknown RegClassID");
348
349
350 } // for each operand in a call instruction
351
352
353
354
355 } // for all call instrctions in CallInstrList
356
357}
358
359
360void UltraSparcRegInfo::setCallArgColor(LiveRange *const LR,
361 const unsigned RegNo) const {
362
363 // if no call interference and LR is NOT previously colored (e.g., as an
364 // incoming arg)
365 if( ! LR->getNumOfCallInterferences() && ! LR->hasColor() ) {
366 // we can directly allocate a %o register
367 LR->setColor( RegNo);
368 if( DEBUG_RA) printReg( LR );
369 }
370 else { // there are call interferences
371
372 /*
373 // insert a copy machine instr to copy from LR to %o(reg)
374 PreMInstrMap[ CallMI ] =
375 getNewCopyMInstr( LR->, SparcIntRegOrder::o0 + intArgNo );
376 */
377 cout << " $$$ TODO: Insert a copy for call argument!: " << endl;
378
379 // We don't color LR here. It's colored as any other normal LR
380 }
381
382}
383
384
385
386
387
Chris Lattner20b1ea02001-09-14 03:47:57 +0000388//---------------------------------------------------------------------------
389// class UltraSparcMachine
390//
391// Purpose:
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.
396//
397//---------------------------------------------------------------------------
398
Chris Lattnerf6e0e282001-09-14 04:32:55 +0000399UltraSparc::UltraSparc() : TargetMachine("UltraSparc-Native"),
Ruchira Sasankae38bd5332001-09-15 00:30:44 +0000400 InstSchedulingInfo(&InstInfo),
401 RegInfo( this ) {
Chris Lattner20b1ea02001-09-14 03:47:57 +0000402 optSizeForSubWordData = 4;
403 minMemOpWordSize = 8;
404 maxAtomicMemOpWordSize = 8;
Ruchira Sasanka866f1382001-09-15 19:11:31 +0000405 zeroRegNum = RegInfo.getZeroReg(); // %g0 always gives 0 on Sparc
Chris Lattner20b1ea02001-09-14 03:47:57 +0000406}
407
Ruchira Sasankae38bd5332001-09-15 00:30:44 +0000408
409
410//----------------------------------------------------------------------------
411// Entry point for register allocation for a module
412//----------------------------------------------------------------------------
413
414void AllocateRegisters(Method *M, TargetMachine &TM)
415{
416
417 if ( (M)->isExternal() ) // don't process prototypes
418 return;
419
420 if( DEBUG_RA ) {
421 cout << endl << "******************** Method "<< (M)->getName();
422 cout << " ********************" <<endl;
423 }
424
425 MethodLiveVarInfo LVI(M ); // Analyze live varaibles
426 LVI.analyze();
427
428
429 PhyRegAlloc PRA(M, TM , &LVI); // allocate registers
430 PRA.allocateRegisters();
431
432
433 if( DEBUG_RA ) cout << endl << "Register allocation complete!" << endl;
434
435}
436
437
438
439
440
Chris Lattner20b1ea02001-09-14 03:47:57 +0000441bool UltraSparc::compileMethod(Method *M) {
442 if (SelectInstructionsForMethod(M, *this)) {
443 cerr << "Instruction selection failed for method " << M->getName()
444 << "\n\n";
445 return true;
446 }
447
Chris Lattnerf6e0e282001-09-14 04:32:55 +0000448 if (ScheduleInstructionsWithSSA(M, *this, InstSchedulingInfo)) {
Chris Lattner20b1ea02001-09-14 03:47:57 +0000449 cerr << "Instruction scheduling before allocation failed for method "
450 << M->getName() << "\n\n";
451 return true;
452 }
Ruchira Sasankae38bd5332001-09-15 00:30:44 +0000453
454 AllocateRegisters(M, *this); // allocate registers
455
456
Chris Lattner20b1ea02001-09-14 03:47:57 +0000457 return false;
458}
Chris Lattnerf6e0e282001-09-14 04:32:55 +0000459