xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/PostRAHazardRecognizer.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
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"
35*480093f4SDimitry 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);
850b57cec5SDimitry Andric       for (unsigned i = 0; i != NumPreNoops; ++i) {
860b57cec5SDimitry Andric         HazardRec->EmitNoop();
870b57cec5SDimitry Andric         TII->insertNoop(MBB, MachineBasicBlock::iterator(MI));
880b57cec5SDimitry Andric         ++NumNoops;
890b57cec5SDimitry Andric       }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric       HazardRec->EmitInstruction(&MI);
920b57cec5SDimitry Andric       if (HazardRec->atIssueLimit()) {
930b57cec5SDimitry Andric         HazardRec->AdvanceCycle();
940b57cec5SDimitry Andric       }
950b57cec5SDimitry Andric     }
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric   return true;
980b57cec5SDimitry Andric }
99