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; 36 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 43 virtual const char *getPassName() const { 44 return "SPU nop/lnop Filler"; 45 } 46 47 void runOnMachineBasicBlock(MachineBasicBlock &MBB); 48 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(); 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:: 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 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 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