Encapsulate PassManager debug flags to avoid static init and cxa_exit.
authorAndrew Trick <atrick@apple.com>
Wed, 18 Sep 2013 23:31:16 +0000 (23:31 +0000)
committerAndrew Trick <atrick@apple.com>
Wed, 18 Sep 2013 23:31:16 +0000 (23:31 +0000)
This puts all the global PassManager debugging flags, like
-print-after-all and -time-passes, behind a managed static. This
eliminates their static initializers and, more importantly, exit-time
destructors.

The only behavioral change I anticipate is that tools need to
initialize the PassManager before parsing the command line in order to
export these options, which makes sense. Tools that already initialize
the standard passes (opt/llc) don't need to do anything new.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190974 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/PassManager.h
lib/IR/Core.cpp
lib/IR/PassManager.cpp
tools/llvm-as/llvm-as.cpp
tools/llvm-diff/llvm-diff.cpp
tools/llvm-dis/llvm-dis.cpp
tools/llvm-extract/llvm-extract.cpp
tools/llvm-link/llvm-link.cpp
tools/llvm-nm/llvm-nm.cpp
tools/llvm-prof/llvm-prof.cpp
tools/llvm-stress/llvm-stress.cpp

index b6a8186a4e809b2049b01bfcdf143cd9778bfb65..044dc3320bacf5aeed2fa6988339c205ca5af9f6 100644 (file)
@@ -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.
index 95c516a251177785257ffaac46ecf384fe3056b8..749ae6014619c1c66bcf135f91825c51550fb91c 100644 (file)
@@ -40,6 +40,7 @@
 using namespace llvm;
 
 void llvm::initializeCore(PassRegistry &Registry) {
+  initializePassManager();
   initializeDominatorTreePass(Registry);
   initializePrintModulePassPass(Registry);
   initializePrintFunctionPassPass(Registry);
index 8d2e2ca89bacf92555c44141637f065f9d9d6aa0..99933a89b004c5150b6cfde3afcf47d7461c2b42 100644 (file)
@@ -45,65 +45,94 @@ enum PassDebugLevel {
   Disabled, Arguments, Structure, Executions, Details
 };
 
-static cl::opt<enum PassDebugLevel>
-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<enum PassDebugLevel> PassDebugging;
+
+  typedef llvm::cl::list<const llvm::PassInfo *, bool, PassNameParser>
+  PassOptionList;
+
+  // Print IR out before/after specified passes.
+  PassOptionList PrintBefore;
+
+  PassOptionList PrintAfter;
+
+  cl::opt<bool> PrintBeforeAll;
+  cl::opt<bool> PrintAfterAll;
+
+  cl::opt<bool,true> 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));
-
-typedef llvm::cl::list<const llvm::PassInfo *, bool, PassNameParser>
-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<bool>
-PrintBeforeAll("print-before-all",
-               llvm::cl::desc("Print IR before each pass"),
-               cl::init(false));
-static cl::opt<bool>
-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;
-      }
+                    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"))
+  {}
+
+  /// 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.
+  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.
-static bool ShouldPrintAfterPass(const PassInfo *PI) {
-  return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter);
+static ManagedStatic<PassDebugOpts> 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<bool,true>
-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.
index b2e44ef9d3468e9de31a656c87cd92f2b0cf35b6..9d5e96d9650e6ed209aad387594c6d1dab32cb58 100644 (file)
@@ -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...
index f70219eaf542abbc064979e955355e1ba3c97138..62fc026327ea3bc7c22e4bda24ff3845312c4d8c 100644 (file)
@@ -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<std::string> GlobalsToCompare(cl::Positional,
                                               cl::desc("<globals to compare>"));
 
 int main(int argc, char **argv) {
+  // Initialize PassManager for -time-passes support.
+  initializePassManager();
+
   cl::ParseCommandLineOptions(argc, argv);
 
   LLVMContext Context;
index 87eb34708a1debedd102b2e131b2de8d7b8deb0b..f31cbd4d2c3f8a041e955dc419020bc78aec4ea9 100644 (file)
@@ -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");
 
index dc1a410953b6d6afb9f34b0b7b457801fc9c33a8..99131764f36530e770705ea85d3775f60255fe19 100644 (file)
@@ -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.
index 99cca2322d8a8ce701f3492f1a21a80ba24862da..8e7d4b01df85116ce29296ae93bf6aa09f68024e 100644 (file)
@@ -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;
index 01dd1c33fdcadcfb4ff9647276ad76e61f52dbda..45309c071466eae2cf60e886c960a6deed4ddc74 100644 (file)
@@ -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.
index 52d0130069467bc443bdeb0b98f8049426611c1f..e36441d6f19c6a7fa2595193094b1b3b5c49adbf 100644 (file)
@@ -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...
index 15f7abf70e9f709db1cc6259c801dfcf063e2b57..6f2224221d895db96f8e6c02704677dbc3e73bcc 100644 (file)
@@ -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;