[llvm] 5d960cb - [opt][NewPM] Add a --print-passes flag to print all available passes

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 10 11:22:34 PST 2021


Author: Arthur Eubanks
Date: 2021-02-10T11:22:12-08:00
New Revision: 5d960cba34682d0d4e0cd56837131888eb647c62

URL: https://github.com/llvm/llvm-project/commit/5d960cba34682d0d4e0cd56837131888eb647c62
DIFF: https://github.com/llvm/llvm-project/commit/5d960cba34682d0d4e0cd56837131888eb647c62.diff

LOG: [opt][NewPM] Add a --print-passes flag to print all available passes

It seems nicer to list passes given a flag rather than displaying all
passes in opt --help.

This is awkwardly structured because a PassBuilder is required, but
reusing the PassBuilder in runPassPipeline() doesn't work because we
read the input IR before getting to runPassPipeline(). So printing the
list of passes needs to happen before reading the input IR. If we remove
the legacy PM code in main() and move everything from NewPMDriver.cpp
into opt.cpp, we can create the PassBuilder before reading IR and check
if we should print the list of passes and exit. But until then this hack
seems fine.

Compared to the legacy PM, the new PM passes are lacking descriptions.
We'll need to figure out a way to add descriptions if we think this is
important.

Also, this only works for passes specified in PassRegistry.def. If we
want to print other custom registered passes, we'll need a different
mechanism.

Reviewed By: asbirlea

Differential Revision: https://reviews.llvm.org/D96101

Added: 
    llvm/test/Other/print-passes.ll

Modified: 
    llvm/include/llvm/Passes/PassBuilder.h
    llvm/lib/Passes/PassBuilder.cpp
    llvm/tools/opt/NewPMDriver.cpp
    llvm/tools/opt/NewPMDriver.h
    llvm/tools/opt/opt.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index 28f9e83bf76a..9bff0a4d9302 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -19,6 +19,7 @@
 #include "llvm/Analysis/CGSCCPassManager.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/IPO/Inliner.h"
 #include "llvm/Transforms/Instrumentation.h"
 #include "llvm/Transforms/Scalar/LoopPassManager.h"
@@ -532,6 +533,9 @@ class PassBuilder {
   /// Returns true if the pass name is the name of a (non-alias) analysis pass.
   bool isAnalysisPassName(StringRef PassName);
 
+  /// Print pass names.
+  void printPassNames(raw_ostream &OS);
+
   /// Register a callback for a default optimizer pipeline extension
   /// point
   ///

diff  --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 29c2eb82c3bb..92cabeaafa39 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -3060,6 +3060,54 @@ bool PassBuilder::isAnalysisPassName(StringRef PassName) {
   return false;
 }
 
+static void printPassName(StringRef PassName, raw_ostream &OS) {
+  OS << "  " << PassName << "\n";
+}
+
+void PassBuilder::printPassNames(raw_ostream &OS) {
+  // TODO: print pass descriptions when they are available
+
+  OS << "Module passes:\n";
+#define MODULE_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+
+  OS << "Module analyses:\n";
+#define MODULE_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+
+  OS << "Module alias analyses:\n";
+#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+
+  OS << "CGSCC passes:\n";
+#define CGSCC_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+
+  OS << "CGSCC analyses:\n";
+#define CGSCC_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+
+  OS << "Function passes:\n";
+#define FUNCTION_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+
+  OS << "Function analyses:\n";
+#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+
+  OS << "Function alias analyses:\n";
+#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+
+  OS << "Loop passes:\n";
+#define LOOP_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+
+  OS << "Loop analyses:\n";
+#define LOOP_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
+#include "PassRegistry.def"
+}
+
 void PassBuilder::registerParseTopLevelPipelineCallback(
     const std::function<bool(ModulePassManager &, ArrayRef<PipelineElement>,
                              bool DebugLogging)> &C) {

diff  --git a/llvm/test/Other/print-passes.ll b/llvm/test/Other/print-passes.ll
new file mode 100644
index 000000000000..a77922bff6f4
--- /dev/null
+++ b/llvm/test/Other/print-passes.ll
@@ -0,0 +1,22 @@
+; RUN: opt --print-passes | FileCheck %s
+
+; CHECK: Module passes:
+; CHECK: no-op-module
+; CHECK: Module analyses:
+; CHECK: no-op-module
+; CHECK: Module alias analyses:
+; CHECK: globals-aa
+; CHECK: CGSCC passes:
+; CHECK: no-op-cgscc
+; CHECK: CGSCC analyses:
+; CHECK: no-op-cgscc
+; CHECK: Function passes:
+; CHECK: no-op-function
+; CHECK: Function analyses:
+; CHECK: no-op-function
+; CHECK: Function alias analyses:
+; CHECK: basic-aa
+; CHECK: Loop passes:
+; CHECK: no-op-loop
+; CHECK: Loop analyses:
+; CHECK: no-op-loop

diff  --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 401a58fc154a..1c6da3822451 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -463,3 +463,8 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
 
   return true;
 }
+
+void llvm::printPasses(raw_ostream &OS) {
+  PassBuilder PB;
+  PB.printPassNames(OS);
+}

diff  --git a/llvm/tools/opt/NewPMDriver.h b/llvm/tools/opt/NewPMDriver.h
index 87a71cec4c53..ebec4fd6a0fb 100644
--- a/llvm/tools/opt/NewPMDriver.h
+++ b/llvm/tools/opt/NewPMDriver.h
@@ -54,6 +54,8 @@ enum PGOKind {
 enum CSPGOKind { NoCSPGO, CSInstrGen, CSInstrUse };
 }
 
+void printPasses(raw_ostream &OS);
+
 /// Driver function to run the new pass manager over a module.
 ///
 /// This function only exists factored away from opt.cpp in order to prevent

diff  --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp
index 9426940d3ba7..a5b50582d0ac 100644
--- a/llvm/tools/opt/opt.cpp
+++ b/llvm/tools/opt/opt.cpp
@@ -82,8 +82,13 @@ static cl::opt<bool> EnableNewPassManager(
 // pass management.
 static cl::opt<std::string> PassPipeline(
     "passes",
-    cl::desc("A textual description of the pass pipeline for optimizing"),
-    cl::Hidden);
+    cl::desc(
+        "A textual description of the pass pipeline. To have analysis passes "
+        "available before a certain pass, add 'require<foo-analysis>'."));
+
+static cl::opt<bool> PrintPasses("print-passes",
+                                 cl::desc("Print available passes that can be "
+                                          "specified in -passes=foo and exit"));
 
 static cl::opt<std::string>
 InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
@@ -589,6 +594,14 @@ int main(int argc, char **argv) {
     return 1;
   }
 
+  // FIXME: once the legacy PM code is deleted, move runPassPipeline() here and
+  // construct the PassBuilder before parsing IR so we can reuse the same
+  // PassBuilder for print passes.
+  if (PrintPasses) {
+    printPasses(outs());
+    return 0;
+  }
+
   TimeTracerRAII TimeTracer(argv[0]);
 
   SMDiagnostic Err;


        


More information about the llvm-commits mailing list