summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/CodeGen/Passes.h4
-rw-r--r--llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h11
-rw-r--r--llvm/include/llvm/InitializePasses.h1
-rw-r--r--llvm/include/llvm/Target/TargetInstrInfo.h7
-rw-r--r--llvm/lib/CodeGen/CMakeLists.txt1
-rw-r--r--llvm/lib/CodeGen/CodeGen.cpp1
-rw-r--r--llvm/lib/CodeGen/PostRAHazardRecognizer.cpp101
7 files changed, 126 insertions, 0 deletions
diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h
index 3b0957202b7..30630dcf644 100644
--- a/llvm/include/llvm/CodeGen/Passes.h
+++ b/llvm/include/llvm/CodeGen/Passes.h
@@ -498,6 +498,10 @@ namespace llvm {
/// register allocation.
extern char &ExpandPostRAPseudosID;
+ /// createPostRAHazardRecognizer - This pass runs the post-ra hazard
+ /// recognizer.
+ extern char &PostRAHazardRecognizerID;
+
/// createPostRAScheduler - This pass performs post register allocation
/// scheduling.
extern char &PostRASchedulerID;
diff --git a/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h
index 8a40e7212ff..214be2794ba 100644
--- a/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h
+++ b/llvm/include/llvm/CodeGen/ScheduleHazardRecognizer.h
@@ -17,6 +17,7 @@
namespace llvm {
+class MachineInstr;
class SUnit;
/// HazardRecognizer - This determines whether or not an instruction can be
@@ -70,6 +71,10 @@ public:
/// emitted, to advance the hazard state.
virtual void EmitInstruction(SUnit *) {}
+ /// This overload will be used when the hazard recognizer is being used
+ /// by a non-scheduling pass, which does not use SUnits.
+ virtual void EmitInstruction(MachineInstr *) {}
+
/// PreEmitNoops - This callback is invoked prior to emitting an instruction.
/// It should return the number of noops to emit prior to the provided
/// instruction.
@@ -79,6 +84,12 @@ public:
return 0;
}
+ /// This overload will be used when the hazard recognizer is being used
+ /// by a non-scheduling pass, which does not use SUnits.
+ virtual unsigned PreEmitNoops(MachineInstr *) {
+ return 0;
+ }
+
/// ShouldPreferAnother - This callback may be invoked if getHazardType
/// returns NoHazard. If, even though there is no hazard, it would be better to
/// schedule another available instruction, this callback should return true.
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index 9e394bf87cd..3988cc95480 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -243,6 +243,7 @@ void initializePostDomPrinterPass(PassRegistry&);
void initializePostDomViewerPass(PassRegistry&);
void initializePostDominatorTreeWrapperPassPass(PassRegistry&);
void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&);
+void initializePostRAHazardRecognizerPass(PassRegistry&);
void initializePostRASchedulerPass(PassRegistry&);
void initializePostMachineSchedulerPass(PassRegistry&);
void initializePrintFunctionPassWrapperPass(PassRegistry&);
diff --git a/llvm/include/llvm/Target/TargetInstrInfo.h b/llvm/include/llvm/Target/TargetInstrInfo.h
index 955b5cfc9c5..809525c2c2e 100644
--- a/llvm/include/llvm/Target/TargetInstrInfo.h
+++ b/llvm/include/llvm/Target/TargetInstrInfo.h
@@ -1100,6 +1100,13 @@ public:
CreateTargetPostRAHazardRecognizer(const InstrItineraryData*,
const ScheduleDAG *DAG) const;
+ /// Allocate and return a hazard recognizer to use for by non-scheduling
+ /// passes.
+ virtual ScheduleHazardRecognizer*
+ CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const {
+ return nullptr;
+ }
+
/// Provide a global flag for disabling the PreRA hazard recognizer that
/// targets may choose to honor.
bool usePreRAHazardRecognizer() const;
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index cb646d5717f..aab4088eb9a 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -85,6 +85,7 @@ add_llvm_library(LLVMCodeGen
PeepholeOptimizer.cpp
PHIElimination.cpp
PHIEliminationUtils.cpp
+ PostRAHazardRecognizer.cpp
PostRASchedulerList.cpp
ProcessImplicitDefs.cpp
PrologEpilogInserter.cpp
diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp
index 2613f5e4eda..ca3b36c17f1 100644
--- a/llvm/lib/CodeGen/CodeGen.cpp
+++ b/llvm/lib/CodeGen/CodeGen.cpp
@@ -61,6 +61,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializePHIEliminationPass(Registry);
initializePeepholeOptimizerPass(Registry);
initializePostMachineSchedulerPass(Registry);
+ initializePostRAHazardRecognizerPass(Registry);
initializePostRASchedulerPass(Registry);
initializeProcessImplicitDefsPass(Registry);
initializeRegisterCoalescerPass(Registry);
diff --git a/llvm/lib/CodeGen/PostRAHazardRecognizer.cpp b/llvm/lib/CodeGen/PostRAHazardRecognizer.cpp
new file mode 100644
index 00000000000..85c23a8cc47
--- /dev/null
+++ b/llvm/lib/CodeGen/PostRAHazardRecognizer.cpp
@@ -0,0 +1,101 @@
+//===----- PostRAHazardRecognizer.cpp - hazard recognizer -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This runs the hazard recognizer and emits noops when necessary. This
+/// gives targets a way to run the hazard recognizer without running one of
+/// the schedulers. Example use cases for this pass would be:
+///
+/// - Targets that need the hazard recognizer to be run at -O0.
+/// - Targets that want to guarantee that hazards at the beginning of
+/// scheduling regions are handled correctly. The post-RA scheduler is
+/// a top-down scheduler, but when there are multiple scheduling regions
+/// in a basic block, it visits the regions in bottom-up order. This
+/// makes it impossible for the scheduler to gauranttee it can correctly
+/// handle hazards at the beginning of scheduling regions.
+///
+/// This pass traverses all the instructions in a program in top-down order.
+/// In contrast to the instruction scheduling passes, this pass never resets
+/// the hazard recognizer to ensure it can correctly handles noop hazards at
+/// the begining of blocks.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "post-RA-hazard-rec"
+
+STATISTIC(NumNoops, "Number of noops inserted");
+
+namespace {
+ class PostRAHazardRecognizer : public MachineFunctionPass {
+ const TargetInstrInfo *TII;
+
+ public:
+ static char ID;
+ PostRAHazardRecognizer() : MachineFunctionPass(ID) {}
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesCFG();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ bool runOnMachineFunction(MachineFunction &Fn) override;
+
+ };
+ char PostRAHazardRecognizer::ID = 0;
+
+}
+
+char &llvm::PostRAHazardRecognizerID = PostRAHazardRecognizer::ID;
+
+INITIALIZE_PASS(PostRAHazardRecognizer, DEBUG_TYPE,
+ "Post RA hazard recognizer", false, false)
+
+bool PostRAHazardRecognizer::runOnMachineFunction(MachineFunction &Fn) {
+ const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo();
+ std::unique_ptr<ScheduleHazardRecognizer> HazardRec(
+ TII->CreateTargetPostRAHazardRecognizer(Fn));
+
+ // Return if the target has not implemented a hazard recognizer.
+ if (!HazardRec.get())
+ return false;
+
+ // Loop over all of the basic blocks
+ for (auto &MBB : Fn) {
+ // We do not call HazardRec->reset() here to make sure we are handling noop
+ // hazards at the start of basic blocks.
+ for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
+ I != E; ++I) {
+ MachineInstr *MI = I;
+ // If we need to emit noops prior to this instruction, then do so.
+ unsigned NumPreNoops = HazardRec->PreEmitNoops(MI);
+ for (unsigned i = 0; i != NumPreNoops; ++i) {
+ HazardRec->EmitNoop();
+ TII->insertNoop(MBB, I);
+ ++NumNoops;
+ }
+
+ HazardRec->EmitInstruction(MI);
+ if (HazardRec->atIssueLimit()) {
+ HazardRec->AdvanceCycle();
+ }
+ }
+ }
+ return true;
+}
OpenPOWER on IntegriCloud