Encapsulate PassManager debug flags to avoid static init and cxa_exit.

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
This commit is contained in:
Andrew Trick 2013-09-18 23:31:16 +00:00
parent 2cccc6220c
commit 7d4e9934e7
11 changed files with 135 additions and 73 deletions

View File

@ -28,6 +28,11 @@ class Module;
class PassManagerImpl; class PassManagerImpl;
class FunctionPassManagerImpl; 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 /// PassManagerBase - An abstract interface to allow code to add passes to
/// a pass manager without having to hard-code what kind of pass manager /// a pass manager without having to hard-code what kind of pass manager
/// it is. /// it is.

View File

@ -40,6 +40,7 @@
using namespace llvm; using namespace llvm;
void llvm::initializeCore(PassRegistry &Registry) { void llvm::initializeCore(PassRegistry &Registry) {
initializePassManager();
initializeDominatorTreePass(Registry); initializeDominatorTreePass(Registry);
initializePrintModulePassPass(Registry); initializePrintModulePassPass(Registry);
initializePrintFunctionPassPass(Registry); initializePrintFunctionPassPass(Registry);

View File

@ -45,65 +45,94 @@ enum PassDebugLevel {
Disabled, Arguments, Structure, Executions, Details Disabled, Arguments, Structure, Executions, Details
}; };
static cl::opt<enum PassDebugLevel> bool TimePassesIsEnabled = false;
PassDebugging("debug-pass", cl::Hidden,
/// 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::desc("Print PassManager debugging information"),
cl::values( cl::values(
clEnumVal(Disabled , "disable debug output"), clEnumVal(Disabled , "disable debug output"),
clEnumVal(Arguments , "print pass arguments to pass to 'opt'"), clEnumVal(Arguments,
clEnumVal(Structure , "print pass structure before run()"), "print pass arguments to pass to 'opt'"),
clEnumVal(Executions, "print pass name before it is executed"), clEnumVal(Structure, "print pass structure before run()"),
clEnumVal(Details , "print pass details when it is executed"), clEnumVal(Executions,
clEnumValEnd)); "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<const llvm::PassInfo *, bool, PassNameParser> /// This is a helper to determine whether to print IR before or
PassOptionList; /// after a pass.
bool ShouldPrintBeforeOrAfterPass(const PassInfo *PI,
// Print IR out before/after specified passes. PassOptionList &PassesToPrint) {
static PassOptionList for (unsigned i = 0, ie = PassesToPrint.size(); i < ie; ++i) {
PrintBefore("print-before", const llvm::PassInfo *PassInf = PassesToPrint[i];
llvm::cl::desc("Print IR before specified passes"), if (PassInf)
cl::Hidden); if (PassInf->getPassArgument() == PI->getPassArgument()) {
return true;
static PassOptionList }
PrintAfter("print-after", }
llvm::cl::desc("Print IR after specified passes"), return false;
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;
}
} }
return false;
}
/// This is a utility to check whether a pass should have IR dumped /// This is a utility to check whether a pass should have IR dumped
/// before it. /// before it.
static bool ShouldPrintBeforePass(const PassInfo *PI) { bool ShouldPrintBeforePass(const PassInfo *PI) {
return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore); return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore);
} }
/// This is a utility to check whether a pass should have IR dumped /// This is a utility to check whether a pass should have IR dumped
/// after it. /// after it.
static bool ShouldPrintAfterPass(const PassInfo *PI) { bool ShouldPrintAfterPass(const PassInfo *PI) {
return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter); 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 } // End of llvm namespace
@ -111,12 +140,9 @@ static bool ShouldPrintAfterPass(const PassInfo *PI) {
/// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions
/// or higher is specified. /// or higher is specified.
bool PMDataManager::isPassDebuggingExecutionsOrMore() const { bool PMDataManager::isPassDebuggingExecutionsOrMore() const {
return PassDebugging >= Executions; return GlobalPassDebugOpts->PassDebugging >= Executions;
} }
void PassManagerPrettyStackEntry::print(raw_ostream &OS) const { void PassManagerPrettyStackEntry::print(raw_ostream &OS) const {
if (V == 0 && M == 0) if (V == 0 && M == 0)
OS << "Releasing pass '"; OS << "Releasing pass '";
@ -668,7 +694,8 @@ void PMTopLevelManager::schedulePass(Pass *P) {
return; return;
} }
if (PI && !PI->isAnalysis() && ShouldPrintBeforePass(PI)) { if (PI && !PI->isAnalysis() &&
GlobalPassDebugOpts->ShouldPrintBeforePass(PI)) {
Pass *PP = P->createPrinterPass( Pass *PP = P->createPrinterPass(
dbgs(), std::string("*** IR Dump Before ") + P->getPassName() + " ***"); dbgs(), std::string("*** IR Dump Before ") + P->getPassName() + " ***");
PP->assignPassManager(activeStack, getTopLevelPassManagerType()); PP->assignPassManager(activeStack, getTopLevelPassManagerType());
@ -677,7 +704,8 @@ void PMTopLevelManager::schedulePass(Pass *P) {
// Add the requested pass to the best available pass manager. // Add the requested pass to the best available pass manager.
P->assignPassManager(activeStack, getTopLevelPassManagerType()); P->assignPassManager(activeStack, getTopLevelPassManagerType());
if (PI && !PI->isAnalysis() && ShouldPrintAfterPass(PI)) { if (PI && !PI->isAnalysis() &&
GlobalPassDebugOpts->ShouldPrintAfterPass(PI)) {
Pass *PP = P->createPrinterPass( Pass *PP = P->createPrinterPass(
dbgs(), std::string("*** IR Dump After ") + P->getPassName() + " ***"); dbgs(), std::string("*** IR Dump After ") + P->getPassName() + " ***");
PP->assignPassManager(activeStack, getTopLevelPassManagerType()); PP->assignPassManager(activeStack, getTopLevelPassManagerType());
@ -729,7 +757,7 @@ Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) {
// Print passes managed by this top level manager. // Print passes managed by this top level manager.
void PMTopLevelManager::dumpPasses() const { void PMTopLevelManager::dumpPasses() const {
if (PassDebugging < Structure) if (GlobalPassDebugOpts->PassDebugging < Structure)
return; return;
// Print out the immutable passes // Print out the immutable passes
@ -748,7 +776,7 @@ void PMTopLevelManager::dumpPasses() const {
void PMTopLevelManager::dumpArguments() const { void PMTopLevelManager::dumpArguments() const {
if (PassDebugging < Arguments) if (GlobalPassDebugOpts->PassDebugging < Arguments)
return; return;
dbgs() << "Pass Arguments: "; dbgs() << "Pass Arguments: ";
@ -881,7 +909,7 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) {
std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
PreservedSet.end()) { PreservedSet.end()) {
// Remove this analysis // Remove this analysis
if (PassDebugging >= Details) { if (GlobalPassDebugOpts->PassDebugging >= Details) {
Pass *S = Info->second; Pass *S = Info->second;
dbgs() << " -- '" << P->getPassName() << "' is not preserving '"; dbgs() << " -- '" << P->getPassName() << "' is not preserving '";
dbgs() << S->getPassName() << "'\n"; dbgs() << S->getPassName() << "'\n";
@ -905,7 +933,7 @@ void PMDataManager::removeNotPreservedAnalysis(Pass *P) {
std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) == std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
PreservedSet.end()) { PreservedSet.end()) {
// Remove this analysis // Remove this analysis
if (PassDebugging >= Details) { if (GlobalPassDebugOpts->PassDebugging >= Details) {
Pass *S = Info->second; Pass *S = Info->second;
dbgs() << " -- '" << P->getPassName() << "' is not preserving '"; dbgs() << " -- '" << P->getPassName() << "' is not preserving '";
dbgs() << S->getPassName() << "'\n"; dbgs() << S->getPassName() << "'\n";
@ -928,7 +956,7 @@ void PMDataManager::removeDeadPasses(Pass *P, StringRef Msg,
TPM->collectLastUses(DeadPasses, P); TPM->collectLastUses(DeadPasses, P);
if (PassDebugging >= Details && !DeadPasses.empty()) { if (GlobalPassDebugOpts->PassDebugging >= Details && !DeadPasses.empty()) {
dbgs() << " -*- '" << P->getPassName(); dbgs() << " -*- '" << P->getPassName();
dbgs() << "' is the last user of following pass instances."; dbgs() << "' is the last user of following pass instances.";
dbgs() << " Free these instances\n"; dbgs() << " Free these instances\n";
@ -1146,7 +1174,7 @@ void PMDataManager::dumpPassArguments() const {
void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1, void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1,
enum PassDebuggingString S2, enum PassDebuggingString S2,
StringRef Msg) { StringRef Msg) {
if (PassDebugging < Executions) if (GlobalPassDebugOpts->PassDebugging < Executions)
return; return;
dbgs() << (void*)this << std::string(getDepth()*2+1, ' '); dbgs() << (void*)this << std::string(getDepth()*2+1, ' ');
switch (S1) { switch (S1) {
@ -1187,7 +1215,7 @@ void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1,
} }
void PMDataManager::dumpRequiredSet(const Pass *P) const { void PMDataManager::dumpRequiredSet(const Pass *P) const {
if (PassDebugging < Details) if (GlobalPassDebugOpts->PassDebugging < Details)
return; return;
AnalysisUsage analysisUsage; AnalysisUsage analysisUsage;
@ -1196,7 +1224,7 @@ void PMDataManager::dumpRequiredSet(const Pass *P) const {
} }
void PMDataManager::dumpPreservedSet(const Pass *P) const { void PMDataManager::dumpPreservedSet(const Pass *P) const {
if (PassDebugging < Details) if (GlobalPassDebugOpts->PassDebugging < Details)
return; return;
AnalysisUsage analysisUsage; AnalysisUsage analysisUsage;
@ -1206,7 +1234,7 @@ void PMDataManager::dumpPreservedSet(const Pass *P) const {
void PMDataManager::dumpAnalysisUsage(StringRef Msg, const Pass *P, void PMDataManager::dumpAnalysisUsage(StringRef Msg, const Pass *P,
const AnalysisUsage::VectorType &Set) const { const AnalysisUsage::VectorType &Set) const {
assert(PassDebugging >= Details); assert(GlobalPassDebugOpts->PassDebugging >= Details);
if (Set.empty()) if (Set.empty())
return; return;
dbgs() << (const void*)P << std::string(getDepth()*2+3, ' ') << Msg << " Analyses:"; dbgs() << (const void*)P << std::string(getDepth()*2+3, ' ') << Msg << " Analyses:";
@ -1741,11 +1769,6 @@ bool PassManager::run(Module &M) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// TimingInfo implementation // 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 // createTheTimeInfo - This method either initializes the TheTimeInfo pointer to
// a non null value (if the -time-passes option is enabled) or it leaves it // a non null value (if the -time-passes option is enabled) or it leaves it
// null. It may be called multiple times. // null. It may be called multiple times.

View File

@ -20,6 +20,7 @@
#include "llvm/Assembly/Parser.h" #include "llvm/Assembly/Parser.h"
#include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/PrettyStackTrace.h"
@ -89,6 +90,10 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv); PrettyStackTraceProgram X(argc, argv);
LLVMContext &Context = getGlobalContext(); LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 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"); cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n");
// Parse the file now... // Parse the file now...

View File

@ -20,6 +20,7 @@
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/Type.h" #include "llvm/IR/Type.h"
#include "llvm/IRReader/IRReader.h" #include "llvm/IRReader/IRReader.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h" #include "llvm/Support/SourceMgr.h"
@ -67,6 +68,9 @@ static cl::list<std::string> GlobalsToCompare(cl::Positional,
cl::desc("<globals to compare>")); cl::desc("<globals to compare>"));
int main(int argc, char **argv) { int main(int argc, char **argv) {
// Initialize PassManager for -time-passes support.
initializePassManager();
cl::ParseCommandLineOptions(argc, argv); cl::ParseCommandLineOptions(argc, argv);
LLVMContext Context; LLVMContext Context;

View File

@ -23,6 +23,7 @@
#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/Type.h" #include "llvm/IR/Type.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/DataStream.h" #include "llvm/Support/DataStream.h"
#include "llvm/Support/FormattedStream.h" #include "llvm/Support/FormattedStream.h"
@ -119,6 +120,8 @@ int main(int argc, char **argv) {
LLVMContext &Context = getGlobalContext(); LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 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"); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");

View File

@ -96,6 +96,10 @@ int main(int argc, char **argv) {
LLVMContext &Context = getGlobalContext(); LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Initialize PassManager for -time-passes support.
initializePassManager();
cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n");
// Use lazy loading, since we only care about selected global values. // Use lazy loading, since we only care about selected global values.

View File

@ -18,6 +18,7 @@
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h" #include "llvm/IRReader/IRReader.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
@ -73,6 +74,10 @@ int main(int argc, char **argv) {
LLVMContext &Context = getGlobalContext(); LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
// Initialize PassManager for -time-passes support.
initializePassManager();
cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
unsigned BaseArg = 0; unsigned BaseArg = 0;

View File

@ -22,6 +22,7 @@
#include "llvm/Object/Archive.h" #include "llvm/Object/Archive.h"
#include "llvm/Object/MachOUniversal.h" #include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
@ -446,6 +447,10 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv); PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 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"); cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
// llvm-nm only reads binary files. // llvm-nm only reads binary files.

View File

@ -260,6 +260,9 @@ int main(int argc, char **argv) {
LLVMContext &Context = getGlobalContext(); LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 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"); cl::ParseCommandLineOptions(argc, argv, "llvm profile dump decoder\n");
// Read in the bitcode file... // Read in the bitcode file...

View File

@ -681,6 +681,10 @@ void IntroduceControlFlow(Function *F, Random &R) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
// Init LLVM, call llvm_shutdown() on exit, parse args, etc. // Init LLVM, call llvm_shutdown() on exit, parse args, etc.
llvm::PrettyStackTraceProgram X(argc, argv); llvm::PrettyStackTraceProgram X(argc, argv);
// Initialize PassManager for -time-passes support.
initializePassManager();
cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");
llvm_shutdown_obj Y; llvm_shutdown_obj Y;