diff --git a/include/llvm/PassManager.h b/include/llvm/PassManager.h index b6a8186a4e8..044dc3320ba 100644 --- a/include/llvm/PassManager.h +++ b/include/llvm/PassManager.h @@ -28,6 +28,11 @@ class Module; class PassManagerImpl; class FunctionPassManagerImpl; +/// Called by tools to initialize globals and register options at a particular +/// point (before command line parsing). If this is not called, then PassManager +/// globals are lazily initialized at first use. +void initializePassManager(); + /// PassManagerBase - An abstract interface to allow code to add passes to /// a pass manager without having to hard-code what kind of pass manager /// it is. diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 95c516a2511..749ae601461 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -40,6 +40,7 @@ using namespace llvm; void llvm::initializeCore(PassRegistry &Registry) { + initializePassManager(); initializeDominatorTreePass(Registry); initializePrintModulePassPass(Registry); initializePrintFunctionPassPass(Registry); diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp index 8d2e2ca89ba..99933a89b00 100644 --- a/lib/IR/PassManager.cpp +++ b/lib/IR/PassManager.cpp @@ -45,65 +45,94 @@ enum PassDebugLevel { Disabled, Arguments, Structure, Executions, Details }; -static cl::opt -PassDebugging("debug-pass", cl::Hidden, +bool TimePassesIsEnabled = false; + +/// Encapsulate PassManager debug options. These are convenient options that +/// should be available to any LLVM-based tool. They exist purely as +/// command-line debug options, therefore don't need to be local to an LLVM +/// context or captured by a formal API. In all respects they are handled like +/// global variables, but being defined in the LLVMCore library cannot have +/// static initializers and must be destroyed only at llvm_shutdown. +struct PassDebugOpts { + cl::opt PassDebugging; + + typedef llvm::cl::list + PassOptionList; + + // Print IR out before/after specified passes. + PassOptionList PrintBefore; + + PassOptionList PrintAfter; + + cl::opt PrintBeforeAll; + cl::opt PrintAfterAll; + + cl::opt EnableTiming; + + PassDebugOpts(): + PassDebugging("debug-pass", cl::Hidden, cl::desc("Print PassManager debugging information"), cl::values( - clEnumVal(Disabled , "disable debug output"), - clEnumVal(Arguments , "print pass arguments to pass to 'opt'"), - clEnumVal(Structure , "print pass structure before run()"), - clEnumVal(Executions, "print pass name before it is executed"), - clEnumVal(Details , "print pass details when it is executed"), - clEnumValEnd)); + clEnumVal(Disabled , "disable debug output"), + clEnumVal(Arguments, + "print pass arguments to pass to 'opt'"), + clEnumVal(Structure, "print pass structure before run()"), + clEnumVal(Executions, + "print pass name before it is executed"), + clEnumVal(Details, + "print pass details when it is executed"), + clEnumValEnd)), + PrintBefore("print-before", + llvm::cl::desc("Print IR before specified passes"), + cl::Hidden), + PrintAfter("print-after", + llvm::cl::desc("Print IR after specified passes"), + cl::Hidden), + PrintBeforeAll("print-before-all", + llvm::cl::desc("Print IR before each pass"), + cl::init(false)), + PrintAfterAll("print-after-all", + llvm::cl::desc("Print IR after each pass"), + cl::init(false)), + EnableTiming("time-passes", cl::location(TimePassesIsEnabled), + cl::desc( + "Time each pass, printing elapsed time for each on exit")) + {} -typedef llvm::cl::list -PassOptionList; - -// Print IR out before/after specified passes. -static PassOptionList -PrintBefore("print-before", - llvm::cl::desc("Print IR before specified passes"), - cl::Hidden); - -static PassOptionList -PrintAfter("print-after", - llvm::cl::desc("Print IR after specified passes"), - cl::Hidden); - -static cl::opt -PrintBeforeAll("print-before-all", - llvm::cl::desc("Print IR before each pass"), - cl::init(false)); -static cl::opt -PrintAfterAll("print-after-all", - llvm::cl::desc("Print IR after each pass"), - cl::init(false)); - -/// This is a helper to determine whether to print IR before or -/// after a pass. - -static bool ShouldPrintBeforeOrAfterPass(const PassInfo *PI, - PassOptionList &PassesToPrint) { - for (unsigned i = 0, ie = PassesToPrint.size(); i < ie; ++i) { - const llvm::PassInfo *PassInf = PassesToPrint[i]; - if (PassInf) - if (PassInf->getPassArgument() == PI->getPassArgument()) { - return true; - } + /// This is a helper to determine whether to print IR before or + /// after a pass. + bool ShouldPrintBeforeOrAfterPass(const PassInfo *PI, + PassOptionList &PassesToPrint) { + for (unsigned i = 0, ie = PassesToPrint.size(); i < ie; ++i) { + const llvm::PassInfo *PassInf = PassesToPrint[i]; + if (PassInf) + if (PassInf->getPassArgument() == PI->getPassArgument()) { + return true; + } + } + return false; } - return false; -} -/// This is a utility to check whether a pass should have IR dumped -/// before it. -static bool ShouldPrintBeforePass(const PassInfo *PI) { - return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore); -} + /// This is a utility to check whether a pass should have IR dumped + /// before it. + bool ShouldPrintBeforePass(const PassInfo *PI) { + return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore); + } -/// This is a utility to check whether a pass should have IR dumped -/// after it. -static bool ShouldPrintAfterPass(const PassInfo *PI) { - return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter); + /// This is a utility to check whether a pass should have IR dumped + /// after it. + bool ShouldPrintAfterPass(const PassInfo *PI) { + return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter); + } +}; + +static ManagedStatic GlobalPassDebugOpts; + +/// This is called by tools to force registration of debugging options and +/// ensure they appear in the tool's -help usage. +void initializePassManager() { + // Force instantiation of PassDebugOpts. + *GlobalPassDebugOpts; } } // End of llvm namespace @@ -111,12 +140,9 @@ static bool ShouldPrintAfterPass(const PassInfo *PI) { /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions /// or higher is specified. bool PMDataManager::isPassDebuggingExecutionsOrMore() const { - return PassDebugging >= Executions; + return GlobalPassDebugOpts->PassDebugging >= Executions; } - - - void PassManagerPrettyStackEntry::print(raw_ostream &OS) const { if (V == 0 && M == 0) OS << "Releasing pass '"; @@ -668,7 +694,8 @@ void PMTopLevelManager::schedulePass(Pass *P) { return; } - if (PI && !PI->isAnalysis() && ShouldPrintBeforePass(PI)) { + if (PI && !PI->isAnalysis() && + GlobalPassDebugOpts->ShouldPrintBeforePass(PI)) { Pass *PP = P->createPrinterPass( dbgs(), std::string("*** IR Dump Before ") + P->getPassName() + " ***"); PP->assignPassManager(activeStack, getTopLevelPassManagerType()); @@ -677,7 +704,8 @@ void PMTopLevelManager::schedulePass(Pass *P) { // Add the requested pass to the best available pass manager. P->assignPassManager(activeStack, getTopLevelPassManagerType()); - if (PI && !PI->isAnalysis() && ShouldPrintAfterPass(PI)) { + if (PI && !PI->isAnalysis() && + GlobalPassDebugOpts->ShouldPrintAfterPass(PI)) { Pass *PP = P->createPrinterPass( dbgs(), std::string("*** IR Dump After ") + P->getPassName() + " ***"); PP->assignPassManager(activeStack, getTopLevelPassManagerType()); @@ -729,7 +757,7 @@ Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) { // Print passes managed by this top level manager. void PMTopLevelManager::dumpPasses() const { - if (PassDebugging < Structure) + if (GlobalPassDebugOpts->PassDebugging < Structure) return; // Print out the immutable passes @@ -748,7 +776,7 @@ void PMTopLevelManager::dumpPasses() const { void PMTopLevelManager::dumpArguments() const { - if (PassDebugging < Arguments) + if (GlobalPassDebugOpts->PassDebugging < Arguments) return; dbgs() << "Pass Arguments: "; @@ -881,7 +909,7 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) { std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == PreservedSet.end()) { // Remove this analysis - if (PassDebugging >= Details) { + if (GlobalPassDebugOpts->PassDebugging >= Details) { Pass *S = Info->second; dbgs() << " -- '" << P->getPassName() << "' is not preserving '"; dbgs() << S->getPassName() << "'\n"; @@ -905,7 +933,7 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) { std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == PreservedSet.end()) { // Remove this analysis - if (PassDebugging >= Details) { + if (GlobalPassDebugOpts->PassDebugging >= Details) { Pass *S = Info->second; dbgs() << " -- '" << P->getPassName() << "' is not preserving '"; dbgs() << S->getPassName() << "'\n"; @@ -928,7 +956,7 @@ void PMDataManager::removeDeadPasses(Pass *P, StringRef Msg, TPM->collectLastUses(DeadPasses, P); - if (PassDebugging >= Details && !DeadPasses.empty()) { + if (GlobalPassDebugOpts->PassDebugging >= Details && !DeadPasses.empty()) { dbgs() << " -*- '" << P->getPassName(); dbgs() << "' is the last user of following pass instances."; dbgs() << " Free these instances\n"; @@ -1146,7 +1174,7 @@ void PMDataManager::dumpPassArguments() const { void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1, enum PassDebuggingString S2, StringRef Msg) { - if (PassDebugging < Executions) + if (GlobalPassDebugOpts->PassDebugging < Executions) return; dbgs() << (void*)this << std::string(getDepth()*2+1, ' '); switch (S1) { @@ -1187,7 +1215,7 @@ void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1, } void PMDataManager::dumpRequiredSet(const Pass *P) const { - if (PassDebugging < Details) + if (GlobalPassDebugOpts->PassDebugging < Details) return; AnalysisUsage analysisUsage; @@ -1196,7 +1224,7 @@ void PMDataManager::dumpRequiredSet(const Pass *P) const { } void PMDataManager::dumpPreservedSet(const Pass *P) const { - if (PassDebugging < Details) + if (GlobalPassDebugOpts->PassDebugging < Details) return; AnalysisUsage analysisUsage; @@ -1206,7 +1234,7 @@ void PMDataManager::dumpPreservedSet(const Pass *P) const { void PMDataManager::dumpAnalysisUsage(StringRef Msg, const Pass *P, const AnalysisUsage::VectorType &Set) const { - assert(PassDebugging >= Details); + assert(GlobalPassDebugOpts->PassDebugging >= Details); if (Set.empty()) return; dbgs() << (const void*)P << std::string(getDepth()*2+3, ' ') << Msg << " Analyses:"; @@ -1741,11 +1769,6 @@ bool PassManager::run(Module &M) { //===----------------------------------------------------------------------===// // TimingInfo implementation -bool llvm::TimePassesIsEnabled = false; -static cl::opt -EnableTiming("time-passes", cl::location(TimePassesIsEnabled), - cl::desc("Time each pass, printing elapsed time for each on exit")); - // createTheTimeInfo - This method either initializes the TheTimeInfo pointer to // a non null value (if the -time-passes option is enabled) or it leaves it // null. It may be called multiple times. diff --git a/tools/llvm-as/llvm-as.cpp b/tools/llvm-as/llvm-as.cpp index b2e44ef9d34..9d5e96d9650 100644 --- a/tools/llvm-as/llvm-as.cpp +++ b/tools/llvm-as/llvm-as.cpp @@ -20,6 +20,7 @@ #include "llvm/Assembly/Parser.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/Module.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" @@ -89,6 +90,10 @@ int main(int argc, char **argv) { PrettyStackTraceProgram X(argc, argv); LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize PassManager for -time-passes support. + initializePassManager(); + cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n"); // Parse the file now... diff --git a/tools/llvm-diff/llvm-diff.cpp b/tools/llvm-diff/llvm-diff.cpp index f70219eaf54..62fc026327e 100644 --- a/tools/llvm-diff/llvm-diff.cpp +++ b/tools/llvm-diff/llvm-diff.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/IRReader/IRReader.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" @@ -67,6 +68,9 @@ static cl::list GlobalsToCompare(cl::Positional, cl::desc("")); int main(int argc, char **argv) { + // Initialize PassManager for -time-passes support. + initializePassManager(); + cl::ParseCommandLineOptions(argc, argv); LLVMContext Context; diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index 87eb34708a1..f31cbd4d2c3 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -23,6 +23,7 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DataStream.h" #include "llvm/Support/FormattedStream.h" @@ -119,6 +120,8 @@ int main(int argc, char **argv) { LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + // Initialize PassManager for -time-passes support. + initializePassManager(); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index dc1a410953b..99131764f36 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -96,6 +96,10 @@ int main(int argc, char **argv) { LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize PassManager for -time-passes support. + initializePassManager(); + cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); // Use lazy loading, since we only care about selected global values. diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index 99cca2322d8..8e7d4b01df8 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IRReader/IRReader.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" @@ -73,6 +74,10 @@ int main(int argc, char **argv) { LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize PassManager for -time-passes support. + initializePassManager(); + cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); unsigned BaseArg = 0; diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index 01dd1c33fdc..45309c07146 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -22,6 +22,7 @@ #include "llvm/Object/Archive.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" @@ -446,6 +447,10 @@ int main(int argc, char **argv) { PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + // Initialize PassManager for -time-passes support. + initializePassManager(); + cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n"); // llvm-nm only reads binary files. diff --git a/tools/llvm-prof/llvm-prof.cpp b/tools/llvm-prof/llvm-prof.cpp index 52d01300694..e36441d6f19 100644 --- a/tools/llvm-prof/llvm-prof.cpp +++ b/tools/llvm-prof/llvm-prof.cpp @@ -260,6 +260,9 @@ int main(int argc, char **argv) { LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + // Initialize PassManager for -time-passes support. + initializePassManager(); + cl::ParseCommandLineOptions(argc, argv, "llvm profile dump decoder\n"); // Read in the bitcode file... diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp index 15f7abf70e9..6f2224221d8 100644 --- a/tools/llvm-stress/llvm-stress.cpp +++ b/tools/llvm-stress/llvm-stress.cpp @@ -681,6 +681,10 @@ void IntroduceControlFlow(Function *F, Random &R) { int main(int argc, char **argv) { // Init LLVM, call llvm_shutdown() on exit, parse args, etc. llvm::PrettyStackTraceProgram X(argc, argv); + + // Initialize PassManager for -time-passes support. + initializePassManager(); + cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); llvm_shutdown_obj Y;