Index: include/llvm/Target/TargetMachine.h =================================================================== --- include/llvm/Target/TargetMachine.h +++ include/llvm/Target/TargetMachine.h @@ -95,6 +95,80 @@ const TargetOptions DefaultOptions; mutable TargetOptions Options; + /// Provide a generic way to handle the Start/Stop After/Before + /// parameters of addPassesToEmitFile. + /// @{ + /// Name of the commandline option to set the StartAfter parameter. + static const char *StartAfterOptName; + /// Name of the commandline option to set the StartAfter parameter. + static const char *StartBeforeOptName; + /// Name of the commandline option to set the StopAfter parameter. + static const char *StopAfterOptName; + /// Name of the commandline option to set the StopBefore parameter. + static const char *StopBeforeOptName; + + /// Enum of the different options available to control the pipeline + /// when emitting a file (addPassesToEmitFile). + enum PipelineControlOption { + StartAfter, + StartBefore, + StopAfter, + StopBefore, + LastPipelineControlOption = StopBefore + }; + + /// Helper method to get the pass ID of the Start/Stop After/Before + /// passes from the generic options. + /// \p Kind defines which pass ID we look for. + /// + /// This uses getPassID with the value of the related option as + /// PassName. In other words, \see getPassID for the usage of + /// \p AbortIfNotRegistered. + static AnalysisID getPassIDForOption(PipelineControlOption Kind, + bool AbortIfNotRegistered = true); + + /// Helper method to get the pass ID of \p PassName. + /// This is a simple wrapper around getPassInfo. + static AnalysisID getPassID(StringRef PassName, + bool AbortIfNotRegistered = true); + + /// Helper method to get the pass ID of the StartAfter generic option. + /// \see getPassIDForOption. + static AnalysisID getStartAfterID(bool AbortIfNotRegistered = true) { + return getPassIDForOption(TargetMachine::StartAfter, AbortIfNotRegistered); + } + + /// Helper method to get the pass ID of the StartBefore generic option. + /// \see getPassIDForOption. + static AnalysisID getStartBeforeID(bool AbortIfNotRegistered = true) { + return getPassIDForOption(TargetMachine::StartBefore, AbortIfNotRegistered); + } + + /// Helper method to get the pass ID of the StopAfter generic option. + /// \see getPassIDForOption. + static AnalysisID getStopAfterID(bool AbortIfNotRegistered = true) { + return getPassIDForOption(TargetMachine::StopAfter, AbortIfNotRegistered); + } + + /// Helper method to get the pass ID of the StopBefore generic option. + /// \see getPassIDForOption. + static AnalysisID getStopBeforeID(bool AbortIfNotRegistered = true) { + return getPassIDForOption(TargetMachine::StopBefore, AbortIfNotRegistered); + } + + /// Helper method to get the PassInfo of \p PassName + /// \p AbortIfNotRegistered will abort the process if the name of + /// the pass specified with the related option hasn't been found. + /// This parameter has no effect if the option was not set. + /// + /// \pre The pass registry has been initialized. + /// + /// \return The PassInfo of \p PassName or nullptr if PassName is empty + /// or this pass does not exist. + static const PassInfo *getPassInfo(StringRef PassName, + bool AbortIfNotRegistered = true); + /// @} + TargetMachine(const TargetMachine &) = delete; void operator=(const TargetMachine &) = delete; virtual ~TargetMachine(); @@ -225,9 +299,11 @@ /// supported, or false on success. virtual bool addPassesToEmitFile( PassManagerBase &, raw_pwrite_stream &, CodeGenFileType, - bool /*DisableVerify*/ = true, AnalysisID /*StartBefore*/ = nullptr, - AnalysisID /*StartAfter*/ = nullptr, AnalysisID /*StopBefore*/ = nullptr, - AnalysisID /*StopAfter*/ = nullptr, + bool /*DisableVerify*/ = true, + AnalysisID StartBefore = getStartBeforeID(), + AnalysisID StartAfter = getStartAfterID(), + AnalysisID StopBefore = getStopBeforeID(), + AnalysisID StopAfter = getStopAfterID(), MachineFunctionInitializer * /*MFInitializer*/ = nullptr) { return true; } @@ -287,9 +363,10 @@ /// emitted. Typically this will involve several steps of code generation. bool addPassesToEmitFile( PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, - bool DisableVerify = true, AnalysisID StartBefore = nullptr, - AnalysisID StartAfter = nullptr, AnalysisID StopBefore = nullptr, - AnalysisID StopAfter = nullptr, + bool DisableVerify = true, AnalysisID StartBefore = getStartBeforeID(), + AnalysisID StartAfter = getStartAfterID(), + AnalysisID StopBefore = getStopBeforeID(), + AnalysisID StopAfter = getStopAfterID(), MachineFunctionInitializer *MFInitializer = nullptr) override; /// Add passes to the specified pass manager to get machine code emitted with Index: lib/Target/TargetMachine.cpp =================================================================== --- lib/Target/TargetMachine.cpp +++ lib/Target/TargetMachine.cpp @@ -31,6 +31,31 @@ #include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; +const char *TargetMachine::StartAfterOptName = "start-after"; +const char *TargetMachine::StartBeforeOptName = "start-before"; +const char *TargetMachine::StopAfterOptName = "stop-after"; +const char *TargetMachine::StopBeforeOptName = "stop-before"; + +static cl::opt + StartAfterOpt(StringRef(TargetMachine::StartAfterOptName), + cl::desc("Resume compilation after a specific pass"), + cl::value_desc("pass-name"), cl::init("")); + +static cl::opt + StartBeforeOpt(StringRef(TargetMachine::StartBeforeOptName), + cl::desc("Resume compilation before a specific pass"), + cl::value_desc("pass-name"), cl::init("")); + +static cl::opt + StopAfterOpt(StringRef(TargetMachine::StopAfterOptName), + cl::desc("Stop compilation after a specific pass"), + cl::value_desc("pass-name"), cl::init("")); + +static cl::opt + StopBeforeOpt(StringRef(TargetMachine::StopBeforeOptName), + cl::desc("Stop compilation before a specific pass"), + cl::value_desc("pass-name"), cl::init("")); + cl::opt EnableIPRA("enable-ipra", cl::init(false), cl::Hidden, cl::desc("Enable interprocedural register allocation " "to reduce load/store at procedure calls.")); @@ -56,6 +81,42 @@ delete STI; } +AnalysisID TargetMachine::getPassIDForOption(PipelineControlOption Kind, + bool AbortIfNotRegistered) { + static cl::opt *PassNames[] = {&StartAfterOpt, &StartBeforeOpt, + &StopAfterOpt, &StopBeforeOpt}; +#define CHECK_OPT(OPTNAME) \ + assert(PassNames[TargetMachine::OPTNAME] == &OPTNAME##Opt && \ + "Static array is messed up for " #OPTNAME); + CHECK_OPT(StartAfter); + CHECK_OPT(StartBefore); + CHECK_OPT(StopAfter); + CHECK_OPT(StopBefore); + static_assert(LastPipelineControlOption == 3, + "The check before needs to be updated"); + return getPassID(*PassNames[Kind], AbortIfNotRegistered); +} + +const PassInfo *TargetMachine::getPassInfo(StringRef PassName, + bool AbortIfNotRegistered) { + if (PassName.empty()) + return nullptr; + + const PassRegistry &PR = *PassRegistry::getPassRegistry(); + const PassInfo *PI = PR.getPassInfo(PassName); + if (!PI && AbortIfNotRegistered) { + errs() << "\"" << PassName << "\" pass is not registered.\n"; + exit(1); + } + return PI; +} + +AnalysisID TargetMachine::getPassID(StringRef PassName, + bool AbortIfNotRegistered) { + const PassInfo *PI = getPassInfo(PassName, AbortIfNotRegistered); + return PI ? PI->getTypeInfo() : nullptr; +} + bool TargetMachine::isPositionIndependent() const { return getRelocationModel() == Reloc::PIC_; } Index: test/CodeGen/Generic/llc-start-stop.ll =================================================================== --- test/CodeGen/Generic/llc-start-stop.ll +++ test/CodeGen/Generic/llc-start-stop.ll @@ -24,10 +24,10 @@ ; 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 -; 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. +; NONEXISTENT-START-BEFORE: "nonexistent" pass is not registered. +; NONEXISTENT-STOP-BEFORE: "nonexistent" pass is not registered. +; NONEXISTENT-START-AFTER: "nonexistent" pass is not registered. +; NONEXISTENT-STOP-AFTER: "nonexistent" pass is not registered. ; RUN: not llc < %s -start-before=loop-reduce -start-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=DOUBLE-START ; RUN: not llc < %s -stop-before=loop-reduce -stop-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=DOUBLE-STOP Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -118,22 +118,6 @@ 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("")); - static cl::list IncludeDirs("I", cl::desc("include search path")); static cl::opt PassRemarksWithHotness( @@ -338,15 +322,12 @@ static bool addPass(PassManagerBase &PM, const char *argv0, StringRef PassName, TargetPassConfig &TPC) { - if (PassName == "none") + if (PassName.empty() || PassName == "none") return false; - const PassRegistry *PR = PassRegistry::getPassRegistry(); - const PassInfo *PI = PR->getPassInfo(PassName); - if (!PI) { - errs() << argv0 << ": run-pass " << PassName << " is not registered.\n"; - return true; - } + const PassInfo *PI = + TargetMachine::getPassInfo(PassName, /*AbortIfNotRegistered=*/true); + assert(PI && "We should have aborted in the previous call in that case"); Pass *P; if (PI->getTargetMachineCtor()) @@ -364,20 +345,6 @@ 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; @@ -509,9 +476,13 @@ OS = BOS.get(); } + AnalysisID StartBeforeID = TargetMachine::getStartBeforeID(); + AnalysisID StartAfterID = TargetMachine::getStartAfterID(); + AnalysisID StopAfterID = TargetMachine::getStopAfterID(); + AnalysisID StopBeforeID = TargetMachine::getStopBeforeID(); + if (!RunPassNames->empty()) { - if (!StartAfter.empty() || !StopAfter.empty() || !StartBefore.empty() || - !StopBefore.empty()) { + if (StartAfterID || StopAfterID || StartBeforeID || StopBeforeID) { errs() << argv[0] << ": start-after and/or stop-after passes are " "redundant when run-pass is specified.\n"; return 1; @@ -534,11 +505,6 @@ } PM.add(createPrintMIRPass(*OS)); } else { - 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); if (StartBeforeID && StartAfterID) { errs() << argv[0] << ": -start-before and -start-after specified!\n";