1 /// - Targets that need the hazard recognizer to be run at -O0. 2 /// - Targets that want to guarantee that hazards at the beginning of 3 /// scheduling regions are handled correctly. The post-RA scheduler is 4 /// a top-down scheduler, but when there are multiple scheduling regions 5 /// in a basic block, it visits the regions in bottom-up order. This 6 /// makes it impossible for the scheduler to gauranttee it can correctly 7 /// handle hazards at the beginning of scheduling regions. 8 /// 9 /// This pass traverses all the instructions in a program in top-down order. 10 /// In contrast to the instruction scheduling passes, this pass never resets 11 /// the hazard recognizer to ensure it can correctly handles noop hazards at 12 /// the beginning of blocks. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/ADT/Statistic.h" 17 #include "llvm/CodeGen/MachineFunctionPass.h" 18 #include "llvm/CodeGen/Passes.h" 19 #include "llvm/CodeGen/ScheduleHazardRecognizer.h" 20 #include "llvm/CodeGen/TargetInstrInfo.h" 21 #include "llvm/CodeGen/TargetSubtargetInfo.h" 22 #include "llvm/InitializePasses.h" 23 #include "llvm/Support/Debug.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/raw_ostream.h" 26 using namespace llvm; 27 28 #define DEBUG_TYPE "post-RA-hazard-rec" 29 30 STATISTIC(NumNoops, "Number of noops inserted"); 31 32 namespace { 33 class PostRAHazardRecognizer : public MachineFunctionPass { 34 35 public: 36 static char ID; 37 PostRAHazardRecognizer() : MachineFunctionPass(ID) {} 38 39 void getAnalysisUsage(AnalysisUsage &AU) const override { 40 AU.setPreservesCFG(); 41 MachineFunctionPass::getAnalysisUsage(AU); 42 } 43 44 bool runOnMachineFunction(MachineFunction &Fn) override; 45 46 }; 47 char PostRAHazardRecognizer::ID = 0; 48 49 } 50 51 char &llvm::PostRAHazardRecognizerID = PostRAHazardRecognizer::ID; 52 53 INITIALIZE_PASS(PostRAHazardRecognizer, DEBUG_TYPE, 54 "Post RA hazard recognizer", false, false) 55 56 bool PostRAHazardRecognizer::runOnMachineFunction(MachineFunction &Fn) { 57 const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo(); 58 std::unique_ptr<ScheduleHazardRecognizer> HazardRec( 59 TII->CreateTargetPostRAHazardRecognizer(Fn)); 60 61 // Return if the target has not implemented a hazard recognizer. 62 if (!HazardRec.get()) 63 return false; 64 65 // Loop over all of the basic blocks 66 for (auto &MBB : Fn) { 67 // We do not call HazardRec->reset() here to make sure we are handling noop 68 // hazards at the start of basic blocks. 69 for (MachineInstr &MI : MBB) { 70 // If we need to emit noops prior to this instruction, then do so. 71 unsigned NumPreNoops = HazardRec->PreEmitNoops(&MI); 72 for (unsigned i = 0; i != NumPreNoops; ++i) { 73 HazardRec->EmitNoop(); 74 TII->insertNoop(MBB, MachineBasicBlock::iterator(MI)); 75 ++NumNoops; 76 } 77 78 HazardRec->EmitInstruction(&MI); 79 if (HazardRec->atIssueLimit()) { 80 HazardRec->AdvanceCycle(); 81 } 82 } 83 } 84 return true; 85 } 86