10b57cec5SDimitry Andric //===----- PostRAHazardRecognizer.cpp - hazard recognizer -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This runs the hazard recognizer and emits noops when necessary. This 110b57cec5SDimitry Andric /// gives targets a way to run the hazard recognizer without running one of 120b57cec5SDimitry Andric /// the schedulers. Example use cases for this pass would be: 130b57cec5SDimitry Andric /// 140b57cec5SDimitry Andric /// - Targets that need the hazard recognizer to be run at -O0. 150b57cec5SDimitry Andric /// - Targets that want to guarantee that hazards at the beginning of 160b57cec5SDimitry Andric /// scheduling regions are handled correctly. The post-RA scheduler is 170b57cec5SDimitry Andric /// a top-down scheduler, but when there are multiple scheduling regions 180b57cec5SDimitry Andric /// in a basic block, it visits the regions in bottom-up order. This 190b57cec5SDimitry Andric /// makes it impossible for the scheduler to gauranttee it can correctly 200b57cec5SDimitry Andric /// handle hazards at the beginning of scheduling regions. 210b57cec5SDimitry Andric /// 220b57cec5SDimitry Andric /// This pass traverses all the instructions in a program in top-down order. 230b57cec5SDimitry Andric /// In contrast to the instruction scheduling passes, this pass never resets 240b57cec5SDimitry Andric /// the hazard recognizer to ensure it can correctly handles noop hazards at 250b57cec5SDimitry Andric /// the beginning of blocks. 260b57cec5SDimitry Andric // 270b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleHazardRecognizer.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 35480093f4SDimitry Andric #include "llvm/InitializePasses.h" 360b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 370b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 380b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 390b57cec5SDimitry Andric using namespace llvm; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric #define DEBUG_TYPE "post-RA-hazard-rec" 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric STATISTIC(NumNoops, "Number of noops inserted"); 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric namespace { 460b57cec5SDimitry Andric class PostRAHazardRecognizer : public MachineFunctionPass { 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric public: 490b57cec5SDimitry Andric static char ID; 500b57cec5SDimitry Andric PostRAHazardRecognizer() : MachineFunctionPass(ID) {} 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 530b57cec5SDimitry Andric AU.setPreservesCFG(); 540b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric }; 600b57cec5SDimitry Andric char PostRAHazardRecognizer::ID = 0; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric char &llvm::PostRAHazardRecognizerID = PostRAHazardRecognizer::ID; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric INITIALIZE_PASS(PostRAHazardRecognizer, DEBUG_TYPE, 670b57cec5SDimitry Andric "Post RA hazard recognizer", false, false) 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric bool PostRAHazardRecognizer::runOnMachineFunction(MachineFunction &Fn) { 700b57cec5SDimitry Andric const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo(); 710b57cec5SDimitry Andric std::unique_ptr<ScheduleHazardRecognizer> HazardRec( 720b57cec5SDimitry Andric TII->CreateTargetPostRAHazardRecognizer(Fn)); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Return if the target has not implemented a hazard recognizer. 750b57cec5SDimitry Andric if (!HazardRec.get()) 760b57cec5SDimitry Andric return false; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // Loop over all of the basic blocks 790b57cec5SDimitry Andric for (auto &MBB : Fn) { 800b57cec5SDimitry Andric // We do not call HazardRec->reset() here to make sure we are handling noop 810b57cec5SDimitry Andric // hazards at the start of basic blocks. 820b57cec5SDimitry Andric for (MachineInstr &MI : MBB) { 830b57cec5SDimitry Andric // If we need to emit noops prior to this instruction, then do so. 840b57cec5SDimitry Andric unsigned NumPreNoops = HazardRec->PreEmitNoops(&MI); 85*e8d8bef9SDimitry Andric HazardRec->EmitNoops(NumPreNoops); 86*e8d8bef9SDimitry Andric TII->insertNoops(MBB, MachineBasicBlock::iterator(MI), NumPreNoops); 87*e8d8bef9SDimitry Andric NumNoops += NumPreNoops; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric HazardRec->EmitInstruction(&MI); 900b57cec5SDimitry Andric if (HazardRec->atIssueLimit()) { 910b57cec5SDimitry Andric HazardRec->AdvanceCycle(); 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric return true; 960b57cec5SDimitry Andric } 97