Index: llvm/trunk/include/llvm/CodeGen/Passes.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/Passes.h +++ llvm/trunk/include/llvm/CodeGen/Passes.h @@ -498,6 +498,10 @@ /// 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; Index: llvm/trunk/include/llvm/CodeGen/ScheduleHazardRecognizer.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ llvm/trunk/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 @@ /// 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 @@ 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. Index: llvm/trunk/include/llvm/InitializePasses.h =================================================================== --- llvm/trunk/include/llvm/InitializePasses.h +++ llvm/trunk/include/llvm/InitializePasses.h @@ -243,6 +243,7 @@ void initializePostDomViewerPass(PassRegistry&); void initializePostDominatorTreeWrapperPassPass(PassRegistry&); void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&); +void initializePostRAHazardRecognizerPass(PassRegistry&); void initializePostRASchedulerPass(PassRegistry&); void initializePostMachineSchedulerPass(PassRegistry&); void initializePrintFunctionPassWrapperPass(PassRegistry&); Index: llvm/trunk/include/llvm/Target/TargetInstrInfo.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetInstrInfo.h +++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h @@ -1100,6 +1100,13 @@ 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; Index: llvm/trunk/lib/CodeGen/CMakeLists.txt =================================================================== --- llvm/trunk/lib/CodeGen/CMakeLists.txt +++ llvm/trunk/lib/CodeGen/CMakeLists.txt @@ -85,6 +85,7 @@ PeepholeOptimizer.cpp PHIElimination.cpp PHIEliminationUtils.cpp + PostRAHazardRecognizer.cpp PostRASchedulerList.cpp ProcessImplicitDefs.cpp PrologEpilogInserter.cpp Index: llvm/trunk/lib/CodeGen/CodeGen.cpp =================================================================== --- llvm/trunk/lib/CodeGen/CodeGen.cpp +++ llvm/trunk/lib/CodeGen/CodeGen.cpp @@ -61,6 +61,7 @@ initializePHIEliminationPass(Registry); initializePeepholeOptimizerPass(Registry); initializePostMachineSchedulerPass(Registry); + initializePostRAHazardRecognizerPass(Registry); initializePostRASchedulerPass(Registry); initializeProcessImplicitDefsPass(Registry); initializeRegisterCoalescerPass(Registry); Index: llvm/trunk/lib/CodeGen/PostRAHazardRecognizer.cpp =================================================================== --- llvm/trunk/lib/CodeGen/PostRAHazardRecognizer.cpp +++ llvm/trunk/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 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; +}