Index: include/llvm/CodeGen/TargetPassConfig.h =================================================================== --- include/llvm/CodeGen/TargetPassConfig.h +++ include/llvm/CodeGen/TargetPassConfig.h @@ -94,8 +94,10 @@ private: PassManagerBase *PM; - AnalysisID StartBefore, StartAfter; - AnalysisID StopAfter; + AnalysisID StartBefore = nullptr; + AnalysisID StartAfter = nullptr; + AnalysisID StopBefore = nullptr; + AnalysisID StopAfter = nullptr; bool Started; bool Stopped; bool AddingMachinePasses; @@ -143,11 +145,14 @@ /// 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"); + AnalysisID StopBefore, AnalysisID StopAfter) { + assert(!(StartBefore && StartAfter) && + "Start after and start before passes are given"); + assert(!(StopBefore && StopAfter) && + "Stop after and stop before passed are given"); this->StartBefore = StartBefore; this->StartAfter = StartAfter; + this->StopBefore = StopBefore; this->StopAfter = StopAfter; Started = (StartAfter == nullptr) && (StartBefore == nullptr); } Index: include/llvm/Target/TargetMachine.h =================================================================== --- include/llvm/Target/TargetMachine.h +++ include/llvm/Target/TargetMachine.h @@ -241,7 +241,8 @@ virtual bool addPassesToEmitFile( PassManagerBase &, raw_pwrite_stream &, CodeGenFileType, bool /*DisableVerify*/ = true, AnalysisID /*StartBefore*/ = nullptr, - AnalysisID /*StartAfter*/ = nullptr, AnalysisID /*StopAfter*/ = nullptr, + AnalysisID /*StartAfter*/ = nullptr, AnalysisID /*StopBefore*/ = nullptr, + AnalysisID /*StopAfter*/ = nullptr, MachineFunctionInitializer * /*MFInitializer*/ = nullptr) { return true; } @@ -302,7 +303,8 @@ bool addPassesToEmitFile( PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, bool DisableVerify = true, AnalysisID StartBefore = nullptr, - AnalysisID StartAfter = nullptr, AnalysisID StopAfter = nullptr, + AnalysisID StartAfter = nullptr, AnalysisID StopBefore = 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 @@ -105,7 +105,8 @@ static MCContext * addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM, bool DisableVerify, AnalysisID StartBefore, - AnalysisID StartAfter, AnalysisID StopAfter, + AnalysisID StartAfter, AnalysisID StopBefore, + AnalysisID StopAfter, MachineFunctionInitializer *MFInitializer = nullptr) { // When in emulated TLS mode, add the LowerEmuTLS pass. @@ -120,7 +121,8 @@ // Targets may override createPassConfig to provide a target-specific // subclass. TargetPassConfig *PassConfig = TM->createPassConfig(PM); - PassConfig->setStartStopPasses(StartBefore, StartAfter, StopAfter); + PassConfig->setStartStopPasses(StartBefore, StartAfter, StopBefore, + StopAfter); // Set PassConfig options provided by TargetMachine. PassConfig->setDisableVerify(DisableVerify); @@ -181,15 +183,16 @@ bool LLVMTargetMachine::addPassesToEmitFile( PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, bool DisableVerify, AnalysisID StartBefore, AnalysisID StartAfter, - AnalysisID StopAfter, MachineFunctionInitializer *MFInitializer) { + AnalysisID StopBefore, AnalysisID StopAfter, + MachineFunctionInitializer *MFInitializer) { // Add common CodeGen passes. MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify, StartBefore, StartAfter, - StopAfter, MFInitializer); + StopBefore, StopAfter, MFInitializer); if (!Context) return true; - if (StopAfter) { + if (StopBefore || StopAfter) { PM.add(createPrintMIRPass(Out)); return false; } @@ -274,7 +277,7 @@ bool DisableVerify) { // Add common CodeGen passes. Ctx = addPassesToGenerateCode(this, PM, DisableVerify, nullptr, nullptr, - nullptr); + nullptr, nullptr); if (!Ctx) return true; Index: lib/CodeGen/TargetPassConfig.cpp =================================================================== --- lib/CodeGen/TargetPassConfig.cpp +++ lib/CodeGen/TargetPassConfig.cpp @@ -252,8 +252,7 @@ // 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), StartBefore(nullptr), StartAfter(nullptr), - StopAfter(nullptr), Started(true), Stopped(false), + : ImmutablePass(ID), PM(&pm), Started(true), Stopped(false), AddingMachinePasses(false), TM(tm), Impl(nullptr), Initialized(false), DisableVerify(false), EnableTailMerge(true) { @@ -347,6 +346,8 @@ if (StartBefore == PassID) Started = true; + if (StopBefore == PassID) + Stopped = true; if (Started && !Stopped) { std::string Banner; // Construct banner message before PM->add() as that may delete the pass. Index: test/CodeGen/Generic/llc-start-stop.ll =================================================================== --- /dev/null +++ test/CodeGen/Generic/llc-start-stop.ll @@ -0,0 +1,31 @@ +; RUN: llc < %s -debug-pass=Structure -stop-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=STOP-AFTER +; RUN: llc < %s -debug-pass=Structure -stop-before=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=STOP-BEFORE +; RUN: llc < %s -debug-pass=Structure -start-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=START-AFTER +; RUN: llc < %s -debug-pass=Structure -start-before=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=START-BEFORE +; RUN: not llc < %s -start-before=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-START-BEFORE +; RUN: not llc < %s -stop-before=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-STOP-BEFORE +; RUN: not llc < %s -start-after=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-START-AFTER +; RUN: not llc < %s -stop-after=nonexistent -o /dev/null 2>&1 | FileCheck %s -check-prefix=NONEXISTENT-STOP-AFTER + +; STOP-AFTER: -loop-reduce +; STOP-AFTER: Dominator Tree Construction +; STOP-AFTER: Loop Strength Reduction +; STOP-AFTER-NEXT: MIR Printing Pass + +; STOP-BEFORE-NOT: -loop-reduce +; STOP-BEFORE: Dominator Tree Construction +; STOP-BEFORE-NOT: Loop Strength Reduction + +; START-AFTER: -machine-branch-prob -pre-isel-intrinsic-lowering +; START-AFTER: FunctionPass Manager +; START-AFTER-NEXT: Lower Garbage Collection Instructions + +; START-BEFORE: -machine-branch-prob -pre-isel-intrinsic-lowering +; START-BEFORE: FunctionPass Manager +; START-BEFORE: Loop Strength Reduction +; START-BEFORE-NEXT: Lower Garbage Collection Instructions + +; NONEXISTENT-START-BEFORE: start-before pass is not registered. +; NONEXISTENT-STOP-BEFORE: stop-before pass is not registered. +; NONEXISTENT-START-AFTER: start-after pass is not registered. +; NONEXISTENT-STOP-AFTER: stop-after pass is not registered. Index: test/CodeGen/Generic/stop-after.ll =================================================================== --- test/CodeGen/Generic/stop-after.ll +++ /dev/null @@ -1,10 +0,0 @@ -; RUN: llc < %s -debug-pass=Structure -stop-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=STOP -; RUN: llc < %s -debug-pass=Structure -start-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=START - -; STOP: -loop-reduce -; STOP: Loop Strength Reduction -; STOP-NEXT: MIR Printing Pass - -; START: -machine-branch-prob -pre-isel-intrinsic-lowering -; START: FunctionPass Manager -; START-NEXT: Lower Garbage Collection Instructions Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -118,10 +118,18 @@ cl::desc("Discard names from Value (other than GlobalValue)."), cl::init(false), cl::Hidden); +static cl::opt StopBefore("stop-before", + cl::desc("Stop compilation before a specific pass"), + cl::value_desc("pass-name"), cl::init("")); + static cl::opt StopAfter("stop-after", cl::desc("Stop compilation after a specific pass"), cl::value_desc("pass-name"), cl::init("")); +static cl::opt StartBefore("start-before", + cl::desc("Resume compilation before a specific pass"), + cl::value_desc("pass-name"), cl::init("")); + static cl::opt StartAfter("start-after", cl::desc("Resume compilation after a specific pass"), cl::value_desc("pass-name"), cl::init("")); @@ -303,6 +311,20 @@ return false; } +static AnalysisID getPassID(const char *argv0, const char *OptionName, + StringRef PassName) { + if (PassName.empty()) + return nullptr; + + const PassRegistry &PR = *PassRegistry::getPassRegistry(); + const PassInfo *PI = PR.getPassInfo(PassName); + if (!PI) { + errs() << argv0 << ": " << OptionName << " pass is not registered.\n"; + exit(1); + } + return PI->getTypeInfo(); +} + static int compileModule(char **argv, LLVMContext &Context) { // Load the module to be compiled... SMDiagnostic Err; @@ -433,12 +455,9 @@ OS = BOS.get(); } - AnalysisID StartBeforeID = nullptr; - AnalysisID StartAfterID = nullptr; - AnalysisID StopAfterID = nullptr; - const PassRegistry *PR = PassRegistry::getPassRegistry(); if (!RunPassNames->empty()) { - if (!StartAfter.empty() || !StopAfter.empty()) { + if (!StartAfter.empty() || !StopAfter.empty() || !StartBefore.empty() || + !StopBefore.empty()) { errs() << argv[0] << ": start-after and/or stop-after passes are " "redundant when run-pass is specified.\n"; return 1; @@ -461,27 +480,16 @@ } PM.add(createPrintMIRPass(*OS)); } 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(); - } + const char *argv0 = argv[0]; + AnalysisID StartBeforeID = getPassID(argv0, "start-before", StartBefore); + AnalysisID StartAfterID = getPassID(argv0, "start-after", StartAfter); + AnalysisID StopAfterID = getPassID(argv0, "stop-after", StopAfter); + AnalysisID StopBeforeID = getPassID(argv0, "stop-before", StopBefore); // Ask the target to add backend passes as necessary. if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, - StartBeforeID, StartAfterID, StopAfterID, - MIR.get())) { + StartBeforeID, StartAfterID, StopBeforeID, + StopAfterID, MIR.get())) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1;