class Module;
class Function;
-namespace detail {
-
-// Declare our debug option here so we can refer to it from templates.
-extern cl::opt<bool> DebugPM;
-
-} // End detail namespace
-
/// \brief An abstract set of preserved analyses following a transformation pass
/// run.
///
/// runs.
template <typename IRUnitT> class PassManager {
public:
+ /// \brief Construct a pass manager.
+ ///
+ /// It can be passed a flag to get debug logging as the passes are run.
+ PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- PassManager() {}
- PassManager(PassManager &&Arg) : Passes(std::move(Arg.Passes)) {}
+ PassManager(PassManager &&Arg)
+ : Passes(std::move(Arg.Passes)),
+ DebugLogging(std::move(Arg.DebugLogging)) {}
PassManager &operator=(PassManager &&RHS) {
Passes = std::move(RHS.Passes);
+ DebugLogging = std::move(RHS.DebugLogging);
return *this;
}
PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM = nullptr) {
PreservedAnalyses PA = PreservedAnalyses::all();
- if (detail::DebugPM)
+ if (DebugLogging)
dbgs() << "Starting pass manager run.\n";
for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
- if (detail::DebugPM)
+ if (DebugLogging)
dbgs() << "Running pass: " << Passes[Idx]->name() << "\n";
PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM);
//IR.getContext().yield();
}
- if (detail::DebugPM)
+ if (DebugLogging)
dbgs() << "Finished pass manager run.\n";
return PA;
PassManager &operator=(const PassManager &) LLVM_DELETED_FUNCTION;
std::vector<std::unique_ptr<PassConceptT>> Passes;
+
+ /// \brief Flag indicating whether we should do debug logging.
+ bool DebugLogging;
};
/// \brief Convenience typedef for a pass manager over modules.
public:
// Most public APIs are inherited from the CRTP base class.
+ /// \brief Construct an empty analysis manager.
+ ///
+ /// A flag can be passed to indicate that the manager should perform debug
+ /// logging.
+ AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}
+
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- AnalysisManager() {}
AnalysisManager(AnalysisManager &&Arg)
: BaseT(std::move(static_cast<BaseT &>(Arg))),
- AnalysisResults(std::move(Arg.AnalysisResults)) {}
+ AnalysisResults(std::move(Arg.AnalysisResults)),
+ DebugLogging(std::move(Arg.DebugLogging)) {}
AnalysisManager &operator=(AnalysisManager &&RHS) {
BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
AnalysisResults = std::move(RHS.AnalysisResults);
+ DebugLogging = std::move(RHS.DebugLogging);
return *this;
}
// run it to produce a result, which we then add to the cache.
if (Inserted) {
auto &P = this->lookupPass(PassID);
- if (detail::DebugPM)
+ if (DebugLogging)
dbgs() << "Running analysis: " << P.name() << "\n";
AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
ResultList.emplace_back(PassID, P.run(IR, this));
if (RI == AnalysisResults.end())
return;
- if (detail::DebugPM)
+ if (DebugLogging)
dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name()
<< "\n";
AnalysisResultLists[&IR].erase(RI->second);
if (PA.areAllPreserved())
return std::move(PA);
- if (detail::DebugPM)
+ if (DebugLogging)
dbgs() << "Invalidating all non-preserved analyses for: "
<< IR.getName() << "\n";
// necessary. The analysis pass can return false if no action on the part
// of the analysis manager is required for this invalidation event.
if (I->second->invalidate(IR, PA)) {
- if (detail::DebugPM)
+ if (DebugLogging)
dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name()
<< "\n";
/// \brief Map from an analysis ID and function to a particular cached
/// analysis result.
AnalysisResultMapT AnalysisResults;
+
+ /// \brief A flag indicating whether debug logging is enabled.
+ bool DebugLogging;
};
/// \brief Convenience typedef for the Module analysis manager.
using namespace llvm;
using namespace opt_tool;
+static cl::opt<bool>
+ DebugPM("debug-pass-manager", cl::Hidden,
+ cl::desc("Print pass management debugging information"));
+
bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
tool_output_file *Out, StringRef PassPipeline,
OutputKind OK, VerifierKind VK) {
- FunctionAnalysisManager FAM;
- CGSCCAnalysisManager CGAM;
- ModuleAnalysisManager MAM;
+ FunctionAnalysisManager FAM(DebugPM);
+ CGSCCAnalysisManager CGAM(DebugPM);
+ ModuleAnalysisManager MAM(DebugPM);
// Register all the basic analyses with the managers.
registerModuleAnalyses(MAM);
FAM.registerPass(CGSCCAnalysisManagerFunctionProxy(CGAM));
FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM));
- ModulePassManager MPM;
+ ModulePassManager MPM(DebugPM);
if (VK > VK_NoVerifier)
MPM.addPass(VerifierPass());
- if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass)) {
+ if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass, DebugPM)) {
errs() << Arg0 << ": unable to parse pass pipeline description.\n";
return false;
}
static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
StringRef &PipelineText,
- bool VerifyEachPass) {
+ bool VerifyEachPass, bool DebugLogging) {
for (;;) {
// Parse nested pass managers by recursing.
if (PipelineText.startswith("function(")) {
- FunctionPassManager NestedFPM;
+ FunctionPassManager NestedFPM(DebugLogging);
// Parse the inner pipeline inte the nested manager.
PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
+ if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
+ DebugLogging) ||
PipelineText.empty())
return false;
assert(PipelineText[0] == ')');
}
static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
- StringRef &PipelineText,
- bool VerifyEachPass) {
+ StringRef &PipelineText, bool VerifyEachPass,
+ bool DebugLogging) {
for (;;) {
// Parse nested pass managers by recursing.
if (PipelineText.startswith("cgscc(")) {
- CGSCCPassManager NestedCGPM;
+ CGSCCPassManager NestedCGPM(DebugLogging);
// Parse the inner pipeline into the nested manager.
PipelineText = PipelineText.substr(strlen("cgscc("));
- if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) ||
+ if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass,
+ DebugLogging) ||
PipelineText.empty())
return false;
assert(PipelineText[0] == ')');
// Add the nested pass manager with the appropriate adaptor.
CGPM.addPass(std::move(NestedCGPM));
} else if (PipelineText.startswith("function(")) {
- FunctionPassManager NestedFPM;
+ FunctionPassManager NestedFPM(DebugLogging);
// Parse the inner pipeline inte the nested manager.
PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
+ if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
+ DebugLogging) ||
PipelineText.empty())
return false;
assert(PipelineText[0] == ')');
static bool parseModulePassPipeline(ModulePassManager &MPM,
StringRef &PipelineText,
- bool VerifyEachPass) {
+ bool VerifyEachPass, bool DebugLogging) {
for (;;) {
// Parse nested pass managers by recursing.
if (PipelineText.startswith("module(")) {
- ModulePassManager NestedMPM;
+ ModulePassManager NestedMPM(DebugLogging);
// Parse the inner pipeline into the nested manager.
PipelineText = PipelineText.substr(strlen("module("));
- if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass) ||
+ if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass,
+ DebugLogging) ||
PipelineText.empty())
return false;
assert(PipelineText[0] == ')');
// Now add the nested manager as a module pass.
MPM.addPass(std::move(NestedMPM));
} else if (PipelineText.startswith("cgscc(")) {
- CGSCCPassManager NestedCGPM;
+ CGSCCPassManager NestedCGPM(DebugLogging);
// Parse the inner pipeline inte the nested manager.
PipelineText = PipelineText.substr(strlen("cgscc("));
- if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) ||
+ if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass,
+ DebugLogging) ||
PipelineText.empty())
return false;
assert(PipelineText[0] == ')');
MPM.addPass(
createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM)));
} else if (PipelineText.startswith("function(")) {
- FunctionPassManager NestedFPM;
+ FunctionPassManager NestedFPM(DebugLogging);
// Parse the inner pipeline inte the nested manager.
PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
+ if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
+ DebugLogging) ||
PipelineText.empty())
return false;
assert(PipelineText[0] == ')');
// FIXME: Should this routine accept a TargetMachine or require the caller to
// pre-populate the analysis managers with target-specific stuff?
bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
- bool VerifyEachPass) {
+ bool VerifyEachPass, bool DebugLogging) {
// By default, try to parse the pipeline as-if it were within an implicit
// 'module(...)' pass pipeline. If this will parse at all, it needs to
// consume the entire string.
- if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass))
+ if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass, DebugLogging))
return PipelineText.empty();
// This isn't parsable as a module pipeline, look for the end of a pass name
// If this looks like a CGSCC pass, parse the whole thing as a CGSCC
// pipeline.
if (isCGSCCPassName(FirstName)) {
- CGSCCPassManager CGPM;
- if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) ||
+ CGSCCPassManager CGPM(DebugLogging);
+ if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass,
+ DebugLogging) ||
!PipelineText.empty())
return false;
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
// Similarly, if this looks like a Function pass, parse the whole thing as
// a Function pipelien.
if (isFunctionPassName(FirstName)) {
- FunctionPassManager FPM;
- if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
+ FunctionPassManager FPM(DebugLogging);
+ if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass,
+ DebugLogging) ||
!PipelineText.empty())
return false;
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));