blob: 2476a5f574a6724d98f0b6f99a4469f0339703be [file] [log] [blame]
Vikram S. Adve0fb49802001-09-18 13:01:29 +00001// $Id$
Chris Lattner20b1ea02001-09-14 03:47:57 +00002//***************************************************************************
3// File:
4// Sparc.cpp
5//
6// Purpose:
7//
8// History:
9// 7/15/01 - Vikram Adve - Created
10//**************************************************************************/
11
Vikram S. Adve9db43182001-10-22 13:44:23 +000012
Chris Lattner20b1ea02001-09-14 03:47:57 +000013#include "SparcInternals.h"
Vikram S. Adve9db43182001-10-22 13:44:23 +000014#include "llvm/Target/Sparc.h"
Chris Lattner20b1ea02001-09-14 03:47:57 +000015#include "llvm/CodeGen/InstrScheduling.h"
16#include "llvm/CodeGen/InstrSelection.h"
Chris Lattnercf4525b2002-02-03 07:49:15 +000017#include "llvm/CodeGen/MachineCodeForInstruction.h"
18#include "llvm/CodeGen/MachineCodeForMethod.h"
Ruchira Sasankae38bd5332001-09-15 00:30:44 +000019#include "llvm/CodeGen/PhyRegAlloc.h"
Vikram S. Adve9db43182001-10-22 13:44:23 +000020#include "llvm/Method.h"
Chris Lattner0feb3582002-02-03 23:41:51 +000021#include "llvm/PassManager.h"
Chris Lattner697954c2002-01-20 22:54:45 +000022#include <iostream>
23using std::cerr;
Ruchira Sasankae38bd5332001-09-15 00:30:44 +000024
Chris Lattner9a3d63b2001-09-19 15:56:23 +000025// Build the MachineInstruction Description Array...
26const MachineInstrDescriptor SparcMachineInstrDesc[] = {
27#define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
28 NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS) \
29 { OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
30 NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS },
31#include "SparcInstr.def"
32};
Vikram S. Adve0fb49802001-09-18 13:01:29 +000033
34//----------------------------------------------------------------------------
Chris Lattner46cbff62001-09-14 16:56:32 +000035// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
36// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
Vikram S. Adve0fb49802001-09-18 13:01:29 +000037//----------------------------------------------------------------------------
Chris Lattner46cbff62001-09-14 16:56:32 +000038//
Ruchira Sasankacc3ccac2001-10-15 16:25:28 +000039
Chris Lattner46cbff62001-09-14 16:56:32 +000040TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); }
Chris Lattner20b1ea02001-09-14 03:47:57 +000041
42
Vikram S. Adve0fb49802001-09-18 13:01:29 +000043//----------------------------------------------------------------------------
44// Entry point for register allocation for a module
45//----------------------------------------------------------------------------
46
Chris Lattner0feb3582002-02-03 23:41:51 +000047class RegisterAllocation : public MethodPass {
48 TargetMachine &Target;
49public:
50 inline RegisterAllocation(TargetMachine &T) : Target(T) {}
51 bool runOnMethod(Method *M) {
52 if (DEBUG_RA)
53 cerr << "\n******************** Method "<< M->getName()
54 << " ********************\n";
Vikram S. Adve0fb49802001-09-18 13:01:29 +000055
Chris Lattner0feb3582002-02-03 23:41:51 +000056 MethodLiveVarInfo LVI(M ); // Analyze live varaibles
57 LVI.analyze();
Vikram S. Adve0fb49802001-09-18 13:01:29 +000058
Chris Lattner0feb3582002-02-03 23:41:51 +000059 PhyRegAlloc PRA(M, Target, &LVI); // allocate registers
60 PRA.allocateRegisters();
Vikram S. Adve0fb49802001-09-18 13:01:29 +000061
Chris Lattner0feb3582002-02-03 23:41:51 +000062 if (DEBUG_RA) cerr << "\nRegister allocation complete!\n";
63 return false;
64 }
65};
Vikram S. Adve0fb49802001-09-18 13:01:29 +000066
Chris Lattner0feb3582002-02-03 23:41:51 +000067static MachineInstr* minstrVec[MAX_INSTR_PER_VMINSTR];
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +000068
Vikram S. Adve9db43182001-10-22 13:44:23 +000069//---------------------------------------------------------------------------
Chris Lattner0feb3582002-02-03 23:41:51 +000070// class InsertPrologEpilogCode
71//
72// Insert SAVE/RESTORE instructions for the method
73//
Vikram S. Adve9db43182001-10-22 13:44:23 +000074// Insert prolog code at the unique method entry point.
75// Insert epilog code at each method exit point.
76// InsertPrologEpilog invokes these only if the method is not compiled
77// with the leaf method optimization.
Chris Lattner0feb3582002-02-03 23:41:51 +000078//
Vikram S. Adve9db43182001-10-22 13:44:23 +000079//---------------------------------------------------------------------------
80
Chris Lattner0feb3582002-02-03 23:41:51 +000081class InsertPrologEpilogCode : public MethodPass {
82 TargetMachine &Target;
83public:
84 inline InsertPrologEpilogCode(TargetMachine &T) : Target(T) {}
85 bool runOnMethod(Method *M) {
86 MachineCodeForMethod &mcodeInfo = MachineCodeForMethod::get(M);
87 if (!mcodeInfo.isCompiledAsLeafMethod()) {
88 InsertPrologCode(M);
89 InsertEpilogCode(M);
90 }
91 return false;
92 }
Vikram S. Adve9db43182001-10-22 13:44:23 +000093
Chris Lattner0feb3582002-02-03 23:41:51 +000094 void InsertPrologCode(Method *M);
95 void InsertEpilogCode(Method *M);
96};
97
98void InsertPrologEpilogCode::InsertPrologCode(Method* method)
Vikram S. Adve9db43182001-10-22 13:44:23 +000099{
100 BasicBlock* entryBB = method->getEntryNode();
Chris Lattner0feb3582002-02-03 23:41:51 +0000101 unsigned N = GetInstructionsForProlog(entryBB, Target, minstrVec);
Vikram S. Adve9db43182001-10-22 13:44:23 +0000102 assert(N <= MAX_INSTR_PER_VMINSTR);
Chris Lattner0feb3582002-02-03 23:41:51 +0000103 MachineCodeForBasicBlock& bbMvec = entryBB->getMachineInstrVec();
104 bbMvec.insert(bbMvec.begin(), minstrVec, minstrVec+N);
Vikram S. Adve9db43182001-10-22 13:44:23 +0000105}
106
107
Chris Lattner0feb3582002-02-03 23:41:51 +0000108void InsertPrologEpilogCode::InsertEpilogCode(Method* method)
Vikram S. Adve9db43182001-10-22 13:44:23 +0000109{
110 for (Method::iterator I=method->begin(), E=method->end(); I != E; ++I)
111 if ((*I)->getTerminator()->getOpcode() == Instruction::Ret)
112 {
113 BasicBlock* exitBB = *I;
Chris Lattner0feb3582002-02-03 23:41:51 +0000114 unsigned N = GetInstructionsForEpilog(exitBB, Target, minstrVec);
Vikram S. Adve9db43182001-10-22 13:44:23 +0000115
116 MachineCodeForBasicBlock& bbMvec = exitBB->getMachineInstrVec();
Chris Lattnercf4525b2002-02-03 07:49:15 +0000117 MachineCodeForInstruction &termMvec =
118 MachineCodeForInstruction::get(exitBB->getTerminator());
Vikram S. Adve9db43182001-10-22 13:44:23 +0000119
120 // Remove the NOPs in the delay slots of the return instruction
Chris Lattner0feb3582002-02-03 23:41:51 +0000121 const MachineInstrInfo &mii = Target.getInstrInfo();
Vikram S. Adve9db43182001-10-22 13:44:23 +0000122 unsigned numNOPs = 0;
123 while (termMvec.back()->getOpCode() == NOP)
124 {
125 assert( termMvec.back() == bbMvec.back());
126 termMvec.pop_back();
127 bbMvec.pop_back();
128 ++numNOPs;
129 }
130 assert(termMvec.back() == bbMvec.back());
131
132 // Check that we found the right number of NOPs and have the right
133 // number of instructions to replace them.
134 unsigned ndelays = mii.getNumDelaySlots(termMvec.back()->getOpCode());
135 assert(numNOPs == ndelays && "Missing NOPs in delay slots?");
136 assert(N == ndelays && "Cannot use epilog code for delay slots?");
137
138 // Append the epilog code to the end of the basic block.
139 bbMvec.push_back(minstrVec[0]);
140 }
141}
142
143
Chris Lattner7327d7e2002-02-04 00:04:35 +0000144/*---------------------------------------------------------------------------
145Scheduling guidelines for SPARC IIi:
146
147I-Cache alignment rules (pg 326)
148-- Align a branch target instruction so that it's entire group is within
149 the same cache line (may be 1-4 instructions).
150** Don't let a branch that is predicted taken be the last instruction
151 on an I-cache line: delay slot will need an entire line to be fetched
152-- Make a FP instruction or a branch be the 4th instruction in a group.
153 For branches, there are tradeoffs in reordering to make this happen
154 (see pg. 327).
155** Don't put a branch in a group that crosses a 32-byte boundary!
156 An artificial branch is inserted after every 32 bytes, and having
157 another branch will force the group to be broken into 2 groups.
158
159iTLB rules:
160-- Don't let a loop span two memory pages, if possible
161
162Branch prediction performance:
163-- Don't make the branch in a delay slot the target of a branch
164-- Try not to have 2 predicted branches within a group of 4 instructions
165 (because each such group has a single branch target field).
166-- Try to align branches in slots 0, 2, 4 or 6 of a cache line (to avoid
167 the wrong prediction bits being used in some cases).
168
169D-Cache timing constraints:
170-- Signed int loads of less than 64 bits have 3 cycle latency, not 2
171-- All other loads that hit in D-Cache have 2 cycle latency
172-- All loads are returned IN ORDER, so a D-Cache miss will delay a later hit
173-- Mis-aligned loads or stores cause a trap. In particular, replace
174 mis-aligned FP double precision l/s with 2 single-precision l/s.
175-- Simulations of integer codes show increase in avg. group size of
176 33% when code (including esp. non-faulting loads) is moved across
177 one branch, and 50% across 2 branches.
178
179E-Cache timing constraints:
180-- Scheduling for E-cache (D-Cache misses) is effective (due to load buffering)
181
182Store buffer timing constraints:
183-- Stores can be executed in same cycle as instruction producing the value
184-- Stores are buffered and have lower priority for E-cache until
185 highwater mark is reached in the store buffer (5 stores)
186
187Pipeline constraints:
188-- Shifts can only use IEU0.
189-- CC setting instructions can only use IEU1.
190-- Several other instructions must only use IEU1:
191 EDGE(?), ARRAY(?), CALL, JMPL, BPr, PST, and FCMP.
192-- Two instructions cannot store to the same register file in a single cycle
193 (single write port per file).
194
195Issue and grouping constraints:
196-- FP and branch instructions must use slot 4.
197-- Shift instructions cannot be grouped with other IEU0-specific instructions.
198-- CC setting instructions cannot be grouped with other IEU1-specific instrs.
199-- Several instructions must be issued in a single-instruction group:
200 MOVcc or MOVr, MULs/x and DIVs/x, SAVE/RESTORE, many others
201-- A CALL or JMPL breaks a group, ie, is not combined with subsequent instrs.
202--
203--
204
205Branch delay slot scheduling rules:
206-- A CTI couple (two back-to-back CTI instructions in the dynamic stream)
207 has a 9-instruction penalty: the entire pipeline is flushed when the
208 second instruction reaches stage 9 (W-Writeback).
209-- Avoid putting multicycle instructions, and instructions that may cause
210 load misses, in the delay slot of an annulling branch.
211-- Avoid putting WR, SAVE..., RESTORE and RETURN instructions in the
212 delay slot of an annulling branch.
213
214 *--------------------------------------------------------------------------- */
215
216//---------------------------------------------------------------------------
217// List of CPUResources for UltraSPARC IIi.
218//---------------------------------------------------------------------------
219
220static const CPUResource AllIssueSlots( "All Instr Slots", 4);
221static const CPUResource IntIssueSlots( "Int Instr Slots", 3);
222static const CPUResource First3IssueSlots("Instr Slots 0-3", 3);
223static const CPUResource LSIssueSlots( "Load-Store Instr Slot", 1);
224static const CPUResource CTIIssueSlots( "Ctrl Transfer Instr Slot", 1);
225static const CPUResource FPAIssueSlots( "Int Instr Slot 1", 1);
226static const CPUResource FPMIssueSlots( "Int Instr Slot 1", 1);
227
228// IEUN instructions can use either Alu and should use IAluN.
229// IEU0 instructions must use Alu 1 and should use both IAluN and IAlu0.
230// IEU1 instructions must use Alu 2 and should use both IAluN and IAlu1.
231static const CPUResource IAluN("Int ALU 1or2", 2);
232static const CPUResource IAlu0("Int ALU 1", 1);
233static const CPUResource IAlu1("Int ALU 2", 1);
234
235static const CPUResource LSAluC1("Load/Store Unit Addr Cycle", 1);
236static const CPUResource LSAluC2("Load/Store Unit Issue Cycle", 1);
237static const CPUResource LdReturn("Load Return Unit", 1);
238
239static const CPUResource FPMAluC1("FP Mul/Div Alu Cycle 1", 1);
240static const CPUResource FPMAluC2("FP Mul/Div Alu Cycle 2", 1);
241static const CPUResource FPMAluC3("FP Mul/Div Alu Cycle 3", 1);
242
243static const CPUResource FPAAluC1("FP Other Alu Cycle 1", 1);
244static const CPUResource FPAAluC2("FP Other Alu Cycle 2", 1);
245static const CPUResource FPAAluC3("FP Other Alu Cycle 3", 1);
246
247static const CPUResource IRegReadPorts("Int Reg ReadPorts", INT_MAX); // CHECK
248static const CPUResource IRegWritePorts("Int Reg WritePorts", 2); // CHECK
249static const CPUResource FPRegReadPorts("FP Reg Read Ports", INT_MAX);// CHECK
250static const CPUResource FPRegWritePorts("FP Reg Write Ports", 1); // CHECK
251
252static const CPUResource CTIDelayCycle( "CTI delay cycle", 1);
253static const CPUResource FCMPDelayCycle("FCMP delay cycle", 1);
254
255
256
257//---------------------------------------------------------------------------
258// const InstrClassRUsage SparcRUsageDesc[]
259//
260// Purpose:
261// Resource usage information for instruction in each scheduling class.
262// The InstrRUsage Objects for individual classes are specified first.
263// Note that fetch and decode are decoupled from the execution pipelines
264// via an instr buffer, so they are not included in the cycles below.
265//---------------------------------------------------------------------------
266
267static const InstrClassRUsage NoneClassRUsage = {
268 SPARC_NONE,
269 /*totCycles*/ 7,
270
271 /* maxIssueNum */ 4,
272 /* isSingleIssue */ false,
273 /* breaksGroup */ false,
274 /* numBubbles */ 0,
275
276 /*numSlots*/ 4,
277 /* feasibleSlots[] */ { 0, 1, 2, 3 },
278
279 /*numEntries*/ 0,
280 /* V[] */ {
281 /*Cycle G */
282 /*Ccle E */
283 /*Cycle C */
284 /*Cycle N1*/
285 /*Cycle N1*/
286 /*Cycle N1*/
287 /*Cycle W */
288 }
289};
290
291static const InstrClassRUsage IEUNClassRUsage = {
292 SPARC_IEUN,
293 /*totCycles*/ 7,
294
295 /* maxIssueNum */ 3,
296 /* isSingleIssue */ false,
297 /* breaksGroup */ false,
298 /* numBubbles */ 0,
299
300 /*numSlots*/ 3,
301 /* feasibleSlots[] */ { 0, 1, 2 },
302
303 /*numEntries*/ 4,
304 /* V[] */ {
305 /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
306 { IntIssueSlots.rid, 0, 1 },
307 /*Cycle E */ { IAluN.rid, 1, 1 },
308 /*Cycle C */
309 /*Cycle N1*/
310 /*Cycle N1*/
311 /*Cycle N1*/
312 /*Cycle W */ { IRegWritePorts.rid, 6, 1 }
313 }
314};
315
316static const InstrClassRUsage IEU0ClassRUsage = {
317 SPARC_IEU0,
318 /*totCycles*/ 7,
319
320 /* maxIssueNum */ 1,
321 /* isSingleIssue */ false,
322 /* breaksGroup */ false,
323 /* numBubbles */ 0,
324
325 /*numSlots*/ 3,
326 /* feasibleSlots[] */ { 0, 1, 2 },
327
328 /*numEntries*/ 5,
329 /* V[] */ {
330 /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
331 { IntIssueSlots.rid, 0, 1 },
332 /*Cycle E */ { IAluN.rid, 1, 1 },
333 { IAlu0.rid, 1, 1 },
334 /*Cycle C */
335 /*Cycle N1*/
336 /*Cycle N1*/
337 /*Cycle N1*/
338 /*Cycle W */ { IRegWritePorts.rid, 6, 1 }
339 }
340};
341
342static const InstrClassRUsage IEU1ClassRUsage = {
343 SPARC_IEU1,
344 /*totCycles*/ 7,
345
346 /* maxIssueNum */ 1,
347 /* isSingleIssue */ false,
348 /* breaksGroup */ false,
349 /* numBubbles */ 0,
350
351 /*numSlots*/ 3,
352 /* feasibleSlots[] */ { 0, 1, 2 },
353
354 /*numEntries*/ 5,
355 /* V[] */ {
356 /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
357 { IntIssueSlots.rid, 0, 1 },
358 /*Cycle E */ { IAluN.rid, 1, 1 },
359 { IAlu1.rid, 1, 1 },
360 /*Cycle C */
361 /*Cycle N1*/
362 /*Cycle N1*/
363 /*Cycle N1*/
364 /*Cycle W */ { IRegWritePorts.rid, 6, 1 }
365 }
366};
367
368static const InstrClassRUsage FPMClassRUsage = {
369 SPARC_FPM,
370 /*totCycles*/ 7,
371
372 /* maxIssueNum */ 1,
373 /* isSingleIssue */ false,
374 /* breaksGroup */ false,
375 /* numBubbles */ 0,
376
377 /*numSlots*/ 4,
378 /* feasibleSlots[] */ { 0, 1, 2, 3 },
379
380 /*numEntries*/ 7,
381 /* V[] */ {
382 /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
383 { FPMIssueSlots.rid, 0, 1 },
384 /*Cycle E */ { FPRegReadPorts.rid, 1, 1 },
385 /*Cycle C */ { FPMAluC1.rid, 2, 1 },
386 /*Cycle N1*/ { FPMAluC2.rid, 3, 1 },
387 /*Cycle N1*/ { FPMAluC3.rid, 4, 1 },
388 /*Cycle N1*/
389 /*Cycle W */ { FPRegWritePorts.rid, 6, 1 }
390 }
391};
392
393static const InstrClassRUsage FPAClassRUsage = {
394 SPARC_FPA,
395 /*totCycles*/ 7,
396
397 /* maxIssueNum */ 1,
398 /* isSingleIssue */ false,
399 /* breaksGroup */ false,
400 /* numBubbles */ 0,
401
402 /*numSlots*/ 4,
403 /* feasibleSlots[] */ { 0, 1, 2, 3 },
404
405 /*numEntries*/ 7,
406 /* V[] */ {
407 /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
408 { FPAIssueSlots.rid, 0, 1 },
409 /*Cycle E */ { FPRegReadPorts.rid, 1, 1 },
410 /*Cycle C */ { FPAAluC1.rid, 2, 1 },
411 /*Cycle N1*/ { FPAAluC2.rid, 3, 1 },
412 /*Cycle N1*/ { FPAAluC3.rid, 4, 1 },
413 /*Cycle N1*/
414 /*Cycle W */ { FPRegWritePorts.rid, 6, 1 }
415 }
416};
417
418static const InstrClassRUsage LDClassRUsage = {
419 SPARC_LD,
420 /*totCycles*/ 7,
421
422 /* maxIssueNum */ 1,
423 /* isSingleIssue */ false,
424 /* breaksGroup */ false,
425 /* numBubbles */ 0,
426
427 /*numSlots*/ 3,
428 /* feasibleSlots[] */ { 0, 1, 2, },
429
430 /*numEntries*/ 6,
431 /* V[] */ {
432 /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
433 { First3IssueSlots.rid, 0, 1 },
434 { LSIssueSlots.rid, 0, 1 },
435 /*Cycle E */ { LSAluC1.rid, 1, 1 },
436 /*Cycle C */ { LSAluC2.rid, 2, 1 },
437 { LdReturn.rid, 2, 1 },
438 /*Cycle N1*/
439 /*Cycle N1*/
440 /*Cycle N1*/
441 /*Cycle W */ { IRegWritePorts.rid, 6, 1 }
442 }
443};
444
445static const InstrClassRUsage STClassRUsage = {
446 SPARC_ST,
447 /*totCycles*/ 7,
448
449 /* maxIssueNum */ 1,
450 /* isSingleIssue */ false,
451 /* breaksGroup */ false,
452 /* numBubbles */ 0,
453
454 /*numSlots*/ 3,
455 /* feasibleSlots[] */ { 0, 1, 2 },
456
457 /*numEntries*/ 4,
458 /* V[] */ {
459 /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
460 { First3IssueSlots.rid, 0, 1 },
461 { LSIssueSlots.rid, 0, 1 },
462 /*Cycle E */ { LSAluC1.rid, 1, 1 },
463 /*Cycle C */ { LSAluC2.rid, 2, 1 }
464 /*Cycle N1*/
465 /*Cycle N1*/
466 /*Cycle N1*/
467 /*Cycle W */
468 }
469};
470
471static const InstrClassRUsage CTIClassRUsage = {
472 SPARC_CTI,
473 /*totCycles*/ 7,
474
475 /* maxIssueNum */ 1,
476 /* isSingleIssue */ false,
477 /* breaksGroup */ false,
478 /* numBubbles */ 0,
479
480 /*numSlots*/ 4,
481 /* feasibleSlots[] */ { 0, 1, 2, 3 },
482
483 /*numEntries*/ 4,
484 /* V[] */ {
485 /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
486 { CTIIssueSlots.rid, 0, 1 },
487 /*Cycle E */ { IAlu0.rid, 1, 1 },
488 /*Cycles E-C */ { CTIDelayCycle.rid, 1, 2 }
489 /*Cycle C */
490 /*Cycle N1*/
491 /*Cycle N1*/
492 /*Cycle N1*/
493 /*Cycle W */
494 }
495};
496
497static const InstrClassRUsage SingleClassRUsage = {
498 SPARC_SINGLE,
499 /*totCycles*/ 7,
500
501 /* maxIssueNum */ 1,
502 /* isSingleIssue */ true,
503 /* breaksGroup */ false,
504 /* numBubbles */ 0,
505
506 /*numSlots*/ 1,
507 /* feasibleSlots[] */ { 0 },
508
509 /*numEntries*/ 5,
510 /* V[] */ {
511 /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
512 { AllIssueSlots.rid, 0, 1 },
513 { AllIssueSlots.rid, 0, 1 },
514 { AllIssueSlots.rid, 0, 1 },
515 /*Cycle E */ { IAlu0.rid, 1, 1 }
516 /*Cycle C */
517 /*Cycle N1*/
518 /*Cycle N1*/
519 /*Cycle N1*/
520 /*Cycle W */
521 }
522};
523
524
525static const InstrClassRUsage SparcRUsageDesc[] = {
526 NoneClassRUsage,
527 IEUNClassRUsage,
528 IEU0ClassRUsage,
529 IEU1ClassRUsage,
530 FPMClassRUsage,
531 FPAClassRUsage,
532 CTIClassRUsage,
533 LDClassRUsage,
534 STClassRUsage,
535 SingleClassRUsage
536};
537
538
539
540//---------------------------------------------------------------------------
541// const InstrIssueDelta SparcInstrIssueDeltas[]
542//
543// Purpose:
544// Changes to issue restrictions information in InstrClassRUsage for
545// instructions that differ from other instructions in their class.
546//---------------------------------------------------------------------------
547
548static const InstrIssueDelta SparcInstrIssueDeltas[] = {
549
550 // opCode, isSingleIssue, breaksGroup, numBubbles
551
552 // Special cases for single-issue only
553 // Other single issue cases are below.
554//{ LDDA, true, true, 0 },
555//{ STDA, true, true, 0 },
556//{ LDDF, true, true, 0 },
557//{ LDDFA, true, true, 0 },
558 { ADDC, true, true, 0 },
559 { ADDCcc, true, true, 0 },
560 { SUBC, true, true, 0 },
561 { SUBCcc, true, true, 0 },
562//{ LDSTUB, true, true, 0 },
563//{ SWAP, true, true, 0 },
564//{ SWAPA, true, true, 0 },
565//{ CAS, true, true, 0 },
566//{ CASA, true, true, 0 },
567//{ CASX, true, true, 0 },
568//{ CASXA, true, true, 0 },
569//{ LDFSR, true, true, 0 },
570//{ LDFSRA, true, true, 0 },
571//{ LDXFSR, true, true, 0 },
572//{ LDXFSRA, true, true, 0 },
573//{ STFSR, true, true, 0 },
574//{ STFSRA, true, true, 0 },
575//{ STXFSR, true, true, 0 },
576//{ STXFSRA, true, true, 0 },
577//{ SAVED, true, true, 0 },
578//{ RESTORED, true, true, 0 },
579//{ FLUSH, true, true, 9 },
580//{ FLUSHW, true, true, 9 },
581//{ ALIGNADDR, true, true, 0 },
582 { RETURN, true, true, 0 },
583//{ DONE, true, true, 0 },
584//{ RETRY, true, true, 0 },
585//{ TCC, true, true, 0 },
586//{ SHUTDOWN, true, true, 0 },
587
588 // Special cases for breaking group *before*
589 // CURRENTLY NOT SUPPORTED!
590 { CALL, false, false, 0 },
591 { JMPLCALL, false, false, 0 },
592 { JMPLRET, false, false, 0 },
593
594 // Special cases for breaking the group *after*
595 { MULX, true, true, (4+34)/2 },
596 { FDIVS, false, true, 0 },
597 { FDIVD, false, true, 0 },
598 { FDIVQ, false, true, 0 },
599 { FSQRTS, false, true, 0 },
600 { FSQRTD, false, true, 0 },
601 { FSQRTQ, false, true, 0 },
602//{ FCMP{LE,GT,NE,EQ}, false, true, 0 },
603
604 // Instructions that introduce bubbles
605//{ MULScc, true, true, 2 },
606//{ SMULcc, true, true, (4+18)/2 },
607//{ UMULcc, true, true, (4+19)/2 },
608 { SDIVX, true, true, 68 },
609 { UDIVX, true, true, 68 },
610//{ SDIVcc, true, true, 36 },
611//{ UDIVcc, true, true, 37 },
612 { WRCCR, true, true, 4 },
613//{ WRPR, true, true, 4 },
614//{ RDCCR, true, true, 0 }, // no bubbles after, but see below
615//{ RDPR, true, true, 0 },
616};
617
618
619
620
621//---------------------------------------------------------------------------
622// const InstrRUsageDelta SparcInstrUsageDeltas[]
623//
624// Purpose:
625// Changes to resource usage information in InstrClassRUsage for
626// instructions that differ from other instructions in their class.
627//---------------------------------------------------------------------------
628
629static const InstrRUsageDelta SparcInstrUsageDeltas[] = {
630
631 // MachineOpCode, Resource, Start cycle, Num cycles
632
633 //
634 // JMPL counts as a load/store instruction for issue!
635 //
636 { JMPLCALL, LSIssueSlots.rid, 0, 1 },
637 { JMPLRET, LSIssueSlots.rid, 0, 1 },
638
639 //
640 // Many instructions cannot issue for the next 2 cycles after an FCMP
641 // We model that with a fake resource FCMPDelayCycle.
642 //
643 { FCMPS, FCMPDelayCycle.rid, 1, 3 },
644 { FCMPD, FCMPDelayCycle.rid, 1, 3 },
645 { FCMPQ, FCMPDelayCycle.rid, 1, 3 },
646
647 { MULX, FCMPDelayCycle.rid, 1, 1 },
648 { SDIVX, FCMPDelayCycle.rid, 1, 1 },
649 { UDIVX, FCMPDelayCycle.rid, 1, 1 },
650//{ SMULcc, FCMPDelayCycle.rid, 1, 1 },
651//{ UMULcc, FCMPDelayCycle.rid, 1, 1 },
652//{ SDIVcc, FCMPDelayCycle.rid, 1, 1 },
653//{ UDIVcc, FCMPDelayCycle.rid, 1, 1 },
654 { STD, FCMPDelayCycle.rid, 1, 1 },
655 { FMOVRSZ, FCMPDelayCycle.rid, 1, 1 },
656 { FMOVRSLEZ,FCMPDelayCycle.rid, 1, 1 },
657 { FMOVRSLZ, FCMPDelayCycle.rid, 1, 1 },
658 { FMOVRSNZ, FCMPDelayCycle.rid, 1, 1 },
659 { FMOVRSGZ, FCMPDelayCycle.rid, 1, 1 },
660 { FMOVRSGEZ,FCMPDelayCycle.rid, 1, 1 },
661
662 //
663 // Some instructions are stalled in the GROUP stage if a CTI is in
664 // the E or C stage. We model that with a fake resource CTIDelayCycle.
665 //
666 { LDD, CTIDelayCycle.rid, 1, 1 },
667//{ LDDA, CTIDelayCycle.rid, 1, 1 },
668//{ LDDSTUB, CTIDelayCycle.rid, 1, 1 },
669//{ LDDSTUBA, CTIDelayCycle.rid, 1, 1 },
670//{ SWAP, CTIDelayCycle.rid, 1, 1 },
671//{ SWAPA, CTIDelayCycle.rid, 1, 1 },
672//{ CAS, CTIDelayCycle.rid, 1, 1 },
673//{ CASA, CTIDelayCycle.rid, 1, 1 },
674//{ CASX, CTIDelayCycle.rid, 1, 1 },
675//{ CASXA, CTIDelayCycle.rid, 1, 1 },
676
677 //
678 // Signed int loads of less than dword size return data in cycle N1 (not C)
679 // and put all loads in consecutive cycles into delayed load return mode.
680 //
681 { LDSB, LdReturn.rid, 2, -1 },
682 { LDSB, LdReturn.rid, 3, 1 },
683
684 { LDSH, LdReturn.rid, 2, -1 },
685 { LDSH, LdReturn.rid, 3, 1 },
686
687 { LDSW, LdReturn.rid, 2, -1 },
688 { LDSW, LdReturn.rid, 3, 1 },
689
690 //
691 // RDPR from certain registers and RD from any register are not dispatchable
692 // until four clocks after they reach the head of the instr. buffer.
693 // Together with their single-issue requirement, this means all four issue
694 // slots are effectively blocked for those cycles, plus the issue cycle.
695 // This does not increase the latency of the instruction itself.
696 //
697 { RDCCR, AllIssueSlots.rid, 0, 5 },
698 { RDCCR, AllIssueSlots.rid, 0, 5 },
699 { RDCCR, AllIssueSlots.rid, 0, 5 },
700 { RDCCR, AllIssueSlots.rid, 0, 5 },
701
702#undef EXPLICIT_BUBBLES_NEEDED
703#ifdef EXPLICIT_BUBBLES_NEEDED
704 //
705 // MULScc inserts one bubble.
706 // This means it breaks the current group (captured in UltraSparcSchedInfo)
707 // *and occupies all issue slots for the next cycle
708 //
709//{ MULScc, AllIssueSlots.rid, 2, 2-1 },
710//{ MULScc, AllIssueSlots.rid, 2, 2-1 },
711//{ MULScc, AllIssueSlots.rid, 2, 2-1 },
712//{ MULScc, AllIssueSlots.rid, 2, 2-1 },
713
714 //
715 // SMULcc inserts between 4 and 18 bubbles, depending on #leading 0s in rs1.
716 // We just model this with a simple average.
717 //
718//{ SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 },
719//{ SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 },
720//{ SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 },
721//{ SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 },
722
723 // SMULcc inserts between 4 and 19 bubbles, depending on #leading 0s in rs1.
724//{ UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 },
725//{ UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 },
726//{ UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 },
727//{ UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 },
728
729 //
730 // MULX inserts between 4 and 34 bubbles, depending on #leading 0s in rs1.
731 //
732 { MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 },
733 { MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 },
734 { MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 },
735 { MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 },
736
737 //
738 // SDIVcc inserts 36 bubbles.
739 //
740//{ SDIVcc, AllIssueSlots.rid, 2, 36-1 },
741//{ SDIVcc, AllIssueSlots.rid, 2, 36-1 },
742//{ SDIVcc, AllIssueSlots.rid, 2, 36-1 },
743//{ SDIVcc, AllIssueSlots.rid, 2, 36-1 },
744
745 // UDIVcc inserts 37 bubbles.
746//{ UDIVcc, AllIssueSlots.rid, 2, 37-1 },
747//{ UDIVcc, AllIssueSlots.rid, 2, 37-1 },
748//{ UDIVcc, AllIssueSlots.rid, 2, 37-1 },
749//{ UDIVcc, AllIssueSlots.rid, 2, 37-1 },
750
751 //
752 // SDIVX inserts 68 bubbles.
753 //
754 { SDIVX, AllIssueSlots.rid, 2, 68-1 },
755 { SDIVX, AllIssueSlots.rid, 2, 68-1 },
756 { SDIVX, AllIssueSlots.rid, 2, 68-1 },
757 { SDIVX, AllIssueSlots.rid, 2, 68-1 },
758
759 //
760 // UDIVX inserts 68 bubbles.
761 //
762 { UDIVX, AllIssueSlots.rid, 2, 68-1 },
763 { UDIVX, AllIssueSlots.rid, 2, 68-1 },
764 { UDIVX, AllIssueSlots.rid, 2, 68-1 },
765 { UDIVX, AllIssueSlots.rid, 2, 68-1 },
766
767 //
768 // WR inserts 4 bubbles.
769 //
770//{ WR, AllIssueSlots.rid, 2, 68-1 },
771//{ WR, AllIssueSlots.rid, 2, 68-1 },
772//{ WR, AllIssueSlots.rid, 2, 68-1 },
773//{ WR, AllIssueSlots.rid, 2, 68-1 },
774
775 //
776 // WRPR inserts 4 bubbles.
777 //
778//{ WRPR, AllIssueSlots.rid, 2, 68-1 },
779//{ WRPR, AllIssueSlots.rid, 2, 68-1 },
780//{ WRPR, AllIssueSlots.rid, 2, 68-1 },
781//{ WRPR, AllIssueSlots.rid, 2, 68-1 },
782
783 //
784 // DONE inserts 9 bubbles.
785 //
786//{ DONE, AllIssueSlots.rid, 2, 9-1 },
787//{ DONE, AllIssueSlots.rid, 2, 9-1 },
788//{ DONE, AllIssueSlots.rid, 2, 9-1 },
789//{ DONE, AllIssueSlots.rid, 2, 9-1 },
790
791 //
792 // RETRY inserts 9 bubbles.
793 //
794//{ RETRY, AllIssueSlots.rid, 2, 9-1 },
795//{ RETRY, AllIssueSlots.rid, 2, 9-1 },
796//{ RETRY, AllIssueSlots.rid, 2, 9-1 },
797//{ RETRY, AllIssueSlots.rid, 2, 9-1 },
798
799#endif /*EXPLICIT_BUBBLES_NEEDED */
800};
801
802// Additional delays to be captured in code:
803// 1. RDPR from several state registers (page 349)
804// 2. RD from *any* register (page 349)
805// 3. Writes to TICK, PSTATE, TL registers and FLUSH{W} instr (page 349)
806// 4. Integer store can be in same group as instr producing value to store.
807// 5. BICC and BPICC can be in the same group as instr producing CC (pg 350)
808// 6. FMOVr cannot be in the same or next group as an IEU instr (pg 351).
809// 7. The second instr. of a CTI group inserts 9 bubbles (pg 351)
810// 8. WR{PR}, SVAE, SAVED, RESTORE, RESTORED, RETURN, RETRY, and DONE that
811// follow an annulling branch cannot be issued in the same group or in
812// the 3 groups following the branch.
813// 9. A predicted annulled load does not stall dependent instructions.
814// Other annulled delay slot instructions *do* stall dependents, so
815// nothing special needs to be done for them during scheduling.
816//10. Do not put a load use that may be annulled in the same group as the
817// branch. The group will stall until the load returns.
818//11. Single-prec. FP loads lock 2 registers, for dependency checking.
819//
820//
821// Additional delays we cannot or will not capture:
822// 1. If DCTI is last word of cache line, it is delayed until next line can be
823// fetched. Also, other DCTI alignment-related delays (pg 352)
824// 2. Load-after-store is delayed by 7 extra cycles if load hits in D-Cache.
825// Also, several other store-load and load-store conflicts (pg 358)
826// 3. MEMBAR, LD{X}FSR, LDD{A} and a bunch of other load stalls (pg 358)
827// 4. There can be at most 8 outstanding buffered store instructions
828// (including some others like MEMBAR, LDSTUB, CAS{AX}, and FLUSH)
Chris Lattner0feb3582002-02-03 23:41:51 +0000829
Vikram S. Adve9db43182001-10-22 13:44:23 +0000830
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +0000831
Chris Lattner20b1ea02001-09-14 03:47:57 +0000832//---------------------------------------------------------------------------
Chris Lattner20b1ea02001-09-14 03:47:57 +0000833// class UltraSparcSchedInfo
834//
835// Purpose:
836// Scheduling information for the UltraSPARC.
837// Primarily just initializes machine-dependent parameters in
838// class MachineSchedInfo.
839//---------------------------------------------------------------------------
840
841/*ctor*/
Vikram S. Adve7f37fe52001-11-08 04:55:13 +0000842UltraSparcSchedInfo::UltraSparcSchedInfo(const TargetMachine& tgt)
843 : MachineSchedInfo(tgt,
844 (unsigned int) SPARC_NUM_SCHED_CLASSES,
Chris Lattner20b1ea02001-09-14 03:47:57 +0000845 SparcRUsageDesc,
846 SparcInstrUsageDeltas,
847 SparcInstrIssueDeltas,
848 sizeof(SparcInstrUsageDeltas)/sizeof(InstrRUsageDelta),
849 sizeof(SparcInstrIssueDeltas)/sizeof(InstrIssueDelta))
850{
851 maxNumIssueTotal = 4;
852 longestIssueConflict = 0; // computed from issuesGaps[]
853
854 branchMispredictPenalty = 4; // 4 for SPARC IIi
855 branchTargetUnknownPenalty = 2; // 2 for SPARC IIi
856 l1DCacheMissPenalty = 8; // 7 or 9 for SPARC IIi
857 l1ICacheMissPenalty = 8; // ? for SPARC IIi
858
859 inOrderLoads = true; // true for SPARC IIi
860 inOrderIssue = true; // true for SPARC IIi
861 inOrderExec = false; // false for most architectures
862 inOrderRetire= true; // true for most architectures
863
864 // must be called after above parameters are initialized.
865 this->initializeResources();
866}
867
868void
869UltraSparcSchedInfo::initializeResources()
870{
871 // Compute MachineSchedInfo::instrRUsages and MachineSchedInfo::issueGaps
872 MachineSchedInfo::initializeResources();
873
874 // Machine-dependent fixups go here. None for now.
875}
876
877
Vikram S. Adve9db43182001-10-22 13:44:23 +0000878//---------------------------------------------------------------------------
879// class UltraSparcFrameInfo
880//
881// Purpose:
882// Interface to stack frame layout info for the UltraSPARC.
Vikram S. Adve00521d72001-11-12 23:26:35 +0000883// Starting offsets for each area of the stack frame are aligned at
884// a multiple of getStackFrameSizeAlignment().
Vikram S. Adve9db43182001-10-22 13:44:23 +0000885//---------------------------------------------------------------------------
886
887int
Vikram S. Adve7f37fe52001-11-08 04:55:13 +0000888UltraSparcFrameInfo::getFirstAutomaticVarOffset(MachineCodeForMethod& ,
889 bool& pos) const
Vikram S. Adve9db43182001-10-22 13:44:23 +0000890{
Vikram S. Adve7f37fe52001-11-08 04:55:13 +0000891 pos = false; // static stack area grows downwards
892 return StaticAreaOffsetFromFP;
Vikram S. Adve9db43182001-10-22 13:44:23 +0000893}
894
895int
Vikram S. Adve7f37fe52001-11-08 04:55:13 +0000896UltraSparcFrameInfo::getRegSpillAreaOffset(MachineCodeForMethod& mcInfo,
897 bool& pos) const
Vikram S. Adve9db43182001-10-22 13:44:23 +0000898{
Vikram S. Adve7f37fe52001-11-08 04:55:13 +0000899 pos = false; // static stack area grows downwards
900 unsigned int autoVarsSize = mcInfo.getAutomaticVarsSize();
Vikram S. Adve00521d72001-11-12 23:26:35 +0000901 if (int mod = autoVarsSize % getStackFrameSizeAlignment())
902 autoVarsSize += (getStackFrameSizeAlignment() - mod);
903 return StaticAreaOffsetFromFP - autoVarsSize;
Vikram S. Adve9db43182001-10-22 13:44:23 +0000904}
905
906int
Vikram S. Adve7f37fe52001-11-08 04:55:13 +0000907UltraSparcFrameInfo::getTmpAreaOffset(MachineCodeForMethod& mcInfo,
908 bool& pos) const
Vikram S. Adve9db43182001-10-22 13:44:23 +0000909{
Vikram S. Adve7f37fe52001-11-08 04:55:13 +0000910 pos = false; // static stack area grows downwards
911 unsigned int autoVarsSize = mcInfo.getAutomaticVarsSize();
912 unsigned int spillAreaSize = mcInfo.getRegSpillsSize();
Vikram S. Adve00521d72001-11-12 23:26:35 +0000913 int offset = autoVarsSize + spillAreaSize;
914 if (int mod = offset % getStackFrameSizeAlignment())
915 offset += (getStackFrameSizeAlignment() - mod);
916 return StaticAreaOffsetFromFP - offset;
Vikram S. Adve7f37fe52001-11-08 04:55:13 +0000917}
918
919int
920UltraSparcFrameInfo::getDynamicAreaOffset(MachineCodeForMethod& mcInfo,
921 bool& pos) const
922{
923 // dynamic stack area grows downwards starting at top of opt-args area
924 unsigned int optArgsSize = mcInfo.getMaxOptionalArgsSize();
Vikram S. Adve00521d72001-11-12 23:26:35 +0000925 int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP;
926 assert(offset % getStackFrameSizeAlignment() == 0);
927 return offset;
Vikram S. Adve9db43182001-10-22 13:44:23 +0000928}
929
Ruchira Sasankae38bd5332001-09-15 00:30:44 +0000930
Chris Lattner20b1ea02001-09-14 03:47:57 +0000931//---------------------------------------------------------------------------
932// class UltraSparcMachine
933//
934// Purpose:
935// Primary interface to machine description for the UltraSPARC.
936// Primarily just initializes machine-dependent parameters in
937// class TargetMachine, and creates machine-dependent subclasses
938// for classes such as MachineInstrInfo.
939//
940//---------------------------------------------------------------------------
941
Vikram S. Adve0fb49802001-09-18 13:01:29 +0000942UltraSparc::UltraSparc()
943 : TargetMachine("UltraSparc-Native"),
Vikram S. Adve7f37fe52001-11-08 04:55:13 +0000944 instrInfo(*this),
945 schedInfo(*this),
946 regInfo(*this),
Vikram S. Adveb7048402001-11-09 02:16:04 +0000947 frameInfo(*this),
948 cacheInfo(*this)
Vikram S. Adve0fb49802001-09-18 13:01:29 +0000949{
Chris Lattner20b1ea02001-09-14 03:47:57 +0000950 optSizeForSubWordData = 4;
951 minMemOpWordSize = 8;
952 maxAtomicMemOpWordSize = 8;
Chris Lattner20b1ea02001-09-14 03:47:57 +0000953}
954
Ruchira Sasankae38bd5332001-09-15 00:30:44 +0000955
Chris Lattner0feb3582002-02-03 23:41:51 +0000956
957//===---------------------------------------------------------------------===//
958// GenerateCodeForTarget Pass
959//
960// Native code generation for a specified target.
961//===---------------------------------------------------------------------===//
962
963class ConstructMachineCodeForMethod : public MethodPass {
964 TargetMachine &Target;
965public:
966 inline ConstructMachineCodeForMethod(TargetMachine &T) : Target(T) {}
967 bool runOnMethod(Method *M) {
968 MachineCodeForMethod::construct(M, Target);
969 return false;
970 }
971};
972
973class InstructionSelection : public MethodPass {
974 TargetMachine &Target;
975public:
976 inline InstructionSelection(TargetMachine &T) : Target(T) {}
977 bool runOnMethod(Method *M) {
978 if (SelectInstructionsForMethod(M, Target))
979 cerr << "Instr selection failed for method " << M->getName() << "\n";
980 return false;
981 }
982};
983
984class InstructionScheduling : public MethodPass {
985 TargetMachine &Target;
986public:
987 inline InstructionScheduling(TargetMachine &T) : Target(T) {}
988 bool runOnMethod(Method *M) {
989 if (ScheduleInstructionsWithSSA(M, Target))
990 cerr << "Instr scheduling failed for method " << M->getName() << "\n\n";
991 return false;
992 }
993};
994
995struct FreeMachineCodeForMethod : public MethodPass {
996 static void freeMachineCode(Instruction *I) {
997 MachineCodeForInstruction::destroy(I);
998 }
999
1000 bool runOnMethod(Method *M) {
1001 for_each(M->inst_begin(), M->inst_end(), freeMachineCode);
1002 // Don't destruct MachineCodeForMethod - The global printer needs it
1003 //MachineCodeForMethod::destruct(M);
1004 return false;
1005 }
1006};
Ruchira Sasanka89fb46b2001-09-18 22:52:44 +00001007
1008
Chris Lattner0feb3582002-02-03 23:41:51 +00001009void UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out) {
Vikram S. Adve7f37fe52001-11-08 04:55:13 +00001010 // Construct and initialize the MachineCodeForMethod object for this method.
Chris Lattner0feb3582002-02-03 23:41:51 +00001011 PM.add(new ConstructMachineCodeForMethod(*this));
Ruchira Sasankad00982a2002-01-07 19:20:28 +00001012
Chris Lattner0feb3582002-02-03 23:41:51 +00001013 PM.add(new InstructionSelection(*this));
Ruchira Sasankad00982a2002-01-07 19:20:28 +00001014
Chris Lattner0feb3582002-02-03 23:41:51 +00001015 //PM.add(new InstructionScheduling(*this));
Chris Lattnercf4525b2002-02-03 07:49:15 +00001016
Chris Lattner0feb3582002-02-03 23:41:51 +00001017 PM.add(new RegisterAllocation(*this));
1018
1019 //PM.add(new OptimizeLeafProcedures());
1020 //PM.add(new DeleteFallThroughBranches());
1021 //PM.add(new RemoveChainedBranches()); // should be folded with previous
1022 //PM.add(new RemoveRedundantOps()); // operations with %g0, NOP, etc.
1023
1024 PM.add(new InsertPrologEpilogCode(*this));
1025
1026 // Output assembly language to the .s file. Assembly emission is split into
1027 // two parts: Method output and Global value output. This is because method
1028 // output is pipelined with all of the rest of code generation stuff,
1029 // allowing machine code representations for methods to be free'd after the
1030 // method has been emitted.
1031 //
1032 PM.add(getMethodAsmPrinterPass(PM, Out));
1033 PM.add(new FreeMachineCodeForMethod()); // Free stuff no longer needed
Chris Lattnercf4525b2002-02-03 07:49:15 +00001034
Chris Lattner0feb3582002-02-03 23:41:51 +00001035 // Emit Module level assembly after all of the methods have been processed.
1036 PM.add(getModuleAsmPrinterPass(PM, Out));
Chris Lattnercf4525b2002-02-03 07:49:15 +00001037}