xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/PostRAHazardRecognizer.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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/ScheduleHazardRecognizer.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
34480093f4SDimitry Andric #include "llvm/InitializePasses.h"
35*81ad6265SDimitry Andric #include "llvm/Pass.h"
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric #define DEBUG_TYPE "post-RA-hazard-rec"
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric STATISTIC(NumNoops, "Number of noops inserted");
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric namespace {
430b57cec5SDimitry Andric   class PostRAHazardRecognizer : public MachineFunctionPass {
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   public:
460b57cec5SDimitry Andric     static char ID;
PostRAHazardRecognizer()470b57cec5SDimitry Andric     PostRAHazardRecognizer() : MachineFunctionPass(ID) {}
480b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const490b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
500b57cec5SDimitry Andric       AU.setPreservesCFG();
510b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
520b57cec5SDimitry Andric     }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &Fn) override;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   };
570b57cec5SDimitry Andric   char PostRAHazardRecognizer::ID = 0;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric char &llvm::PostRAHazardRecognizerID = PostRAHazardRecognizer::ID;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric INITIALIZE_PASS(PostRAHazardRecognizer, DEBUG_TYPE,
640b57cec5SDimitry Andric                 "Post RA hazard recognizer", false, false)
650b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & Fn)660b57cec5SDimitry Andric bool PostRAHazardRecognizer::runOnMachineFunction(MachineFunction &Fn) {
670b57cec5SDimitry Andric   const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo();
680b57cec5SDimitry Andric   std::unique_ptr<ScheduleHazardRecognizer> HazardRec(
690b57cec5SDimitry Andric       TII->CreateTargetPostRAHazardRecognizer(Fn));
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   // Return if the target has not implemented a hazard recognizer.
72*81ad6265SDimitry Andric   if (!HazardRec)
730b57cec5SDimitry Andric     return false;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   // Loop over all of the basic blocks
76*81ad6265SDimitry Andric   bool Changed = false;
770b57cec5SDimitry Andric   for (auto &MBB : Fn) {
780b57cec5SDimitry Andric     // We do not call HazardRec->reset() here to make sure we are handling noop
790b57cec5SDimitry Andric     // hazards at the start of basic blocks.
800b57cec5SDimitry Andric     for (MachineInstr &MI : MBB) {
810b57cec5SDimitry Andric       // If we need to emit noops prior to this instruction, then do so.
820b57cec5SDimitry Andric       unsigned NumPreNoops = HazardRec->PreEmitNoops(&MI);
83e8d8bef9SDimitry Andric       HazardRec->EmitNoops(NumPreNoops);
84e8d8bef9SDimitry Andric       TII->insertNoops(MBB, MachineBasicBlock::iterator(MI), NumPreNoops);
85e8d8bef9SDimitry Andric       NumNoops += NumPreNoops;
86*81ad6265SDimitry Andric       if (NumPreNoops)
87*81ad6265SDimitry Andric         Changed = true;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric       HazardRec->EmitInstruction(&MI);
900b57cec5SDimitry Andric       if (HazardRec->atIssueLimit()) {
910b57cec5SDimitry Andric         HazardRec->AdvanceCycle();
920b57cec5SDimitry Andric       }
930b57cec5SDimitry Andric     }
940b57cec5SDimitry Andric   }
95*81ad6265SDimitry Andric   return Changed;
960b57cec5SDimitry Andric }
97