LLVM API Documentation
00001 //===-- DelaySlotFiller.cpp - MBlaze delay slot filler --------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // A pass that attempts to fill instructions with delay slots. If no 00011 // instructions can be moved into the delay slot then a NOP is placed there. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #define DEBUG_TYPE "delay-slot-filler" 00016 00017 #include "MBlaze.h" 00018 #include "MBlazeTargetMachine.h" 00019 #include "llvm/ADT/Statistic.h" 00020 #include "llvm/CodeGen/MachineFunctionPass.h" 00021 #include "llvm/CodeGen/MachineInstrBuilder.h" 00022 #include "llvm/Support/CommandLine.h" 00023 #include "llvm/Support/Debug.h" 00024 #include "llvm/Support/ErrorHandling.h" 00025 #include "llvm/Support/raw_ostream.h" 00026 #include "llvm/Target/TargetInstrInfo.h" 00027 00028 using namespace llvm; 00029 00030 STATISTIC(FilledSlots, "Number of delay slots filled"); 00031 00032 static cl::opt<bool> MBDisableDelaySlotFiller( 00033 "disable-mblaze-delay-filler", 00034 cl::init(false), 00035 cl::desc("Disable the MBlaze delay slot filter."), 00036 cl::Hidden); 00037 00038 namespace { 00039 struct Filler : public MachineFunctionPass { 00040 00041 TargetMachine &TM; 00042 const TargetInstrInfo *TII; 00043 00044 static char ID; 00045 Filler(TargetMachine &tm) 00046 : MachineFunctionPass(ID), TM(tm), TII(tm.getInstrInfo()) { } 00047 00048 virtual const char *getPassName() const { 00049 return "MBlaze Delay Slot Filler"; 00050 } 00051 00052 bool runOnMachineBasicBlock(MachineBasicBlock &MBB); 00053 bool runOnMachineFunction(MachineFunction &F) { 00054 bool Changed = false; 00055 for (MachineFunction::iterator FI = F.begin(), FE = F.end(); 00056 FI != FE; ++FI) 00057 Changed |= runOnMachineBasicBlock(*FI); 00058 return Changed; 00059 } 00060 00061 }; 00062 char Filler::ID = 0; 00063 } // end of anonymous namespace 00064 00065 static bool hasImmInstruction(MachineBasicBlock::iterator &candidate) { 00066 // Any instruction with an immediate mode operand greater than 00067 // 16-bits requires an implicit IMM instruction. 00068 unsigned numOper = candidate->getNumOperands(); 00069 for (unsigned op = 0; op < numOper; ++op) { 00070 MachineOperand &mop = candidate->getOperand(op); 00071 00072 // The operand requires more than 16-bits to represent. 00073 if (mop.isImm() && (mop.getImm() < -0x8000 || mop.getImm() > 0x7fff)) 00074 return true; 00075 00076 // We must assume that unknown immediate values require more than 00077 // 16-bits to represent. 00078 if (mop.isGlobal() || mop.isSymbol() || mop.isJTI() || mop.isCPI()) 00079 return true; 00080 00081 // FIXME: we could probably check to see if the FP value happens 00082 // to not need an IMM instruction. For now we just always 00083 // assume that FP values do. 00084 if (mop.isFPImm()) 00085 return true; 00086 } 00087 00088 return false; 00089 } 00090 00091 static unsigned getLastRealOperand(MachineBasicBlock::iterator &instr) { 00092 switch (instr->getOpcode()) { 00093 default: return instr->getNumOperands(); 00094 00095 // These instructions have a variable number of operands but the first two 00096 // are the "real" operands that we care about during hazard detection. 00097 case MBlaze::BRLID: 00098 case MBlaze::BRALID: 00099 case MBlaze::BRLD: 00100 case MBlaze::BRALD: 00101 return 2; 00102 } 00103 } 00104 00105 static bool delayHasHazard(MachineBasicBlock::iterator &candidate, 00106 MachineBasicBlock::iterator &slot) { 00107 // Hazard check 00108 MachineBasicBlock::iterator a = candidate; 00109 MachineBasicBlock::iterator b = slot; 00110 00111 // MBB layout:- 00112 // candidate := a0 = operation(a1, a2) 00113 // ...middle bit... 00114 // slot := b0 = operation(b1, b2) 00115 00116 // Possible hazards:-/ 00117 // 1. a1 or a2 was written during the middle bit 00118 // 2. a0 was read or written during the middle bit 00119 // 3. a0 is one or more of {b0, b1, b2} 00120 // 4. b0 is one or more of {a1, a2} 00121 // 5. a accesses memory, and the middle bit 00122 // contains a store operation. 00123 bool a_is_memory = candidate->mayLoad() || candidate->mayStore(); 00124 00125 // Determine the number of operands in the slot instruction and in the 00126 // candidate instruction. 00127 const unsigned aend = getLastRealOperand(a); 00128 const unsigned bend = getLastRealOperand(b); 00129 00130 // Check hazards type 1, 2 and 5 by scanning the middle bit 00131 MachineBasicBlock::iterator m = a; 00132 for (++m; m != b; ++m) { 00133 for (unsigned aop = 0; aop<aend; ++aop) { 00134 bool aop_is_reg = a->getOperand(aop).isReg(); 00135 if (!aop_is_reg) continue; 00136 00137 bool aop_is_def = a->getOperand(aop).isDef(); 00138 unsigned aop_reg = a->getOperand(aop).getReg(); 00139 00140 const unsigned mend = getLastRealOperand(m); 00141 for (unsigned mop = 0; mop<mend; ++mop) { 00142 bool mop_is_reg = m->getOperand(mop).isReg(); 00143 if (!mop_is_reg) continue; 00144 00145 bool mop_is_def = m->getOperand(mop).isDef(); 00146 unsigned mop_reg = m->getOperand(mop).getReg(); 00147 00148 if (aop_is_def && (mop_reg == aop_reg)) 00149 return true; // Hazard type 2, because aop = a0 00150 else if (mop_is_def && (mop_reg == aop_reg)) 00151 return true; // Hazard type 1, because aop in {a1, a2} 00152 } 00153 } 00154 00155 // Check hazard type 5 00156 if (a_is_memory && m->mayStore()) 00157 return true; 00158 } 00159 00160 // Check hazard type 3 & 4 00161 for (unsigned aop = 0; aop<aend; ++aop) { 00162 if (a->getOperand(aop).isReg()) { 00163 unsigned aop_reg = a->getOperand(aop).getReg(); 00164 00165 for (unsigned bop = 0; bop<bend; ++bop) { 00166 if (b->getOperand(bop).isReg() && !b->getOperand(bop).isImplicit()) { 00167 unsigned bop_reg = b->getOperand(bop).getReg(); 00168 if (aop_reg == bop_reg) 00169 return true; 00170 } 00171 } 00172 } 00173 } 00174 00175 return false; 00176 } 00177 00178 static bool isDelayFiller(MachineBasicBlock &MBB, 00179 MachineBasicBlock::iterator candidate) { 00180 if (candidate == MBB.begin()) 00181 return false; 00182 00183 --candidate; 00184 return (candidate->hasDelaySlot()); 00185 } 00186 00187 static bool hasUnknownSideEffects(MachineBasicBlock::iterator &I) { 00188 if (!I->hasUnmodeledSideEffects()) 00189 return false; 00190 00191 unsigned op = I->getOpcode(); 00192 if (op == MBlaze::ADDK || op == MBlaze::ADDIK || 00193 op == MBlaze::ADDC || op == MBlaze::ADDIC || 00194 op == MBlaze::ADDKC || op == MBlaze::ADDIKC || 00195 op == MBlaze::RSUBK || op == MBlaze::RSUBIK || 00196 op == MBlaze::RSUBC || op == MBlaze::RSUBIC || 00197 op == MBlaze::RSUBKC || op == MBlaze::RSUBIKC) 00198 return false; 00199 00200 return true; 00201 } 00202 00203 static MachineBasicBlock::iterator 00204 findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator slot) { 00205 MachineBasicBlock::iterator I = slot; 00206 while (true) { 00207 if (I == MBB.begin()) 00208 break; 00209 00210 --I; 00211 if (I->hasDelaySlot() || I->isBranch() || isDelayFiller(MBB,I) || 00212 I->isCall() || I->isReturn() || I->isBarrier() || 00213 hasUnknownSideEffects(I)) 00214 break; 00215 00216 if (hasImmInstruction(I) || delayHasHazard(I,slot)) 00217 continue; 00218 00219 return I; 00220 } 00221 00222 return MBB.end(); 00223 } 00224 00225 /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. 00226 /// Currently, we fill delay slots with NOPs. We assume there is only one 00227 /// delay slot per delayed instruction. 00228 bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { 00229 bool Changed = false; 00230 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) 00231 if (I->hasDelaySlot()) { 00232 MachineBasicBlock::iterator D = MBB.end(); 00233 MachineBasicBlock::iterator J = I; 00234 00235 if (!MBDisableDelaySlotFiller) 00236 D = findDelayInstr(MBB,I); 00237 00238 ++FilledSlots; 00239 Changed = true; 00240 00241 if (D == MBB.end()) 00242 BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(MBlaze::NOP)); 00243 else 00244 MBB.splice(++J, &MBB, D); 00245 } 00246 return Changed; 00247 } 00248 00249 /// createMBlazeDelaySlotFillerPass - Returns a pass that fills in delay 00250 /// slots in MBlaze MachineFunctions 00251 FunctionPass *llvm::createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &tm) { 00252 return new Filler(tm); 00253 } 00254