[llvm] [PassManager] Outline pipeline name printing (PR #202655)

David Zbarsky via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 9 07:01:35 PDT 2026


https://github.com/dzbarsky created https://github.com/llvm/llvm-project/pull/202655

PassInfoMixin, RequireAnalysisPass, and InvalidateAnalysisPass instantiate their raw_ostream formatting in every erased pass model. These methods are retained through pass-manager vtables even though pipeline printing is a diagnostic path.

Move the common formatting into two non-template functions in PassManager.cpp. Pass implementations still provide the class name at each call site, preserving pass-name mapping, require/invalidate spelling, and every pass-manager interface while reducing repeated generated code.

In the downstream LLVM 22 all-tool build, the multicall binary shrinks from 161,570,320 to 161,471,536 bytes (-98,784, -0.061%). The minimally stripped binary shrinks from 131,975,944 to 131,876,912 bytes (-99,032, -0.075%). Standalone opt shrinks from 84,127,760 to 84,045,504 bytes (-82,256, -0.098%).

All 41 command forms in llvm/test/Other/new-pm-print-pipeline.ll produce byte-identical stdout, stderr, and exit status. A paired O2 benchmark on large-gep-chain.ll changes CPU time by -0.392% with a 95% confidence interval of [-1.474%, +0.692%].

Work towards #202616

>From 7a768341ca2e55dbef4a15c1a0f7cfb541264a01 Mon Sep 17 00:00:00 2001
From: David Zbarsky <dzbarsky at gmail.com>
Date: Tue, 9 Jun 2026 08:06:23 -0400
Subject: [PATCH] [PassManager] Outline pipeline name printing

PassInfoMixin, RequireAnalysisPass, and InvalidateAnalysisPass instantiate their raw_ostream formatting in every erased pass model. These methods are retained through pass-manager vtables even though pipeline printing is a diagnostic path.

Move the common formatting into two non-template functions in PassManager.cpp. Pass implementations still provide the class name at each call site, preserving pass-name mapping, require/invalidate spelling, and every pass-manager interface while reducing repeated generated code.

In the downstream LLVM 22 all-tool build, the multicall binary shrinks from 161,570,320 to 161,471,536 bytes (-98,784, -0.061%). The minimally stripped binary shrinks from 131,975,944 to 131,876,912 bytes (-99,032, -0.075%). Standalone opt shrinks from 84,127,760 to 84,045,504 bytes (-82,256, -0.098%).

All 41 command forms in llvm/test/Other/new-pm-print-pipeline.ll produce byte-identical stdout, stderr, and exit status. A paired O2 benchmark on large-gep-chain.ll changes CPU time by -0.392% with a 95% confidence interval of [-1.474%, +0.692%].
---
 llvm/include/llvm/IR/PassManager.h | 23 ++++++++++++++---------
 llvm/lib/IR/PassManager.cpp        | 17 +++++++++++++++++
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index 22e02853bc567..fb4e7bbc5bf78 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -68,6 +68,15 @@ template <typename DerivedT> struct InfoMixin {
     return Name;
   }
 };
+
+LLVM_ABI void
+printPassPipelineName(raw_ostream &OS,
+                      function_ref<StringRef(StringRef)> MapClassName2PassName,
+                      StringRef ClassName);
+LLVM_ABI void printAnalysisPassPipelineName(
+    raw_ostream &OS,
+    function_ref<StringRef(StringRef)> MapClassName2PassName,
+    StringRef ClassName, bool IsInvalidate);
 } // namespace detail
 
 class Function;
@@ -89,9 +98,7 @@ template <typename DerivedT>
 struct PassInfoMixin : detail::InfoMixin<DerivedT> {
   void printPipeline(raw_ostream &OS,
                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
-    StringRef ClassName = DerivedT::name();
-    auto PassName = MapClassName2PassName(ClassName);
-    OS << PassName;
+    detail::printPassPipelineName(OS, MapClassName2PassName, DerivedT::name());
   }
 
   // TODO: remove once out of tree users are updated.
@@ -936,9 +943,8 @@ struct RequireAnalysisPass
   }
   void printPipeline(raw_ostream &OS,
                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
-    auto ClassName = AnalysisT::name();
-    auto PassName = MapClassName2PassName(ClassName);
-    OS << "require<" << PassName << '>';
+    detail::printAnalysisPassPipelineName(
+        OS, MapClassName2PassName, AnalysisT::name(), false);
   }
 };
 
@@ -961,9 +967,8 @@ struct InvalidateAnalysisPass
   }
   void printPipeline(raw_ostream &OS,
                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
-    auto ClassName = AnalysisT::name();
-    auto PassName = MapClassName2PassName(ClassName);
-    OS << "invalidate<" << PassName << '>';
+    detail::printAnalysisPassPipelineName(
+        OS, MapClassName2PassName, AnalysisT::name(), true);
   }
 };
 
diff --git a/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp
index af22b779ddbb0..8f614a0ca5f96 100644
--- a/llvm/lib/IR/PassManager.cpp
+++ b/llvm/lib/IR/PassManager.cpp
@@ -15,6 +15,23 @@
 using namespace llvm;
 
 namespace llvm {
+namespace detail {
+void printPassPipelineName(
+    raw_ostream &OS,
+    function_ref<StringRef(StringRef)> MapClassName2PassName,
+    StringRef ClassName) {
+  OS << MapClassName2PassName(ClassName);
+}
+
+void printAnalysisPassPipelineName(
+    raw_ostream &OS,
+    function_ref<StringRef(StringRef)> MapClassName2PassName,
+    StringRef ClassName, bool IsInvalidate) {
+  OS << (IsInvalidate ? "invalidate<" : "require<")
+     << MapClassName2PassName(ClassName) << '>';
+}
+} // namespace detail
+
 // Explicit template instantiations and specialization defininitions for core
 // template typedefs.
 template class LLVM_EXPORT_TEMPLATE AllAnalysesOn<Module>;



More information about the llvm-commits mailing list