1 //===-- SPUNopFiller.cpp - Add nops/lnops to align the pipelines---===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // The final pass just before assembly printing. This pass is the last
11 // checkpoint where nops and lnops are added to the instruction stream to
12 // satisfy the dual issue requirements. The actual dual issue scheduling is
13 // done (TODO: nowhere, currently)
15 //===----------------------------------------------------------------------===//
18 #include "SPUTargetMachine.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/Target/TargetInstrInfo.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/raw_ostream.h"
28 struct SPUNopFiller
: public MachineFunctionPass
{
31 const TargetInstrInfo
*TII
;
32 const InstrItineraryData
*IID
;
33 bool isEvenPlace
; // the instruction slot (mem address) at hand is even/odd
36 SPUNopFiller(TargetMachine
&tm
)
37 : MachineFunctionPass(ID
), TM(tm
), TII(tm
.getInstrInfo()),
38 IID(tm
.getInstrItineraryData())
40 DEBUG( dbgs() << "********** SPU Nop filler **********\n" ; );
43 virtual const char *getPassName() const {
44 return "SPU nop/lnop Filler";
47 void runOnMachineBasicBlock(MachineBasicBlock
&MBB
);
49 bool runOnMachineFunction(MachineFunction
&F
) {
50 isEvenPlace
= true; //all functions get an .align 3 directive at start
51 for (MachineFunction::iterator FI
= F
.begin(), FE
= F
.end();
53 runOnMachineBasicBlock(*FI
);
54 return true; //never-ever do any more modifications, just print it!
57 typedef enum { none
= 0, // no more instructions in this function / BB
58 pseudo
= 1, // this does not get executed
61 SPUOpPlace
getOpPlacement( MachineInstr
&instr
);
64 char SPUNopFiller::ID
= 0;
68 // Fill a BasicBlock to alignment.
69 // In the assebly we align the functions to 'even' adresses, but
70 // basic blocks have an implicit alignmnet. We hereby define
71 // basic blocks to have the same, even, alignment.
73 runOnMachineBasicBlock(MachineBasicBlock
&MBB
)
75 assert( isEvenPlace
&& "basic block start from odd address");
76 for (MachineBasicBlock::iterator I
= MBB
.begin(); I
!= MBB
.end(); ++I
)
78 SPUOpPlace this_optype
, next_optype
;
79 MachineBasicBlock::iterator J
= I
;
82 this_optype
= getOpPlacement( *I
);
85 next_optype
= getOpPlacement( *J
);
87 if (next_optype
!= pseudo
)
91 // padd: odd(wrong), even(wrong), ...
92 // to: nop(corr), odd(corr), even(corr)...
93 if( isEvenPlace
&& this_optype
== odd
&& next_optype
== even
) {
94 DEBUG( dbgs() <<"Adding NOP before: "; );
96 BuildMI(MBB
, I
, I
->getDebugLoc(), TII
->get(SPU::ENOP
));
100 // padd: even(wrong), odd(wrong), ...
101 // to: lnop(corr), even(corr), odd(corr)...
102 else if ( !isEvenPlace
&& this_optype
== even
&& next_optype
== odd
){
103 DEBUG( dbgs() <<"Adding LNOP before: "; );
105 BuildMI(MBB
, I
, I
->getDebugLoc(), TII
->get(SPU::LNOP
));
109 // now go to next mem slot
110 if( this_optype
!= pseudo
)
111 isEvenPlace
= !isEvenPlace
;
115 // padd basicblock end
117 MachineBasicBlock::iterator J
= MBB
.end();
119 if (getOpPlacement( *J
) == odd
) {
120 DEBUG( dbgs() <<"Padding basic block with NOP\n"; );
121 BuildMI(MBB
, J
, J
->getDebugLoc(), TII
->get(SPU::ENOP
));
125 DEBUG( dbgs() <<"Padding basic block with LNOP\n"; );
126 BuildMI(MBB
, J
, DebugLoc(), TII
->get(SPU::LNOP
));
132 FunctionPass
*llvm::createSPUNopFillerPass(SPUTargetMachine
&tm
) {
133 return new SPUNopFiller(tm
);
136 // Figure out if 'instr' is executed in the even or odd pipeline
137 SPUNopFiller::SPUOpPlace
138 SPUNopFiller::getOpPlacement( MachineInstr
&instr
) {
139 int sc
= instr
.getDesc().getSchedClass();
140 const InstrStage
*stage
= IID
->beginStage(sc
);
141 unsigned FUs
= stage
->getUnits();
145 case 0: retval
= pseudo
; break;
146 case 1: retval
= odd
; break;
147 case 2: retval
= even
; break;
148 default: retval
= pseudo
;
149 assert( false && "got unknown FuncUnit\n");