Skip to content

[mlir] Allow statistics to be printed to a custom stream#190937

Open
malbecki wants to merge 1 commit into
llvm:mainfrom
malbecki:custom_stream_statistics_print
Open

[mlir] Allow statistics to be printed to a custom stream#190937
malbecki wants to merge 1 commit into
llvm:mainfrom
malbecki:custom_stream_statistics_print

Conversation

@malbecki
Copy link
Copy Markdown

@malbecki malbecki commented Apr 8, 2026

Add a dumpStatistics method to PassManager to allow compilers to print pass statistics without going through the --info-output-file CLI option. This allows compilers that do not parse CLI options to still be able to print statistics to custom stream.

Add a dumpStatistics method to PassManager to allow compilers to print
pass statistics without going through the --info-output-file CLI option.
This allows compilers that do not parse CLI options to still be able to
print statistics to custom stream.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 8, 2026

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added mlir:core MLIR Core Infrastructure mlir labels Apr 8, 2026
@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Apr 8, 2026

@llvm/pr-subscribers-mlir-core

Author: Mateusz Albecki (malbecki)

Changes

Add a dumpStatistics method to PassManager to allow compilers to print pass statistics without going through the --info-output-file CLI option. This allows compilers that do not parse CLI options to still be able to print statistics to custom stream.


Full diff: https://github.com/llvm/llvm-project/pull/190937.diff

3 Files Affected:

  • (modified) mlir/include/mlir/Pass/PassManager.h (+2)
  • (modified) mlir/lib/Pass/PassStatistics.cpp (+15-11)
  • (modified) mlir/unittests/Pass/PassManagerTest.cpp (+44)
