forked from OSchip/llvm-project
[NPM] Added opt option -print-pipeline-passes.
Added opt option -print-pipeline-passes to print a -passes compatible string describing the built pass pipeline. As an example: $ opt -enable-new-pm=1 -adce -licm -simplifycfg -o /dev/null /dev/null -print-pipeline-passes verify,function(adce),function(loop-mssa(licm)),function(simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts>),verify,BitcodeWriterPass At the moment this is best-effort only and there are some known limitations: - Not all passes accepting parameters will print their parameters (currently only implemented for simplifycfg). - Some ClassName to pass-name mappings are not unique. - Some ClassName to pass-name mappings are missing (e.g. BitcodeWriterPass). Differential Revision: https://reviews.llvm.org/D108298
This commit is contained in:
parent
645af79e8e
commit
304f2bd21d
|
@ -381,6 +381,13 @@ template <typename DerivedT> struct PassInfoMixin {
|
|||
Name = Name.drop_front(strlen("llvm::"));
|
||||
return Name;
|
||||
}
|
||||
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
||||
auto ClassName = name();
|
||||
auto PassName = MapClassName2PassName(ClassName);
|
||||
OS << PassName;
|
||||
}
|
||||
};
|
||||
|
||||
/// A CRTP mix-in that provides informational APIs needed for analysis passes.
|
||||
|
@ -480,6 +487,16 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
||||
for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
|
||||
auto *P = Passes[Idx].get();
|
||||
P->printPipeline(OS, MapClassName2PassName);
|
||||
if (Idx + 1 < Size)
|
||||
OS << ",";
|
||||
}
|
||||
}
|
||||
|
||||
/// Run all of the passes in this manager over the given unit of IR.
|
||||
/// ExtraArgs are passed to each pass.
|
||||
PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
|
||||
|
@ -1195,6 +1212,8 @@ public:
|
|||
|
||||
/// Runs the function pass across every function in the module.
|
||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName);
|
||||
|
||||
static bool isRequired() { return true; }
|
||||
|
||||
|
@ -1243,6 +1262,12 @@ struct RequireAnalysisPass
|
|||
|
||||
return PreservedAnalyses::all();
|
||||
}
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
||||
auto ClassName = AnalysisT::name();
|
||||
auto PassName = MapClassName2PassName(ClassName);
|
||||
OS << "require<" << PassName << ">";
|
||||
}
|
||||
static bool isRequired() { return true; }
|
||||
};
|
||||
|
||||
|
@ -1263,6 +1288,12 @@ struct InvalidateAnalysisPass
|
|||
PA.abandon<AnalysisT>();
|
||||
return PA;
|
||||
}
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
||||
auto ClassName = AnalysisT::name();
|
||||
auto PassName = MapClassName2PassName(ClassName);
|
||||
OS << "invalidate<" << PassName << ">";
|
||||
}
|
||||
};
|
||||
|
||||
/// A utility pass that does nothing, but preserves no analyses.
|
||||
|
@ -1312,6 +1343,13 @@ public:
|
|||
return PA;
|
||||
}
|
||||
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
||||
OS << "repeat<" << Count << ">(";
|
||||
P.printPipeline(OS, MapClassName2PassName);
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
private:
|
||||
int Count;
|
||||
PassT P;
|
||||
|
|
|
@ -46,6 +46,9 @@ struct PassConcept {
|
|||
virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
|
||||
ExtraArgTs... ExtraArgs) = 0;
|
||||
|
||||
virtual void
|
||||
printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName) = 0;
|
||||
/// Polymorphic method to access the name of a pass.
|
||||
virtual StringRef name() const = 0;
|
||||
|
||||
|
@ -85,6 +88,12 @@ struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
|
|||
return Pass.run(IR, AM, ExtraArgs...);
|
||||
}
|
||||
|
||||
void printPipeline(
|
||||
raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName) override {
|
||||
Pass.printPipeline(OS, MapClassName2PassName);
|
||||
}
|
||||
|
||||
StringRef name() const override { return PassT::name(); }
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -94,6 +94,8 @@ public:
|
|||
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
|
||||
LoopStandardAnalysisResults &AR, LPMUpdater &U);
|
||||
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName);
|
||||
/// Add either a loop pass or a loop-nest pass to the pass manager. Append \p
|
||||
/// Pass to the list of loop passes if it has a dedicated \fn run() method for
|
||||
/// loops and to the list of loop-nest passes if the \fn run() method is for
|
||||
|
@ -424,6 +426,8 @@ public:
|
|||
|
||||
/// Runs the loop passes across every loop in the function.
|
||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName);
|
||||
|
||||
static bool isRequired() { return true; }
|
||||
|
||||
|
|
|
@ -41,6 +41,9 @@ public:
|
|||
|
||||
/// Run the pass over the function.
|
||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
||||
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -91,6 +91,13 @@ bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
|
|||
}
|
||||
} // namespace llvm
|
||||
|
||||
void ModuleToFunctionPassAdaptor::printPipeline(
|
||||
raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
||||
OS << "function(";
|
||||
Pass->printPipeline(OS, MapClassName2PassName);
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M,
|
||||
ModuleAnalysisManager &AM) {
|
||||
FunctionAnalysisManager &FAM =
|
||||
|
|
|
@ -291,6 +291,11 @@ PipelineTuningOptions::PipelineTuningOptions() {
|
|||
}
|
||||
|
||||
namespace llvm {
|
||||
cl::opt<bool> PrintPipelinePasses(
|
||||
"print-pipeline-passes",
|
||||
cl::desc("Print a '-passes' compatible string describing the pipeline "
|
||||
"(best-effort only)."));
|
||||
|
||||
extern cl::opt<unsigned> MaxDevirtIterations;
|
||||
extern cl::opt<bool> EnableConstraintElimination;
|
||||
extern cl::opt<bool> EnableFunctionSpecialization;
|
||||
|
@ -439,7 +444,8 @@ AnalysisKey NoOpLoopAnalysis::Key;
|
|||
/// it. This should be updated if new pass instrumentation wants to use the map.
|
||||
/// We currently only use this for --print-before/after.
|
||||
bool shouldPopulateClassToPassNames() {
|
||||
return !printBeforePasses().empty() || !printAfterPasses().empty();
|
||||
return PrintPipelinePasses || !printBeforePasses().empty() ||
|
||||
!printAfterPasses().empty();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -44,6 +44,18 @@ PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
|
|||
return PA;
|
||||
}
|
||||
|
||||
void PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
|
||||
LPMUpdater &>::printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)>
|
||||
MapClassName2PassName) {
|
||||
for (unsigned Idx = 0, Size = LoopPasses.size(); Idx != Size; ++Idx) {
|
||||
auto *P = LoopPasses[Idx].get();
|
||||
P->printPipeline(OS, MapClassName2PassName);
|
||||
if (Idx + 1 < Size)
|
||||
OS << ",";
|
||||
}
|
||||
}
|
||||
|
||||
// Run both loop passes and loop-nest passes on top-level loop \p L.
|
||||
PreservedAnalyses
|
||||
LoopPassManager::runWithLoopNestPasses(Loop &L, LoopAnalysisManager &AM,
|
||||
|
@ -172,6 +184,12 @@ LoopPassManager::runWithoutLoopNestPasses(Loop &L, LoopAnalysisManager &AM,
|
|||
}
|
||||
} // namespace llvm
|
||||
|
||||
void FunctionToLoopPassAdaptor::printPipeline(
|
||||
raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
||||
OS << (UseMemorySSA ? "loop-mssa(" : "loop(");
|
||||
Pass->printPipeline(OS, MapClassName2PassName);
|
||||
OS << ")";
|
||||
}
|
||||
PreservedAnalyses FunctionToLoopPassAdaptor::run(Function &F,
|
||||
FunctionAnalysisManager &AM) {
|
||||
// Before we even compute any loop analyses, first run a miniature function
|
||||
|
|
|
@ -319,6 +319,21 @@ SimplifyCFGPass::SimplifyCFGPass(const SimplifyCFGOptions &Opts)
|
|||
applyCommandLineOverridesToOptions(Options);
|
||||
}
|
||||
|
||||
void SimplifyCFGPass::printPipeline(
|
||||
raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
||||
static_cast<PassInfoMixin<SimplifyCFGPass> *>(this)->printPipeline(
|
||||
OS, MapClassName2PassName);
|
||||
OS << "<";
|
||||
OS << "bonus-inst-threshold=" << Options.BonusInstThreshold << ";";
|
||||
OS << (Options.ForwardSwitchCondToPhi ? "" : "no-") << "forward-switch-cond;";
|
||||
OS << (Options.ConvertSwitchToLookupTable ? "" : "no-")
|
||||
<< "switch-to-lookup;";
|
||||
OS << (Options.NeedCanonicalLoop ? "" : "no-") << "keep-loops;";
|
||||
OS << (Options.HoistCommonInsts ? "" : "no-") << "hoist-common-insts;";
|
||||
OS << (Options.SinkCommonInsts ? "" : "no-") << "sink-common-insts";
|
||||
OS << ">";
|
||||
}
|
||||
|
||||
PreservedAnalyses SimplifyCFGPass::run(Function &F,
|
||||
FunctionAnalysisManager &AM) {
|
||||
auto &TTI = AM.getResult<TargetIRAnalysis>(F);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
;; Test that the -print-pipeline-passes option correctly prints some explicitly specified pipelines.
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(adce),function(simplifycfg<bonus-inst-threshold=123;no-forward-switch-cond;switch-to-lookup;keep-loops;no-hoist-common-insts;sink-common-insts>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-0
|
||||
; CHECK-0: function(adce),function(simplifycfg<bonus-inst-threshold=123;no-forward-switch-cond;switch-to-lookup;keep-loops;no-hoist-common-insts;sink-common-insts>)
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='module(rpo-function-attrs,require<globals-aa>,function(float2int,lower-constant-intrinsics,loop(loop-rotate)),invalidate<globals-aa>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-1
|
||||
; CHECK-1: rpo-function-attrs,require<globals-aa>,function(float2int,lower-constant-intrinsics,loop(loop-rotate)),invalidate<globals-aa>
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='repeat<5>(function(mem2reg)),invalidate<all>' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-2
|
||||
; CHECK-2: repeat<5>(function(mem2reg)),invalidate<all>
|
||||
|
||||
;; Test that we get ClassName printed when there is no ClassName to pass-name mapping (as is the case for the BitcodeWriterPass).
|
||||
; RUN: opt -o /dev/null -disable-verify -print-pipeline-passes -passes='function(mem2reg)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-3
|
||||
; CHECK-3: function(mem2reg),BitcodeWriterPass
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(loop-mssa(indvars))' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-4
|
||||
; CHECK-4: function(loop-mssa(indvars))
|
|
@ -137,6 +137,7 @@ extern cl::opt<std::string> ProfileFile;
|
|||
extern cl::opt<CSPGOKind> CSPGOKindFlag;
|
||||
extern cl::opt<std::string> CSProfileGenFile;
|
||||
extern cl::opt<bool> DisableBasicAA;
|
||||
extern cl::opt<bool> PrintPipelinePasses;
|
||||
} // namespace llvm
|
||||
|
||||
static cl::opt<std::string>
|
||||
|
@ -473,6 +474,17 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
|
|||
// Before executing passes, print the final values of the LLVM options.
|
||||
cl::PrintOptionValues();
|
||||
|
||||
// Print a textual, '-passes=' compatible, representation of pipeline if
|
||||
// requested.
|
||||
if (PrintPipelinePasses) {
|
||||
MPM.printPipeline(outs(), [&PIC](StringRef ClassName) {
|
||||
auto PassName = PIC.getPassNameForClassName(ClassName);
|
||||
return PassName.empty() ? ClassName : PassName;
|
||||
});
|
||||
outs() << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now that we have all of the passes ready, run them.
|
||||
MPM.run(M, MAM);
|
||||
|
||||
|
|
Loading…
Reference in New Issue