Index: include/llvm/CodeGen/CommandFlags.h =================================================================== --- include/llvm/CodeGen/CommandFlags.h +++ include/llvm/CodeGen/CommandFlags.h @@ -204,6 +204,10 @@ cl::value_desc("pass-name"), cl::init("")); +cl::opt + RunPass("run-pass", cl::desc("Run compiler only for one specific pass"), + cl::value_desc("pass-name"), cl::init("")); + cl::opt DataSections("data-sections", cl::desc("Emit data into separate sections"), cl::init(false)); Index: include/llvm/CodeGen/Passes.h =================================================================== --- include/llvm/CodeGen/Passes.h +++ include/llvm/CodeGen/Passes.h @@ -101,7 +101,7 @@ private: PassManagerBase *PM; - AnalysisID StartAfter; + AnalysisID StartBefore, StartAfter; AnalysisID StopAfter; bool Started; bool Stopped; @@ -142,16 +142,24 @@ CodeGenOpt::Level getOptLevel() const { return TM->getOptLevel(); } - /// setStartStopPasses - Set the StartAfter and StopAfter passes to allow - /// running only a portion of the normal code-gen pass sequence. If the - /// Start pass ID is zero, then compilation will begin at the normal point; - /// otherwise, clear the Started flag to indicate that passes should not be - /// added until the starting pass is seen. If the Stop pass ID is zero, - /// then compilation will continue to the end. - void setStartStopPasses(AnalysisID Start, AnalysisID Stop) { - StartAfter = Start; - StopAfter = Stop; - Started = (StartAfter == nullptr); + /// Set the StartAfter, StartBefore and StopAfter passes to allow running only + /// a portion of the normal code-gen pass sequence. + /// + /// If the StartAfter and StartBefore pass ID is zero, then compilation will + /// begin at the normal point; otherwise, clear the Started flag to indicate + /// that passes should not be added until the starting pass is seen. If the + /// Stop pass ID is zero, then compilation will continue to the end. + /// + /// This function expects that at least one of the StartAfter or the + /// StartBefore pass IDs is null. + void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter, + AnalysisID StopAfter) { + if (StartAfter) + assert(!StartBefore && "Start after and start before passes are given"); + this->StartBefore = StartBefore; + this->StartAfter = StartAfter; + this->StopAfter = StopAfter; + Started = (StartAfter == nullptr) && (StartBefore == nullptr); } void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); } Index: include/llvm/Target/TargetMachine.h =================================================================== --- include/llvm/Target/TargetMachine.h +++ include/llvm/Target/TargetMachine.h @@ -212,8 +212,8 @@ /// supported, or false on success. virtual bool addPassesToEmitFile( PassManagerBase &, raw_pwrite_stream &, CodeGenFileType, - bool /*DisableVerify*/ = true, AnalysisID /*StartAfter*/ = nullptr, - AnalysisID /*StopAfter*/ = nullptr, + bool /*DisableVerify*/ = true, AnalysisID /*StartBefore*/ = nullptr, + AnalysisID /*StartAfter*/ = nullptr, AnalysisID /*StopAfter*/ = nullptr, MachineFunctionInitializer * /*MFInitializer*/ = nullptr) { return true; } @@ -260,8 +260,8 @@ /// emitted. Typically this will involve several steps of code generation. bool addPassesToEmitFile( PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, - bool DisableVerify = true, AnalysisID StartAfter = nullptr, - AnalysisID StopAfter = nullptr, + bool DisableVerify = true, AnalysisID StartBefore = nullptr, + AnalysisID StartAfter = nullptr, AnalysisID StopAfter = nullptr, MachineFunctionInitializer *MFInitializer = nullptr) override; /// Add passes to the specified pass manager to get machine code emitted with Index: lib/CodeGen/LLVMTargetMachine.cpp =================================================================== --- lib/CodeGen/LLVMTargetMachine.cpp +++ lib/CodeGen/LLVMTargetMachine.cpp @@ -90,8 +90,8 @@ /// addPassesToX helper drives creation and initialization of TargetPassConfig. static MCContext * addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM, - bool DisableVerify, AnalysisID StartAfter, - AnalysisID StopAfter, + bool DisableVerify, AnalysisID StartBefore, + AnalysisID StartAfter, AnalysisID StopAfter, MachineFunctionInitializer *MFInitializer = nullptr) { // Add internal analysis passes from the target machine. @@ -100,7 +100,7 @@ // Targets may override createPassConfig to provide a target-specific // subclass. TargetPassConfig *PassConfig = TM->createPassConfig(PM); - PassConfig->setStartStopPasses(StartAfter, StopAfter); + PassConfig->setStartStopPasses(StartBefore, StartAfter, StopAfter); // Set PassConfig options provided by TargetMachine. PassConfig->setDisableVerify(DisableVerify); @@ -143,11 +143,12 @@ bool LLVMTargetMachine::addPassesToEmitFile( PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, - bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter, - MachineFunctionInitializer *MFInitializer) { + bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter, + AnalysisID StopAfter, MachineFunctionInitializer *MFInitializer) { // Add common CodeGen passes. - MCContext *Context = addPassesToGenerateCode( - this, PM, DisableVerify, StartAfter, StopAfter, MFInitializer); + MCContext *Context = + addPassesToGenerateCode(this, PM, DisableVerify, StartBefore, StartAfter, + StopAfter, MFInitializer); if (!Context) return true; @@ -231,7 +232,8 @@ raw_pwrite_stream &Out, bool DisableVerify) { // Add common CodeGen passes. - Ctx = addPassesToGenerateCode(this, PM, DisableVerify, nullptr, nullptr); + Ctx = addPassesToGenerateCode(this, PM, DisableVerify, nullptr, nullptr, + nullptr); if (!Ctx) return true; Index: lib/CodeGen/Passes.cpp =================================================================== --- lib/CodeGen/Passes.cpp +++ lib/CodeGen/Passes.cpp @@ -214,10 +214,10 @@ // Out of line constructor provides default values for pass options and // registers all common codegen passes. TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm) - : ImmutablePass(ID), PM(&pm), StartAfter(nullptr), StopAfter(nullptr), - Started(true), Stopped(false), AddingMachinePasses(false), TM(tm), - Impl(nullptr), Initialized(false), DisableVerify(false), - EnableTailMerge(true), EnableShrinkWrap(false) { + : ImmutablePass(ID), PM(&pm), StartBefore(nullptr), StartAfter(nullptr), + StopAfter(nullptr), Started(true), Stopped(false), + AddingMachinePasses(false), TM(tm), Impl(nullptr), Initialized(false), + DisableVerify(false), EnableTailMerge(true), EnableShrinkWrap(false) { Impl = new PassConfigImpl(); @@ -288,6 +288,8 @@ // and shouldn't reference it. AnalysisID PassID = P->getPassID(); + if (StartBefore == PassID) + Started = true; if (Started && !Stopped) { std::string Banner; // Construct banner message before PM->add() as that may delete the pass. Index: lib/Target/CppBackend/CPPBackend.cpp =================================================================== --- lib/Target/CppBackend/CPPBackend.cpp +++ lib/Target/CppBackend/CPPBackend.cpp @@ -2148,8 +2148,8 @@ bool CPPTargetMachine::addPassesToEmitFile( PassManagerBase &PM, raw_pwrite_stream &o, CodeGenFileType FileType, - bool DisableVerify, AnalysisID StartAfter, AnalysisID StopAfter, - MachineFunctionInitializer *MFInitializer) { + bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter, + AnalysisID StopAfter, MachineFunctionInitializer *MFInitializer) { if (FileType != TargetMachine::CGFT_AssemblyFile) return true; auto FOut = llvm::make_unique(o); Index: lib/Target/CppBackend/CPPTargetMachine.h =================================================================== --- lib/Target/CppBackend/CPPTargetMachine.h +++ lib/Target/CppBackend/CPPTargetMachine.h @@ -31,7 +31,8 @@ public: bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, bool DisableVerify, - AnalysisID StartAfter, AnalysisID StopAfter, + AnalysisID StartBefore, AnalysisID StartAfter, + AnalysisID StopAfter, MachineFunctionInitializer *MFInitializer) override; }; Index: test/CodeGen/Generic/run-pass.ll =================================================================== --- /dev/null +++ test/CodeGen/Generic/run-pass.ll @@ -0,0 +1,7 @@ +; RUN: llc < %s -debug-pass=Structure -run-pass=gc-lowering -o /dev/null 2>&1 | FileCheck %s + +; CHECK: -gc-lowering +; CHECK: FunctionPass Manager +; CHECK-NEXT: Lower Garbage Collection Instructions +; CHECK-NEXT: Machine Function Analysis +; CHECK-NEXT: MIR Printing Pass Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -333,29 +333,44 @@ OS = BOS.get(); } + AnalysisID StartBeforeID = nullptr; AnalysisID StartAfterID = nullptr; AnalysisID StopAfterID = nullptr; const PassRegistry *PR = PassRegistry::getPassRegistry(); - if (!StartAfter.empty()) { - const PassInfo *PI = PR->getPassInfo(StartAfter); - if (!PI) { - errs() << argv[0] << ": start-after pass is not registered.\n"; + if (!RunPass.empty()) { + if (!StartAfter.empty() || !StopAfter.empty()) { + errs() << argv[0] << ": start-after and/or stop-after passes are " + "redundant when run-pass is specified.\n"; return 1; } - StartAfterID = PI->getTypeInfo(); - } - if (!StopAfter.empty()) { - const PassInfo *PI = PR->getPassInfo(StopAfter); + const PassInfo *PI = PR->getPassInfo(RunPass); if (!PI) { - errs() << argv[0] << ": stop-after pass is not registered.\n"; + errs() << argv[0] << ": run-pass pass is not registered.\n"; return 1; } - StopAfterID = PI->getTypeInfo(); + StopAfterID = StartBeforeID = PI->getTypeInfo(); + } else { + if (!StartAfter.empty()) { + const PassInfo *PI = PR->getPassInfo(StartAfter); + if (!PI) { + errs() << argv[0] << ": start-after pass is not registered.\n"; + return 1; + } + StartAfterID = PI->getTypeInfo(); + } + if (!StopAfter.empty()) { + const PassInfo *PI = PR->getPassInfo(StopAfter); + if (!PI) { + errs() << argv[0] << ": stop-after pass is not registered.\n"; + return 1; + } + StopAfterID = PI->getTypeInfo(); + } } // Ask the target to add backend passes as necessary. - if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartAfterID, - StopAfterID, MIR.get())) { + if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartBeforeID, + StartAfterID, StopAfterID, MIR.get())) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1;