1 //===-- SPUNopFiller.cpp - Add nops/lnops to align the pipelines ----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
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)
14 //
15 //===----------------------------------------------------------------------===//
16
17 #include "SPU.h"
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"
24
25 using namespace llvm;
26
27 namespace {
28 struct SPUNopFiller : public MachineFunctionPass {
29
30 TargetMachine &TM;
31 const TargetInstrInfo *TII;
32 const InstrItineraryData *IID;
33 bool isEvenPlace; // the instruction slot (mem address) at hand is even/odd
34
35 static char ID;
SPUNopFiller__anon861411560111::SPUNopFiller36 SPUNopFiller(TargetMachine &tm)
37 : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()),
38 IID(tm.getInstrItineraryData())
39 {
40 DEBUG( dbgs() << "********** SPU Nop filler **********\n" ; );
41 }
42
getPassName__anon861411560111::SPUNopFiller43 virtual const char *getPassName() const {
44 return "SPU nop/lnop Filler";
45 }
46
47 void runOnMachineBasicBlock(MachineBasicBlock &MBB);
48
runOnMachineFunction__anon861411560111::SPUNopFiller49 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();
52 FI != FE; ++FI)
53 runOnMachineBasicBlock(*FI);
54 return true; //never-ever do any more modifications, just print it!
55 }
56
57 typedef enum { none = 0, // no more instructions in this function / BB
58 pseudo = 1, // this does not get executed
59 even = 2,
60 odd = 3 } SPUOpPlace;
61 SPUOpPlace getOpPlacement( MachineInstr &instr );
62
63 };
64 char SPUNopFiller::ID = 0;
65
66 }
67
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.
72 void SPUNopFiller::
runOnMachineBasicBlock(MachineBasicBlock & MBB)73 runOnMachineBasicBlock(MachineBasicBlock &MBB)
74 {
75 assert( isEvenPlace && "basic block start from odd address");
76 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I)
77 {
78 SPUOpPlace this_optype, next_optype;
79 MachineBasicBlock::iterator J = I;
80 J++;
81
82 this_optype = getOpPlacement( *I );
83 next_optype = none;
84 while (J!=MBB.end()){
85 next_optype = getOpPlacement( *J );
86 ++J;
87 if (next_optype != pseudo )
88 break;
89 }
90
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: "; );
95 DEBUG( I->dump(); );
96 BuildMI(MBB, I, I->getDebugLoc(), TII->get(SPU::ENOP));
97 isEvenPlace=false;
98 }
99
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: "; );
104 DEBUG( I->dump(); );
105 BuildMI(MBB, I, I->getDebugLoc(), TII->get(SPU::LNOP));
106 isEvenPlace=true;
107 }
108
109 // now go to next mem slot
110 if( this_optype != pseudo )
111 isEvenPlace = !isEvenPlace;
112
113 }
114
115 // padd basicblock end
116 if( !isEvenPlace ){
117 MachineBasicBlock::iterator J = MBB.end();
118 J--;
119 if (getOpPlacement( *J ) == odd) {
120 DEBUG( dbgs() <<"Padding basic block with NOP\n"; );
121 BuildMI(MBB, J, J->getDebugLoc(), TII->get(SPU::ENOP));
122 }
123 else {
124 J++;
125 DEBUG( dbgs() <<"Padding basic block with LNOP\n"; );
126 BuildMI(MBB, J, DebugLoc(), TII->get(SPU::LNOP));
127 }
128 isEvenPlace=true;
129 }
130 }
131
createSPUNopFillerPass(SPUTargetMachine & tm)132 FunctionPass *llvm::createSPUNopFillerPass(SPUTargetMachine &tm) {
133 return new SPUNopFiller(tm);
134 }
135
136 // Figure out if 'instr' is executed in the even or odd pipeline
137 SPUNopFiller::SPUOpPlace
getOpPlacement(MachineInstr & instr)138 SPUNopFiller::getOpPlacement( MachineInstr &instr ) {
139 int sc = instr.getDesc().getSchedClass();
140 const InstrStage *stage = IID->beginStage(sc);
141 unsigned FUs = stage->getUnits();
142 SPUOpPlace retval;
143
144 switch( FUs ) {
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");
150 break;
151 };
152 return retval;
153 }
154