diff --git a/mlir/include/mlir/Pass/PassManager.h b/mlir/include/mlir/Pass/PassManager.h
index 6e59b0f32ac6f..16f12d2dc16eb 100644
--- a/mlir/include/mlir/Pass/PassManager.h
+++ b/mlir/include/mlir/Pass/PassManager.h
@@ -463,6 +463,8 @@ class PassManager : public OpPassManager {
   void
   enableStatistics(PassDisplayMode displayMode = PassDisplayMode::Pipeline);
 
+  void dumpStatistics(raw_ostream &os, PassDisplayMode displayMode);
+
 private:
   /// Dump the statistics of the passes within this pass manager.
   void dumpStatistics();
diff --git a/mlir/lib/Pass/PassStatistics.cpp b/mlir/lib/Pass/PassStatistics.cpp
index 01191aa824440..3d271129ebfe6 100644
--- a/mlir/lib/Pass/PassStatistics.cpp
+++ b/mlir/lib/Pass/PassStatistics.cpp
@@ -138,27 +138,26 @@ static void printResultsAsPipeline(raw_ostream &os, OpPassManager &pm) {
 #endif
 }
 
-static void printStatistics(OpPassManager &pm, PassDisplayMode displayMode) {
-  auto os = llvm::CreateInfoOutputFile();
-
+static void printStatistics(OpPassManager &pm, raw_ostream &os,
+                            PassDisplayMode displayMode) {
   // Print the stats header.
-  *os << "===" << std::string(73, '-') << "===\n";
+  os << "===" << std::string(73, '-') << "===\n";
   // Figure out how many spaces for the description name.
   unsigned padding = (80 - kPassStatsDescription.size()) / 2;
-  os->indent(padding) << kPassStatsDescription << '\n';
-  *os << "===" << std::string(73, '-') << "===\n";
+  os.indent(padding) << kPassStatsDescription << '\n';
+  os << "===" << std::string(73, '-') << "===\n";
 
   // Defer to a specialized printer for each display mode.
   switch (displayMode) {
   case PassDisplayMode::List:
-    printResultsAsList(*os, pm);
+    printResultsAsList(os, pm);
     break;
   case PassDisplayMode::Pipeline:
-    printResultsAsPipeline(*os, pm);
+    printResultsAsPipeline(os, pm);
     break;
   }
-  *os << "\n";
-  os->flush();
+  os << "\n";
+  os.flush();
 }
 
 //===----------------------------------------------------------------------===//
@@ -242,8 +241,13 @@ static void prepareStatistics(OpPassManager &pm) {
 
 /// Dump the statistics of the passes within this pass manager.
 void PassManager::dumpStatistics() {
+  auto os = llvm::CreateInfoOutputFile();
+  dumpStatistics(*os, passStatisticsMode.value());
+}
+
+void PassManager::dumpStatistics(raw_ostream &os, PassDisplayMode displayMode) {
   prepareStatistics(*this);
-  printStatistics(*this, *passStatisticsMode);
+  printStatistics(*this, os, displayMode);
 }
 
 /// Dump the statistics for each pass after running.
diff --git a/mlir/unittests/Pass/PassManagerTest.cpp b/mlir/unittests/Pass/PassManagerTest.cpp
index 3f5db8ebcbb6d..ea6ecc1759ad8 100644
--- a/mlir/unittests/Pass/PassManagerTest.cpp
+++ b/mlir/unittests/Pass/PassManagerTest.cpp
@@ -380,4 +380,48 @@ TEST(PassManagerTest, PassInitialization) {
   EXPECT_TRUE(succeeded(pm.run(module.get())));
 }
 
+struct IncrementStatisticsPass
+    : public PassWrapper<IncrementStatisticsPass, OperationPass<ModuleOp>> {
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(IncrementStatisticsPass)
+
+  IncrementStatisticsPass() {};
+  IncrementStatisticsPass(const IncrementStatisticsPass &other) {}
+
+  void runOnOperation() override {
+    testStat1++;
+    testStat2 += 5;
+    testStat3 = 10;
+  }
+
+  std::unique_ptr<mlir::Pass> clonePass() const override {
+    return std::make_unique<IncrementStatisticsPass>();
+  }
+
+private:
+  Pass::Statistic testStat1{this, "test-stat-1", "Test1"};
+  Pass::Statistic testStat2{this, "test-stat-2", "Test2"};
+  Pass::Statistic testStat3{this, "test-stat-3", "Test3"};
+};
+
+TEST(PassManagerTest, StatisticsPrint) {
+  MLIRContext context;
+  context.allowUnregisteredDialects();
+
+  OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
+
+  auto pm = PassManager::on<ModuleOp>(&context);
+  pm.addPass(std::make_unique<IncrementStatisticsPass>());
+  LogicalResult result = pm.run(module.get());
+  EXPECT_TRUE(succeeded(result));
+
+  std::string statistics;
+  llvm::raw_string_ostream os(statistics);
+
+  pm.dumpStatistics(os, PassDisplayMode::List);
+
+  EXPECT_NE(statistics.find("1 test-stat-1"), std::string::npos);
+  EXPECT_NE(statistics.find("5 test-stat-2"), std::string::npos);
+  EXPECT_NE(statistics.find("10 test-stat-3"), std::string::npos);
+}
+
 } // namespace

@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Apr 8, 2026

@llvm/pr-subscribers-mlir

Author: Mateusz Albecki (malbecki)

Changes

Add a dumpStatistics method to PassManager to allow compilers to print pass statistics without going through the --info-output-file CLI option. This allows compilers that do not parse CLI options to still be able to print statistics to custom stream.


Full diff: https://github.com/llvm/llvm-project/pull/190937.diff

3 Files Affected:

  • (modified) mlir/include/mlir/Pass/PassManager.h (+2)
  • (modified) mlir/lib/Pass/PassStatistics.cpp (+15-11)
  • (modified) mlir/unittests/Pass/PassManagerTest.cpp (+44)
diff --git a/mlir/include/mlir/Pass/PassManager.h b/mlir/include/mlir/Pass/PassManager.h
index 6e59b0f32ac6f..16f12d2dc16eb 100644
--- a/mlir/include/mlir/Pass/PassManager.h
+++ b/mlir/include/mlir/Pass/PassManager.h
@@ -463,6 +463,8 @@ class PassManager : public OpPassManager {
   void
   enableStatistics(PassDisplayMode displayMode = PassDisplayMode::Pipeline);
 
+  void dumpStatistics(raw_ostream &os, PassDisplayMode displayMode);
+
 private:
   /// Dump the statistics of the passes within this pass manager.
   void dumpStatistics();
diff --git a/mlir/lib/Pass/PassStatistics.cpp b/mlir/lib/Pass/PassStatistics.cpp
index 01191aa824440..3d271129ebfe6 100644
--- a/mlir/lib/Pass/PassStatistics.cpp
+++ b/mlir/lib/Pass/PassStatistics.cpp
@@ -138,27 +138,26 @@ static void printResultsAsPipeline(raw_ostream &os, OpPassManager &pm) {
 #endif
 }
 
-static void printStatistics(OpPassManager &pm, PassDisplayMode displayMode) {
-  auto os = llvm::CreateInfoOutputFile();
-
+static void printStatistics(OpPassManager &pm, raw_ostream &os,
+                            PassDisplayMode displayMode) {
   // Print the stats header.
-  *os << "===" << std::string(73, '-') << "===\n";
+  os << "===" << std::string(73, '-') << "===\n";
   // Figure out how many spaces for the description name.
   unsigned padding = (80 - kPassStatsDescription.size()) / 2;
-  os->indent(padding) << kPassStatsDescription << '\n';
-  *os << "===" << std::string(73, '-') << "===\n";
+  os.indent(padding) << kPassStatsDescription << '\n';
+  os << "===" << std::string(73, '-') << "===\n";
 
   // Defer to a specialized printer for each display mode.
   switch (displayMode) {
   case PassDisplayMode::List:
-    printResultsAsList(*os, pm);
+    printResultsAsList(os, pm);
     break;
   case PassDisplayMode::Pipeline:
-    printResultsAsPipeline(*os, pm);
+    printResultsAsPipeline(os, pm);
     break;
   }
-  *os << "\n";
-  os->flush();
+  os << "\n";
+  os.flush();
 }
 
 //===----------------------------------------------------------------------===//
@@ -242,8 +241,13 @@ static void prepareStatistics(OpPassManager &pm) {
 
 /// Dump the statistics of the passes within this pass manager.
 void PassManager::dumpStatistics() {
+  auto os = llvm::CreateInfoOutputFile();
+  dumpStatistics(*os, passStatisticsMode.value());
+}
+
+void PassManager::dumpStatistics(raw_ostream &os, PassDisplayMode displayMode) {
   prepareStatistics(*this);
-  printStatistics(*this, *passStatisticsMode);
+  printStatistics(*this, os, displayMode);
 }
 
 /// Dump the statistics for each pass after running.
diff --git a/mlir/unittests/Pass/PassManagerTest.cpp b/mlir/unittests/Pass/PassManagerTest.cpp
index 3f5db8ebcbb6d..ea6ecc1759ad8 100644
--- a/mlir/unittests/Pass/PassManagerTest.cpp
+++ b/mlir/unittests/Pass/PassManagerTest.cpp
@@ -380,4 +380,48 @@ TEST(PassManagerTest, PassInitialization) {
   EXPECT_TRUE(succeeded(pm.run(module.get())));
 }
 
+struct IncrementStatisticsPass
+    : public PassWrapper<IncrementStatisticsPass, OperationPass<ModuleOp>> {
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(IncrementStatisticsPass)
+
+  IncrementStatisticsPass() {};
+  IncrementStatisticsPass(const IncrementStatisticsPass &other) {}
+
+  void runOnOperation() override {
+    testStat1++;
+    testStat2 += 5;
+    testStat3 = 10;
+  }
+
+  std::unique_ptr<mlir::Pass> clonePass() const override {
+    return std::make_unique<IncrementStatisticsPass>();
+  }
+
+private:
+  Pass::Statistic testStat1{this, "test-stat-1", "Test1"};
+  Pass::Statistic testStat2{this, "test-stat-2", "Test2"};
+  Pass::Statistic testStat3{this, "test-stat-3", "Test3"};
+};
+
+TEST(PassManagerTest, StatisticsPrint) {
+  MLIRContext context;
+  context.allowUnregisteredDialects();
+
+  OwningOpRef<ModuleOp> module(ModuleOp::create(UnknownLoc::get(&context)));
+
+  auto pm = PassManager::on<ModuleOp>(&context);
+  pm.addPass(std::make_unique<IncrementStatisticsPass>());
+  LogicalResult result = pm.run(module.get());
+  EXPECT_TRUE(succeeded(result));
+
+  std::string statistics;
+  llvm::raw_string_ostream os(statistics);
+
+  pm.dumpStatistics(os, PassDisplayMode::List);
+
+  EXPECT_NE(statistics.find("1 test-stat-1"), std::string::npos);
+  EXPECT_NE(statistics.find("5 test-stat-2"), std::string::npos);
+  EXPECT_NE(statistics.find("10 test-stat-3"), std::string::npos);
+}
+
 } // namespace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mlir:core MLIR Core Infrastructure mlir

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants