[Mlir-commits] [mlir] Pretty print on -dump-pass-pipeline (PR #143223)

Jeremy Kun llvmlistbot at llvm.org
Fri Jun 6 19:53:21 PDT 2025


https://github.com/j2kun updated https://github.com/llvm/llvm-project/pull/143223

>From 8604bf62da04f5a79c6ff220ae45316a22d08cb7 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 6 Jun 2025 18:29:22 -0700
Subject: [PATCH 1/3] Pretty print on -dump-pass-pipeline

---
 mlir/lib/Pass/Pass.cpp | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp
index e0e9b5f54042a..6e8d3bbfdff81 100644
--- a/mlir/lib/Pass/Pass.cpp
+++ b/mlir/lib/Pass/Pass.cpp
@@ -18,6 +18,7 @@
 #include "mlir/IR/Threading.h"
 #include "mlir/IR/Verifier.h"
 #include "mlir/Support/FileUtilities.h"
+#include "mlir/Support/IndentedOstream.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
@@ -392,18 +393,28 @@ StringRef OpPassManager::getOpAnchorName() const {
 /// Prints out the passes of the pass manager as the textual representation
 /// of pipelines.
 void printAsTextualPipeline(
-    raw_ostream &os, StringRef anchorName,
+    raw_indented_ostream &os, StringRef anchorName,
     const llvm::iterator_range<OpPassManager::pass_iterator> &passes) {
-  os << anchorName << "(";
+  os << anchorName << "(\n";
+  os.indent();
   llvm::interleave(
       passes, [&](mlir::Pass &pass) { pass.printAsTextualPipeline(os); },
-      [&]() { os << ","; });
+      [&]() { os << ",\n"; });
+  os << "\n";
+  os.unindent();
   os << ")";
 }
+void printAsTextualPipeline(
+    raw_ostream &os, StringRef anchorName,
+    const llvm::iterator_range<OpPassManager::pass_iterator> &passes) {
+  raw_indented_ostream indentedOS(os);
+  printAsTextualPipeline(indentedOS, anchorName, passes);
+}
 void OpPassManager::printAsTextualPipeline(raw_ostream &os) const {
   StringRef anchorName = getOpAnchorName();
+  raw_indented_ostream indentedOS(os);
   ::printAsTextualPipeline(
-      os, anchorName,
+      indentedOS, anchorName,
       {MutableArrayRef<std::unique_ptr<Pass>>{impl->passes}.begin(),
        MutableArrayRef<std::unique_ptr<Pass>>{impl->passes}.end()});
 }

>From 3b0e3dd81bed6ee8253a6aa42dc918bdc1c9af91 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 6 Jun 2025 19:03:02 -0700
Subject: [PATCH 2/3] add a pretty option and fix most tests

---
 mlir/include/mlir/Pass/Pass.h                 |  2 +-
 mlir/include/mlir/Pass/PassManager.h          |  2 +-
 mlir/lib/Pass/Pass.cpp                        | 37 ++++++++++++-------
 mlir/test/Pass/pipeline-parsing.mlir          |  4 +-
 mlir/test/Pass/run-reproducer.mlir            |  4 +-
 mlir/test/Transforms/composite-pass.mlir      |  5 ++-
 .../inlining-dump-default-pipeline.mlir       |  4 +-
 7 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/mlir/include/mlir/Pass/Pass.h b/mlir/include/mlir/Pass/Pass.h
index 9e8ba7158f1b3..3f0a838f2447f 100644
--- a/mlir/include/mlir/Pass/Pass.h
+++ b/mlir/include/mlir/Pass/Pass.h
@@ -119,7 +119,7 @@ class Pass {
 
   /// Prints out the pass in the textual representation of pipelines. If this is
   /// an adaptor pass, print its pass managers.
-  void printAsTextualPipeline(raw_ostream &os);
+  void printAsTextualPipeline(raw_ostream &os, bool pretty = false);
 
   //===--------------------------------------------------------------------===//
   // Statistics
diff --git a/mlir/include/mlir/Pass/PassManager.h b/mlir/include/mlir/Pass/PassManager.h
index 2287b0a33f47d..ec2207c278cdd 100644
--- a/mlir/include/mlir/Pass/PassManager.h
+++ b/mlir/include/mlir/Pass/PassManager.h
@@ -143,7 +143,7 @@ class OpPassManager {
   /// of pipelines.
   /// Note: The quality of the string representation depends entirely on the
   /// the correctness of per-pass overrides of Pass::printAsTextualPipeline.
-  void printAsTextualPipeline(raw_ostream &os) const;
+  void printAsTextualPipeline(raw_ostream &os, bool pretty = false) const;
 
   /// Raw dump of the pass manager to llvm::errs().
   void dump();
diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp
index 6e8d3bbfdff81..d34a4726cad26 100644
--- a/mlir/lib/Pass/Pass.cpp
+++ b/mlir/lib/Pass/Pass.cpp
@@ -82,12 +82,12 @@ void Pass::copyOptionValuesFrom(const Pass *other) {
 
 /// Prints out the pass in the textual representation of pipelines. If this is
 /// an adaptor pass, print its pass managers.
-void Pass::printAsTextualPipeline(raw_ostream &os) {
+void Pass::printAsTextualPipeline(raw_ostream &os, bool pretty) {
   // Special case for adaptors to print its pass managers.
   if (auto *adaptor = dyn_cast<OpToOpPassAdaptor>(this)) {
     llvm::interleave(
         adaptor->getPassManagers(),
-        [&](OpPassManager &pm) { pm.printAsTextualPipeline(os); },
+        [&](OpPassManager &pm) { pm.printAsTextualPipeline(os, pretty); },
         [&] { os << ","; });
     return;
   }
@@ -394,14 +394,24 @@ StringRef OpPassManager::getOpAnchorName() const {
 /// of pipelines.
 void printAsTextualPipeline(
     raw_indented_ostream &os, StringRef anchorName,
-    const llvm::iterator_range<OpPassManager::pass_iterator> &passes) {
-  os << anchorName << "(\n";
-  os.indent();
+    const llvm::iterator_range<OpPassManager::pass_iterator> &passes,
+    bool pretty = false) {
+  os << anchorName << "(";
+  if (pretty) {
+    os << "\n";
+    os.indent();
+  }
   llvm::interleave(
       passes, [&](mlir::Pass &pass) { pass.printAsTextualPipeline(os); },
-      [&]() { os << ",\n"; });
-  os << "\n";
-  os.unindent();
+      [&]() {
+        os << ",";
+        if (pretty)
+          os << "\n";
+      });
+  if (pretty) {
+    os << "\n";
+    os.unindent();
+  }
   os << ")";
 }
 void printAsTextualPipeline(
@@ -410,18 +420,19 @@ void printAsTextualPipeline(
   raw_indented_ostream indentedOS(os);
   printAsTextualPipeline(indentedOS, anchorName, passes);
 }
-void OpPassManager::printAsTextualPipeline(raw_ostream &os) const {
+void OpPassManager::printAsTextualPipeline(raw_ostream &os, bool pretty) const {
   StringRef anchorName = getOpAnchorName();
   raw_indented_ostream indentedOS(os);
   ::printAsTextualPipeline(
       indentedOS, anchorName,
       {MutableArrayRef<std::unique_ptr<Pass>>{impl->passes}.begin(),
-       MutableArrayRef<std::unique_ptr<Pass>>{impl->passes}.end()});
+       MutableArrayRef<std::unique_ptr<Pass>>{impl->passes}.end()},
+      pretty);
 }
 
 void OpPassManager::dump() {
   llvm::errs() << "Pass Manager with " << impl->passes.size() << " passes:\n";
-  printAsTextualPipeline(llvm::errs());
+  printAsTextualPipeline(llvm::errs(), /*pretty=*/true);
   llvm::errs() << "\n";
 }
 
@@ -477,7 +488,6 @@ llvm::hash_code OpPassManager::hash() {
   return hashCode;
 }
 
-
 //===----------------------------------------------------------------------===//
 // OpToOpPassAdaptor
 //===----------------------------------------------------------------------===//
@@ -882,7 +892,8 @@ LogicalResult PassManager::run(Operation *op) {
   // Initialize all of the passes within the pass manager with a new generation.
   llvm::hash_code newInitKey = context->getRegistryHash();
   llvm::hash_code pipelineKey = hash();
-  if (newInitKey != initializationKey || pipelineKey != pipelineInitializationKey) {
+  if (newInitKey != initializationKey ||
+      pipelineKey != pipelineInitializationKey) {
     if (failed(initialize(context, impl->initializationGeneration + 1)))
       return failure();
     initializationKey = newInitKey;
diff --git a/mlir/test/Pass/pipeline-parsing.mlir b/mlir/test/Pass/pipeline-parsing.mlir
index f41553d2669f0..7f368c6df2af5 100644
--- a/mlir/test/Pass/pipeline-parsing.mlir
+++ b/mlir/test/Pass/pipeline-parsing.mlir
@@ -21,7 +21,9 @@
 // CHECK_ERROR_7: can't run 'wrong-op' pass manager on 'builtin.module' op
 
 // RUN: mlir-opt %s -pass-pipeline='any(cse)' -dump-pass-pipeline 2>&1 | FileCheck %s -check-prefix=CHECK_ROUNDTRIP
-// CHECK_ROUNDTRIP: any(cse)
+// CHECK_ROUNDTRIP: any(
+// CHECK_ROUNDTRIP-NEXT: cse
+// CHECK_ROUNDTRIP-NEXT: )
 
 func.func @foo() {
   return
diff --git a/mlir/test/Pass/run-reproducer.mlir b/mlir/test/Pass/run-reproducer.mlir
index bf3ab2dae2ff8..5e455cb30a66c 100644
--- a/mlir/test/Pass/run-reproducer.mlir
+++ b/mlir/test/Pass/run-reproducer.mlir
@@ -14,7 +14,9 @@ func.func @bar() {
   external_resources: {
     mlir_reproducer: {
       verify_each: true,
-      // CHECK:  builtin.module(func.func(cse,canonicalize{ max-iterations=1 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=false}))
+      // CHECK:       builtin.module(
+      // CHECK-NEXT:    func.func(cse,canonicalize{ max-iterations=1 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=false})
+      // CHECK-NEXT:  )
       pipeline: "builtin.module(func.func(cse,canonicalize{max-iterations=1 max-num-rewrites=-1 region-simplify=normal top-down=false}))",
       disable_threading: true
     }
diff --git a/mlir/test/Transforms/composite-pass.mlir b/mlir/test/Transforms/composite-pass.mlir
index 75587edd5b96d..65764a96a4016 100644
--- a/mlir/test/Transforms/composite-pass.mlir
+++ b/mlir/test/Transforms/composite-pass.mlir
@@ -2,8 +2,9 @@
 // RUN: mlir-opt %s --log-actions-to=- --composite-fixed-point-pass='name=TestCompositePass pipeline=any(canonicalize,cse)' -split-input-file | FileCheck %s
 
 // Ensure the composite pass correctly prints its options.
-// PIPELINE:      builtin.module(composite-fixed-point-pass{max-iterations=10 name=TestCompositePass
-// PIPELINE-SAME: pipeline=canonicalize{ max-iterations=10 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=true},cse})
+// PIPELINE:      builtin.module(
+// PIPELINE-NEXT:    composite-fixed-point-pass{max-iterations=10 name=TestCompositePass
+// PIPELINE-SAME: pipeline=canonicalize{ max-iterations=10 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=true},cse}
 
 // CHECK-LABEL: running `TestCompositePass`
 //       CHECK: running `Canonicalizer`
diff --git a/mlir/test/Transforms/inlining-dump-default-pipeline.mlir b/mlir/test/Transforms/inlining-dump-default-pipeline.mlir
index 4f8638054206e..ef5fac49c6ce2 100644
--- a/mlir/test/Transforms/inlining-dump-default-pipeline.mlir
+++ b/mlir/test/Transforms/inlining-dump-default-pipeline.mlir
@@ -1,2 +1,4 @@
 // RUN: mlir-opt %s -pass-pipeline="builtin.module(inline)" -dump-pass-pipeline 2>&1 | FileCheck %s
-// CHECK: builtin.module(inline{default-pipeline=canonicalize inlining-threshold=4294967295 max-iterations=4 })
+// CHECK:      builtin.module(
+// CHECK-NEXT:   inline{default-pipeline=canonicalize inlining-threshold=4294967295 max-iterations=4 }
+// CHECK-NEXT: )

>From 6821a6ed1593deed1696f3c6691081aaa988385c Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 6 Jun 2025 19:53:10 -0700
Subject: [PATCH 3/3] fix tests

---
 mlir/lib/Pass/Pass.cpp                       | 12 ++--
 mlir/lib/Pass/PassCrashRecovery.cpp          |  3 +-
 mlir/test/Pass/pipeline-options-parsing.mlir | 76 +++++++++++++++++---
 mlir/test/Pass/run-reproducer.mlir           |  5 +-
 4 files changed, 82 insertions(+), 14 deletions(-)

diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp
index d34a4726cad26..66f8fc4d0234d 100644
--- a/mlir/lib/Pass/Pass.cpp
+++ b/mlir/lib/Pass/Pass.cpp
@@ -88,7 +88,11 @@ void Pass::printAsTextualPipeline(raw_ostream &os, bool pretty) {
     llvm::interleave(
         adaptor->getPassManagers(),
         [&](OpPassManager &pm) { pm.printAsTextualPipeline(os, pretty); },
-        [&] { os << ","; });
+        [&] {
+          os << ",";
+          if (pretty)
+            os << "\n";
+        });
     return;
   }
   // Otherwise, print the pass argument followed by its options. If the pass
@@ -402,7 +406,7 @@ void printAsTextualPipeline(
     os.indent();
   }
   llvm::interleave(
-      passes, [&](mlir::Pass &pass) { pass.printAsTextualPipeline(os); },
+      passes, [&](mlir::Pass &pass) { pass.printAsTextualPipeline(os, pretty); },
       [&]() {
         os << ",";
         if (pretty)
@@ -416,9 +420,9 @@ void printAsTextualPipeline(
 }
 void printAsTextualPipeline(
     raw_ostream &os, StringRef anchorName,
-    const llvm::iterator_range<OpPassManager::pass_iterator> &passes) {
+    const llvm::iterator_range<OpPassManager::pass_iterator> &passes, bool pretty) {
   raw_indented_ostream indentedOS(os);
-  printAsTextualPipeline(indentedOS, anchorName, passes);
+  printAsTextualPipeline(indentedOS, anchorName, passes, pretty);
 }
 void OpPassManager::printAsTextualPipeline(raw_ostream &os, bool pretty) const {
   StringRef anchorName = getOpAnchorName();
diff --git a/mlir/lib/Pass/PassCrashRecovery.cpp b/mlir/lib/Pass/PassCrashRecovery.cpp
index 8c6d865cb31dd..b048ff9462392 100644
--- a/mlir/lib/Pass/PassCrashRecovery.cpp
+++ b/mlir/lib/Pass/PassCrashRecovery.cpp
@@ -443,7 +443,8 @@ makeReproducerStreamFactory(StringRef outputFile) {
 
 void printAsTextualPipeline(
     raw_ostream &os, StringRef anchorName,
-    const llvm::iterator_range<OpPassManager::pass_iterator> &passes);
+    const llvm::iterator_range<OpPassManager::pass_iterator> &passes,
+    bool pretty = false);
 
 std::string mlir::makeReproducer(
     StringRef anchorName,
diff --git a/mlir/test/Pass/pipeline-options-parsing.mlir b/mlir/test/Pass/pipeline-options-parsing.mlir
index b8cd605a83a2b..9385d353faf95 100644
--- a/mlir/test/Pass/pipeline-options-parsing.mlir
+++ b/mlir/test/Pass/pipeline-options-parsing.mlir
@@ -38,11 +38,71 @@
 
 // CHECK_1: test-options-pass{enum=zero list={1,2,3,4,5} string=nested_pipeline{arg1=10 arg2=" {} " arg3=true} string-list={a,b,c,d}}
 // CHECK_2: test-options-pass{enum=one list={1} string= string-list={a,b}}
-// CHECK_3: builtin.module(builtin.module(func.func(test-options-pass{enum=zero list={3} string= }),func.func(test-options-pass{enum=one list={1,2,3,4} string= })))
-// CHECK_4: builtin.module(builtin.module(func.func(test-options-pass{enum=zero list={3} string= }),func.func(test-options-pass{enum=one list={1,2,3,4} string=foobar })))
-// CHECK_5: builtin.module(builtin.module(func.func(test-options-pass{enum=zero list={3} string= }),func.func(test-options-pass{enum=one list={1,2,3,4} string={foo bar baz} })))
-// CHECK_6: builtin.module(builtin.module(func.func(test-options-pass{enum=zero list={3} string= }),func.func(test-options-pass{enum=one list={1,2,3,4} string=foo"bar"baz })))
-// CHECK_7{LITERAL}: builtin.module(func.func(test-options-super-pass{list={{enum=zero list={1} string=foo },{enum=one list={2} string=bar },{enum=two list={3} string=baz }}}))
-// CHECK_8{LITERAL}: builtin.module(func.func(test-options-super-pass{list={{enum=zero list={1} string=foo },{enum=one string=bar }}}))
-// CHECK_9: builtin.module(func.func(test-options-pass{enum=zero  string= string-list={}}))
-// CHECK_10: builtin.module(func.func(test-options-pass{enum=zero  string= string-list={,}}))
+
+// CHECK_3:      builtin.module(
+// CHECK_3-NEXT:   builtin.module(
+// CHECK_3-NEXT:     func.func(
+// CHECK_3-NEXT:       test-options-pass{enum=zero list={3} string= }
+// CHECK_3-NEXT:     ),
+// CHECK_3-NEXT:     func.func(
+// CHECK_3-NEXT:       test-options-pass{enum=one list={1,2,3,4} string= }
+// CHECK_3-NEXT:     )
+// CHECK_3-NEXT:   )
+// CHECK_3-NEXT: )
+
+// CHECK_4:      builtin.module(
+// CHECK_4-NEXT:   builtin.module(
+// CHECK_4-NEXT:     func.func(
+// CHECK_4-NEXT:       test-options-pass{enum=zero list={3} string= }
+// CHECK_4-NEXT:     ),
+// CHECK_4-NEXT:     func.func(
+// CHECK_4-NEXT:       test-options-pass{enum=one list={1,2,3,4} string=foobar }
+// CHECK_4-NEXT:     )
+// CHECK_4-NEXT:   )
+// CHECK_4-NEXT: )
+
+// CHECK_5:      builtin.module(
+// CHECK_5-NEXT:   builtin.module(
+// CHECK_5-NEXT:     func.func(
+// CHECK_5-NEXT:       test-options-pass{enum=zero list={3} string= }
+// CHECK_5-NEXT:     ),
+// CHECK_5-NEXT:     func.func(
+// CHECK_5-NEXT:       test-options-pass{enum=one list={1,2,3,4} string={foo bar baz} }
+// CHECK_5-NEXT:     )
+// CHECK_5-NEXT:   )
+// CHECK_5-NEXT: )
+
+// CHECK_6:      builtin.module(
+// CHECK_6-NEXT:   builtin.module(
+// CHECK_6-NEXT:     func.func(
+// CHECK_6-NEXT:       test-options-pass{enum=zero list={3} string= }
+// CHECK_6-NEXT:     ),
+// CHECK_6-NEXT:     func.func(
+// CHECK_6-NEXT:       test-options-pass{enum=one list={1,2,3,4} string=foo"bar"baz }
+// CHECK_6-NEXT:     )
+// CHECK_6-NEXT:   )
+// CHECK_6-NEXT: )
+
+// CHECK_7{LITERAL}:      builtin.module(
+// CHECK_7{LITERAL}-NEXT:   func.func(
+// CHECK_7{LITERAL}-NEXT:     test-options-super-pass{list={{enum=zero list={1} string=foo },{enum=one list={2} string=bar },{enum=two list={3} string=baz }}}
+// CHECK_7{LITERAL}-NEXT:   )
+// CHECK_7{LITERAL}-NEXT: )
+
+// CHECK_8{LITERAL}:      builtin.module(
+// CHECK_8{LITERAL}-NEXT:   func.func(
+// CHECK_8{LITERAL}-NEXT:     test-options-super-pass{list={{enum=zero list={1} string=foo },{enum=one string=bar }}}
+// CHECK_8{LITERAL}-NEXT:   )
+// CHECK_8{LITERAL}-NEXT: )
+
+// CHECK_9:      builtin.module(
+// CHECK_9-NEXT:   func.func(
+// CHECK_9-NEXT:     test-options-pass{enum=zero  string= string-list={}}
+// CHECK_9-NEXT:   )
+// CHECK_9-NEXT: )
+
+// CHECK_10:      builtin.module(
+// CHECK_10-NEXT:   func.func(
+// CHECK_10-NEXT:     test-options-pass{enum=zero  string= string-list={,}}
+// CHECK_10-NEXT:   )
+// CHECK_10-NEXT: )
diff --git a/mlir/test/Pass/run-reproducer.mlir b/mlir/test/Pass/run-reproducer.mlir
index 5e455cb30a66c..d2daceab163de 100644
--- a/mlir/test/Pass/run-reproducer.mlir
+++ b/mlir/test/Pass/run-reproducer.mlir
@@ -15,7 +15,10 @@ func.func @bar() {
     mlir_reproducer: {
       verify_each: true,
       // CHECK:       builtin.module(
-      // CHECK-NEXT:    func.func(cse,canonicalize{ max-iterations=1 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=false})
+      // CHECK-NEXT:    func.func(
+      // CHECK-NEXT:      cse,
+      // CHECK-NEXT:      canonicalize{ max-iterations=1 max-num-rewrites=-1 region-simplify=normal test-convergence=false top-down=false}
+      // CHECK-NEXT:    )
       // CHECK-NEXT:  )
       pipeline: "builtin.module(func.func(cse,canonicalize{max-iterations=1 max-num-rewrites=-1 region-simplify=normal top-down=false}))",
       disable_threading: true



More information about the Mlir-commits mailing list