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