[Mlir-commits] [mlir] [MLIR] Add remark flags to mlir-opt (PR #156825)

Guray Ozen llvmlistbot at llvm.org
Mon Sep 8 07:24:01 PDT 2025


https://github.com/grypp updated https://github.com/llvm/llvm-project/pull/156825

>From a3e2893fd9dc72f0bfabd5be414c2b666367787b Mon Sep 17 00:00:00 2001
From: Guray Ozen <gozen at nvidia.com>
Date: Thu, 4 Sep 2025 10:26:33 +0200
Subject: [PATCH 1/6] [MLIR] Add remark flags to mlir-opt

---
 .../include/mlir/Tools/mlir-opt/MlirOptMain.h | 22 +++++
 mlir/lib/Tools/mlir-opt/CMakeLists.txt        |  1 +
 mlir/lib/Tools/mlir-opt/MlirOptMain.cpp       | 88 +++++++++++++++++--
 mlir/unittests/IR/CMakeLists.txt              |  2 +-
 4 files changed, 103 insertions(+), 10 deletions(-)

diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
index 94231227599c9..dc6a6a1c3cc42 100644
--- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
+++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
@@ -38,6 +38,12 @@ enum class VerbosityLevel {
   ErrorsWarningsAndRemarks
 };
 
+using RemarkFormat = enum {
+  REMARK_FORMAT_STDOUT,
+  REMARK_FORMAT_YAML,
+  REMARK_FORMAT_BITSTREAM,
+};
+
 /// Configuration options for the mlir-opt tool.
 /// This is intended to help building tools like mlir-opt by collecting the
 /// supported options.
@@ -221,9 +227,25 @@ class MlirOptMainConfig {
   }
   bool shouldVerifyRoundtrip() const { return verifyRoundtripFlag; }
 
+  /// Checks if any remark filters are set.
+  bool shouldEmitRemarks() const {
+    // Emit all remarks only when no filters are specified.
+    const bool hasFilters =
+        !remarksPassedFlag.empty() || !remarksFailedFlag.empty() ||
+        !remarksMissedFlag.empty() || !remarksAnalyseFlag.empty();
+    return hasFilters;
+  }
+
   /// Reproducer file generation (no crash required).
   StringRef getReproducerFilename() const { return generateReproducerFileFlag; }
 
+  /// Remark options
+  RemarkFormat remarkFormatFlag;
+  std::string remarksPassedFlag = "";
+  std::string remarksFailedFlag = "";
+  std::string remarksMissedFlag = "";
+  std::string remarksAnalyseFlag = "";
+
 protected:
   /// Allow operation with no registered dialects.
   /// This option is for convenience during testing only and discouraged in
diff --git a/mlir/lib/Tools/mlir-opt/CMakeLists.txt b/mlir/lib/Tools/mlir-opt/CMakeLists.txt
index f24d4c60174ee..858c9c1f97f9c 100644
--- a/mlir/lib/Tools/mlir-opt/CMakeLists.txt
+++ b/mlir/lib/Tools/mlir-opt/CMakeLists.txt
@@ -13,4 +13,5 @@ add_mlir_library(MLIROptLib
   MLIRPluginsLib
   MLIRSupport
   MLIRIRDL
+  MLIRRemarkStreamer
   )
diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
index de714d8b740af..c456540cc1793 100644
--- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
+++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
@@ -23,9 +23,11 @@
 #include "mlir/IR/Diagnostics.h"
 #include "mlir/IR/Location.h"
 #include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/Remarks.h"
 #include "mlir/Parser/Parser.h"
 #include "mlir/Pass/PassManager.h"
 #include "mlir/Pass/PassRegistry.h"
+#include "mlir/Remark/RemarkStreamer.h"
 #include "mlir/Support/FileUtilities.h"
 #include "mlir/Support/Timing.h"
 #include "mlir/Support/ToolUtilities.h"
@@ -33,6 +35,7 @@
 #include "mlir/Tools/Plugins/DialectPlugin.h"
 #include "mlir/Tools/Plugins/PassPlugin.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Remarks/RemarkFormat.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LogicalResult.h"
@@ -204,6 +207,41 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig {
             cl::location(generateReproducerFileFlag), cl::init(""),
             cl::value_desc("filename"));
 
+    static cl::OptionCategory remarkCategory(
+        "Remark Options",
+        "Filter remarks by regular expression (llvm::Regex syntax).");
+
+    static llvm::cl::opt<RemarkFormat, /*ExternalStorage=*/true> remarkFormat{
+        "remark-format",
+        llvm::cl::desc("Specify the format for remark output."),
+        cl::location(remarkFormatFlag),
+        llvm::cl::value_desc("format"),
+        llvm::cl::init(REMARK_FORMAT_STDOUT),
+        llvm::cl::values(
+            clEnumValN(REMARK_FORMAT_STDOUT, "emitRemark",
+                       "Print as emitRemark to command-line"),
+            clEnumValN(REMARK_FORMAT_YAML, "yaml", "Print yaml file"),
+            clEnumValN(REMARK_FORMAT_BITSTREAM, "bitstream",
+                       "Print bitstream file")),
+        llvm::cl::cat(remarkCategory)};
+
+    static cl::opt<std::string, /*ExternalStorage=*/true> remarksPassed(
+        "remarks-passed", cl::desc("Show passed remarks"),
+        cl::location(remarksPassedFlag), cl::init(""), cl::cat(remarkCategory));
+
+    static cl::opt<std::string, /*ExternalStorage=*/true> remarksFailed(
+        "remarks-failed", cl::desc("Show failed remarks"),
+        cl::location(remarksFailedFlag), cl::init(""), cl::cat(remarkCategory));
+
+    static cl::opt<std::string, /*ExternalStorage=*/true> remarksMissed(
+        "remarks-missed", cl::desc("Show missed remarks"),
+        cl::location(remarksMissedFlag), cl::init(""), cl::cat(remarkCategory));
+
+    static cl::opt<std::string, /*ExternalStorage=*/true> remarksAnalyse(
+        "remarks-analyse", cl::desc("Show analysis remarks"),
+        cl::location(remarksAnalyseFlag), cl::init(""),
+        cl::cat(remarkCategory));
+
     /// Set the callback to load a pass plugin.
     passPlugins.setCallback([&](const std::string &pluginPath) {
       auto plugin = PassPlugin::load(pluginPath);
@@ -241,23 +279,23 @@ class DiagnosticFilter : public ScopedDiagnosticHandler {
     setHandler([verbosityLevel, showNotes](Diagnostic &diag) {
       auto severity = diag.getSeverity();
       switch (severity) {
-      case DiagnosticSeverity::Error:
+      case mlir::DiagnosticSeverity::Error:
         // failure indicates that the error is not handled by the filter and
         // goes through to the default handler. Therefore, the error can be
         // successfully printed.
         return failure();
-      case DiagnosticSeverity::Warning:
+      case mlir::DiagnosticSeverity::Warning:
         if (verbosityLevel == VerbosityLevel::ErrorsOnly)
           return success();
         else
           return failure();
-      case DiagnosticSeverity::Remark:
+      case mlir::DiagnosticSeverity::Remark:
         if (verbosityLevel == VerbosityLevel::ErrorsOnly ||
             verbosityLevel == VerbosityLevel::ErrorsAndWarnings)
           return success();
         else
           return failure();
-      case DiagnosticSeverity::Note:
+      case mlir::DiagnosticSeverity::Note:
         if (showNotes)
           return failure();
         else
@@ -462,6 +500,38 @@ performActions(raw_ostream &os,
 
   context->enableMultithreading(wasThreadingEnabled);
 
+  // Set up optimization remarks.
+  if (config.shouldEmitRemarks()) {
+    remark::RemarkCategories cats{
+        config.remarksPassedFlag, config.remarksFailedFlag,
+        config.remarksMissedFlag, config.remarksAnalyseFlag};
+
+    mlir::MLIRContext &ctx = *context;
+
+    switch (config.remarkFormatFlag) {
+    case REMARK_FORMAT_STDOUT:
+      if (failed(mlir::remark::enableOptimizationRemarks(ctx, nullptr, cats)))
+        return failure();
+      break;
+
+    case REMARK_FORMAT_YAML: {
+      constexpr llvm::StringLiteral file{"mlir-remarks.yaml"};
+      if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
+              ctx, file, llvm::remarks::Format::YAML, cats)))
+        return failure();
+      break;
+    }
+
+    case REMARK_FORMAT_BITSTREAM: {
+      constexpr llvm::StringLiteral File{"mlir-remarks.bitstream"};
+      if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
+              ctx, File, llvm::remarks::Format::Bitstream, cats)))
+        return failure();
+      break;
+    }
+    }
+  }
+
   // Prepare the pass manager, applying command-line and reproducer options.
   PassManager pm(op.get()->getName(), PassManager::Nesting::Implicit);
   pm.enableVerifier(config.shouldVerifyPasses());
@@ -523,8 +593,8 @@ processBuffer(raw_ostream &os, std::unique_ptr<MemoryBuffer> ownedBuffer,
       SMLoc());
   sourceMgr->AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());
 
-  // Create a context just for the current buffer. Disable threading on creation
-  // since we'll inject the thread-pool separately.
+  // Create a context just for the current buffer. Disable threading on
+  // creation since we'll inject the thread-pool separately.
   MLIRContext context(registry, MLIRContext::Threading::DISABLED);
   if (threadPool)
     context.setThreadPool(*threadPool);
@@ -669,9 +739,9 @@ LogicalResult mlir::MlirOptMain(int argc, char **argv,
   if (config.shouldListPasses())
     return printRegisteredPassesAndReturn();
 
-  // When reading from stdin and the input is a tty, it is often a user mistake
-  // and the process "appears to be stuck". Print a message to let the user know
-  // about it!
+  // When reading from stdin and the input is a tty, it is often a user
+  // mistake and the process "appears to be stuck". Print a message to let the
+  // user know about it!
   if (inputFilename == "-" &&
       sys::Process::FileDescriptorIsDisplayed(fileno(stdin)))
     llvm::errs() << "(processing input from stdin now, hit ctrl-c/ctrl-d to "
diff --git a/mlir/unittests/IR/CMakeLists.txt b/mlir/unittests/IR/CMakeLists.txt
index 75cd2d65ef5a1..dd3b110dcd295 100644
--- a/mlir/unittests/IR/CMakeLists.txt
+++ b/mlir/unittests/IR/CMakeLists.txt
@@ -14,7 +14,7 @@ add_mlir_unittest(MLIRIRTests
   MemrefLayoutTest.cpp
   OperationSupportTest.cpp
   PatternMatchTest.cpp
-  RemarkTest.cpp
+  RemarkTest.cpp  
   ShapedTypeTest.cpp
   SymbolTableTest.cpp
   TypeTest.cpp

>From a9a0b54c002278998a26cfc1d2474c6c2ad443df Mon Sep 17 00:00:00 2001
From: Guray Ozen <gozen at nvidia.com>
Date: Thu, 4 Sep 2025 14:30:54 +0200
Subject: [PATCH 2/6] add test

---
 .../include/mlir/Tools/mlir-opt/MlirOptMain.h |  6 +-
 mlir/lib/Tools/mlir-opt/MlirOptMain.cpp       | 26 ++++--
 mlir/test/Pass/remarks.mlir                   | 48 +++++++++++
 mlir/test/lib/Pass/CMakeLists.txt             |  1 +
 mlir/test/lib/Pass/TestRemarksPipeline.cpp    | 80 +++++++++++++++++++
 mlir/tools/mlir-opt/mlir-opt.cpp              |  2 +
 6 files changed, 156 insertions(+), 7 deletions(-)
 create mode 100644 mlir/test/Pass/remarks.mlir
 create mode 100644 mlir/test/lib/Pass/TestRemarksPipeline.cpp

diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
index dc6a6a1c3cc42..73eeb88bf9f09 100644
--- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
+++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
@@ -231,8 +231,9 @@ class MlirOptMainConfig {
   bool shouldEmitRemarks() const {
     // Emit all remarks only when no filters are specified.
     const bool hasFilters =
-        !remarksPassedFlag.empty() || !remarksFailedFlag.empty() ||
-        !remarksMissedFlag.empty() || !remarksAnalyseFlag.empty();
+        !remarksAllFlag.empty() || !remarksPassedFlag.empty() ||
+        !remarksFailedFlag.empty() || !remarksMissedFlag.empty() ||
+        !remarksAnalyseFlag.empty();
     return hasFilters;
   }
 
@@ -241,6 +242,7 @@ class MlirOptMainConfig {
 
   /// Remark options
   RemarkFormat remarkFormatFlag;
+  std::string remarksAllFlag = "";
   std::string remarksPassedFlag = "";
   std::string remarksFailedFlag = "";
   std::string remarksMissedFlag = "";
diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
index c456540cc1793..0558ffaa4b7b1 100644
--- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
+++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
@@ -225,6 +225,11 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig {
                        "Print bitstream file")),
         llvm::cl::cat(remarkCategory)};
 
+    static cl::opt<std::string, /*ExternalStorage=*/true> remarksAll(
+        "remarks",
+        cl::desc("Show all remarks: passed, missed, failed, analysis"),
+        cl::location(remarksAllFlag), cl::init(""), cl::cat(remarkCategory));
+
     static cl::opt<std::string, /*ExternalStorage=*/true> remarksPassed(
         "remarks-passed", cl::desc("Show passed remarks"),
         cl::location(remarksPassedFlag), cl::init(""), cl::cat(remarkCategory));
@@ -502,15 +507,26 @@ performActions(raw_ostream &os,
 
   // Set up optimization remarks.
   if (config.shouldEmitRemarks()) {
+    auto combine = [](const std::string &a, const std::string &b) {
+      if (a.empty())
+        return b;
+      if (b.empty())
+        return a;
+      return a + "|" + b;
+    };
+
     remark::RemarkCategories cats{
-        config.remarksPassedFlag, config.remarksFailedFlag,
-        config.remarksMissedFlag, config.remarksAnalyseFlag};
+        combine(config.remarksAllFlag, config.remarksPassedFlag),
+        combine(config.remarksAllFlag, config.remarksMissedFlag),
+        combine(config.remarksAllFlag, config.remarksAnalyseFlag),
+        combine(config.remarksAllFlag, config.remarksFailedFlag)};
 
     mlir::MLIRContext &ctx = *context;
 
     switch (config.remarkFormatFlag) {
     case REMARK_FORMAT_STDOUT:
-      if (failed(mlir::remark::enableOptimizationRemarks(ctx, nullptr, cats)))
+      if (failed(mlir::remark::enableOptimizationRemarks(
+              ctx, nullptr, cats, true /*printAsEmitRemarks*/)))
         return failure();
       break;
 
@@ -523,9 +539,9 @@ performActions(raw_ostream &os,
     }
 
     case REMARK_FORMAT_BITSTREAM: {
-      constexpr llvm::StringLiteral File{"mlir-remarks.bitstream"};
+      constexpr llvm::StringLiteral file{"mlir-remarks.bitstream"};
       if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
-              ctx, File, llvm::remarks::Format::Bitstream, cats)))
+              ctx, file, llvm::remarks::Format::Bitstream, cats)))
         return failure();
       break;
     }
diff --git a/mlir/test/Pass/remarks.mlir b/mlir/test/Pass/remarks.mlir
new file mode 100644
index 0000000000000..548215e640006
--- /dev/null
+++ b/mlir/test/Pass/remarks.mlir
@@ -0,0 +1,48 @@
+// RUN: mlir-opt %s --test-remark-pipeline --remarks-passed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-PASSED 
+// RUN: mlir-opt %s --test-remark-pipeline --remarks-missed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-MISSED
+// RUN: mlir-opt %s --test-remark-pipeline --remarks-failed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-FAILED
+// RUN: mlir-opt %s --test-remark-pipeline --remarks-analyse="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ANALYSIS
+// RUN: mlir-opt %s --test-remark-pipeline --remarks="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL
+// RUN: mlir-opt %s --test-remark-pipeline --remarks="category-1" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL1
+module @foo {
+  "test.op"() : () -> ()
+  "test.op2"() : () -> ()
+}
+
+
+// CHECK-PASSED: remarks.mlir:8:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-PASSED: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-PASSED: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+
+// CHECK-MISSED:remarks.mlir:8:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-MISSED:remarks.mlir:9:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-MISSED:remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
+
+// CHECK-FAILED: remarks.mlir:8:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-FAILED: remarks.mlir:9:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-FAILED: remarks.mlir:7:1: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
+
+// CHECK-ANALYSIS: remarks.mlir:8:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
+// CHECK-ANALYSIS: remarks.mlir:9:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
+// CHECK-ANALYSIS: remarks.mlir:7:1: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
+
+
+// CHECK-ALL: remarks.mlir:8:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL: remarks.mlir:8:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL: remarks.mlir:8:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL: remarks.mlir:8:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
+// CHECK-ALL: remarks.mlir:9:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL: remarks.mlir:9:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL: remarks.mlir:9:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
+// CHECK-ALL: remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL: remarks.mlir:7:1: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL: remarks.mlir:7:1: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
+
+// CHECK-ALL1: remarks.mlir:8:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL1: remarks.mlir:8:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL1: remarks.mlir:9:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL1: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL1: remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL1: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
diff --git a/mlir/test/lib/Pass/CMakeLists.txt b/mlir/test/lib/Pass/CMakeLists.txt
index ab52f621c517e..622864398930f 100644
--- a/mlir/test/lib/Pass/CMakeLists.txt
+++ b/mlir/test/lib/Pass/CMakeLists.txt
@@ -4,6 +4,7 @@ add_mlir_library(MLIRTestPass
   TestConvertToSPIRVPass.cpp
   TestDynamicPipeline.cpp
   TestPassManager.cpp
+  TestRemarksPipeline.cpp
   TestSPIRVCPURunnerPipeline.cpp
   TestVulkanRunnerPipeline.cpp
 
diff --git a/mlir/test/lib/Pass/TestRemarksPipeline.cpp b/mlir/test/lib/Pass/TestRemarksPipeline.cpp
new file mode 100644
index 0000000000000..c3c9b16f63b79
--- /dev/null
+++ b/mlir/test/lib/Pass/TestRemarksPipeline.cpp
@@ -0,0 +1,80 @@
+//===------ TestRemarkPipeline.cpp --- dynamic pipeline test pass --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a pass to test the dynamic pipeline feature.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Location.h"
+#include "mlir/IR/Remarks.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Pass/PassManager.h"
+
+using namespace mlir;
+
+namespace {
+
+class TestRemarkPipelinePass
+    : public PassWrapper<TestRemarkPipelinePass, OperationPass<>> {
+public:
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestRemarkPipelinePass)
+
+  StringRef getArgument() const final { return "test-remark-pipeline"; }
+  StringRef getDescription() const final {
+    return "Tests the remark pipeline feature";
+  }
+  void getDependentDialects(DialectRegistry &registry) const override {
+    OpPassManager pm(ModuleOp::getOperationName(),
+                     OpPassManager::Nesting::Implicit);
+
+    pm.getDependentDialects(registry);
+  }
+
+  TestRemarkPipelinePass() = default;
+
+  void runOnOperation() override {
+
+    getOperation()->walk([](Operation *op) {
+      Location loc = op->getLoc();
+      mlir::remark::missed(
+          loc,
+          remark::RemarkOpts::name("test-remark").category("category-1-missed"))
+          << remark::add("This is a test missed remark")
+          << remark::reason("because we are testing the remark pipeline")
+          << remark::suggest("try using the remark pipeline feature");
+
+      mlir::remark::passed(
+          loc,
+          remark::RemarkOpts::name("test-remark").category("category-1-passed"))
+          << remark::add("This is a test passed remark")
+          << remark::reason("because we are testing the remark pipeline")
+          << remark::suggest("try using the remark pipeline feature");
+
+      mlir::remark::failed(
+          loc,
+          remark::RemarkOpts::name("test-remark").category("category-2-failed"))
+          << remark::add("This is a test failed remark")
+          << remark::reason("because we are testing the remark pipeline")
+          << remark::suggest("try using the remark pipeline feature");
+
+      mlir::remark::analysis(loc, remark::RemarkOpts::name("test-remark")
+                                      .category("category-2-analysis"))
+          << remark::add("This is a test analysis remark");
+    });
+  }
+};
+} // namespace
+
+namespace mlir {
+namespace test {
+void registerTestRemarkPipelinePass() {
+  PassRegistration<TestRemarkPipelinePass>();
+}
+} // namespace test
+} // namespace mlir
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp
index 7b992b4ee029b..3dd8199bb09c0 100644
--- a/mlir/tools/mlir-opt/mlir-opt.cpp
+++ b/mlir/tools/mlir-opt/mlir-opt.cpp
@@ -97,6 +97,7 @@ void registerTestDiagnosticsPass();
 void registerTestDiagnosticsMetadataPass();
 void registerTestDominancePass();
 void registerTestDynamicPipelinePass();
+void registerTestRemarkPipelinePass();
 void registerTestEmulateNarrowTypePass();
 void registerTestFooAnalysisPass();
 void registerTestComposeSubView();
@@ -243,6 +244,7 @@ void registerTestPasses() {
   mlir::test::registerTestDiagnosticsMetadataPass();
   mlir::test::registerTestDominancePass();
   mlir::test::registerTestDynamicPipelinePass();
+  mlir::test::registerTestRemarkPipelinePass();
   mlir::test::registerTestEmulateNarrowTypePass();
   mlir::test::registerTestFooAnalysisPass();
   mlir::test::registerTestComposeSubView();

>From e76922555e63d77d75fef295e02881a1cbe05014 Mon Sep 17 00:00:00 2001
From: Guray Ozen <gozen at nvidia.com>
Date: Fri, 5 Sep 2025 17:18:01 +0200
Subject: [PATCH 3/6] address comments

---
 .../include/mlir/Tools/mlir-opt/MlirOptMain.h | 40 ++++++++++++++-----
 mlir/lib/Tools/mlir-opt/MlirOptMain.cpp       | 40 +++++++++++++------
 mlir/test/Pass/remarks.mlir                   | 14 ++++---
 mlir/test/lib/Pass/TestRemarksPipeline.cpp    | 19 +++------
 mlir/tools/mlir-opt/mlir-opt.cpp              |  4 +-
 5 files changed, 73 insertions(+), 44 deletions(-)

diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
index 73eeb88bf9f09..c3ac9d99c24bf 100644
--- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
+++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h
@@ -231,22 +231,31 @@ class MlirOptMainConfig {
   bool shouldEmitRemarks() const {
     // Emit all remarks only when no filters are specified.
     const bool hasFilters =
-        !remarksAllFlag.empty() || !remarksPassedFlag.empty() ||
-        !remarksFailedFlag.empty() || !remarksMissedFlag.empty() ||
-        !remarksAnalyseFlag.empty();
+        !getRemarksAllFilter().empty() || !getRemarksPassedFilter().empty() ||
+        !getRemarksFailedFilter().empty() ||
+        !getRemarksMissedFilter().empty() || !getRemarksAnalyseFilter().empty();
     return hasFilters;
   }
 
   /// Reproducer file generation (no crash required).
   StringRef getReproducerFilename() const { return generateReproducerFileFlag; }
 
-  /// Remark options
-  RemarkFormat remarkFormatFlag;
-  std::string remarksAllFlag = "";
-  std::string remarksPassedFlag = "";
-  std::string remarksFailedFlag = "";
-  std::string remarksMissedFlag = "";
-  std::string remarksAnalyseFlag = "";
+  /// Set the reproducer output filename
+  RemarkFormat getRemarkFormat() const { return remarkFormatFlag; }
+  /// Set the remark format to use.
+  std::string getRemarksAllFilter() const { return remarksAllFilterFlag; }
+  /// Set the remark output file.
+  std::string getRemarksOutputFile() const { return remarksOutputFileFlag; }
+  /// Set the remark passed filters.
+  std::string getRemarksPassedFilter() const { return remarksPassedFilterFlag; }
+  /// Set the remark failed filters.
+  std::string getRemarksFailedFilter() const { return remarksFailedFilterFlag; }
+  /// Set the remark missed filters.
+  std::string getRemarksMissedFilter() const { return remarksMissedFilterFlag; }
+  /// Set the remark analyse filters.
+  std::string getRemarksAnalyseFilter() const {
+    return remarksAnalyseFilterFlag;
+  }
 
 protected:
   /// Allow operation with no registered dialects.
@@ -254,6 +263,17 @@ class MlirOptMainConfig {
   /// general.
   bool allowUnregisteredDialectsFlag = false;
 
+  /// Remark format
+  RemarkFormat remarkFormatFlag;
+  /// Remark file to output to
+  std::string remarksOutputFileFlag = "";
+  /// Remark filters
+  std::string remarksAllFilterFlag = "";
+  std::string remarksPassedFilterFlag = "";
+  std::string remarksFailedFilterFlag = "";
+  std::string remarksMissedFilterFlag = "";
+  std::string remarksAnalyseFilterFlag = "";
+
   /// Configuration for the debugging hooks.
   tracing::DebugConfig debugConfig;
 
diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
index 0558ffaa4b7b1..f366d178907ec 100644
--- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
+++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
@@ -228,23 +228,35 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig {
     static cl::opt<std::string, /*ExternalStorage=*/true> remarksAll(
         "remarks",
         cl::desc("Show all remarks: passed, missed, failed, analysis"),
-        cl::location(remarksAllFlag), cl::init(""), cl::cat(remarkCategory));
+        cl::location(remarksAllFilterFlag), cl::init(""),
+        cl::cat(remarkCategory));
+
+    static cl::opt<std::string, /*ExternalStorage=*/true> remarksFile(
+        "remarks-output-file",
+        cl::desc(
+            "Output file for yaml and bitstream remark formats. Default is "
+            "mlir-remarks.yaml or mlir-remarks.bitstream"),
+        cl::location(remarksOutputFileFlag), cl::init(""),
+        cl::cat(remarkCategory));
 
     static cl::opt<std::string, /*ExternalStorage=*/true> remarksPassed(
         "remarks-passed", cl::desc("Show passed remarks"),
-        cl::location(remarksPassedFlag), cl::init(""), cl::cat(remarkCategory));
+        cl::location(remarksPassedFilterFlag), cl::init(""),
+        cl::cat(remarkCategory));
 
     static cl::opt<std::string, /*ExternalStorage=*/true> remarksFailed(
         "remarks-failed", cl::desc("Show failed remarks"),
-        cl::location(remarksFailedFlag), cl::init(""), cl::cat(remarkCategory));
+        cl::location(remarksFailedFilterFlag), cl::init(""),
+        cl::cat(remarkCategory));
 
     static cl::opt<std::string, /*ExternalStorage=*/true> remarksMissed(
         "remarks-missed", cl::desc("Show missed remarks"),
-        cl::location(remarksMissedFlag), cl::init(""), cl::cat(remarkCategory));
+        cl::location(remarksMissedFilterFlag), cl::init(""),
+        cl::cat(remarkCategory));
 
     static cl::opt<std::string, /*ExternalStorage=*/true> remarksAnalyse(
         "remarks-analyse", cl::desc("Show analysis remarks"),
-        cl::location(remarksAnalyseFlag), cl::init(""),
+        cl::location(remarksAnalyseFilterFlag), cl::init(""),
         cl::cat(remarkCategory));
 
     /// Set the callback to load a pass plugin.
@@ -516,14 +528,14 @@ performActions(raw_ostream &os,
     };
 
     remark::RemarkCategories cats{
-        combine(config.remarksAllFlag, config.remarksPassedFlag),
-        combine(config.remarksAllFlag, config.remarksMissedFlag),
-        combine(config.remarksAllFlag, config.remarksAnalyseFlag),
-        combine(config.remarksAllFlag, config.remarksFailedFlag)};
+        combine(config.getRemarksAllFilter(), config.getRemarksPassedFilter()),
+        combine(config.getRemarksAllFilter(), config.getRemarksMissedFilter()),
+        combine(config.getRemarksAllFilter(), config.getRemarksAnalyseFilter()),
+        combine(config.getRemarksAllFilter(), config.getRemarksFailedFilter())};
 
     mlir::MLIRContext &ctx = *context;
 
-    switch (config.remarkFormatFlag) {
+    switch (config.getRemarkFormat()) {
     case REMARK_FORMAT_STDOUT:
       if (failed(mlir::remark::enableOptimizationRemarks(
               ctx, nullptr, cats, true /*printAsEmitRemarks*/)))
@@ -531,7 +543,9 @@ performActions(raw_ostream &os,
       break;
 
     case REMARK_FORMAT_YAML: {
-      constexpr llvm::StringLiteral file{"mlir-remarks.yaml"};
+      std::string file = config.getRemarksOutputFile().empty()
+                             ? "mlir-remarks.yaml"
+                             : config.getRemarksOutputFile();
       if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
               ctx, file, llvm::remarks::Format::YAML, cats)))
         return failure();
@@ -539,7 +553,9 @@ performActions(raw_ostream &os,
     }
 
     case REMARK_FORMAT_BITSTREAM: {
-      constexpr llvm::StringLiteral file{"mlir-remarks.bitstream"};
+      std::string file = config.getRemarksOutputFile().empty()
+                             ? "mlir-remarks.bitstream"
+                             : config.getRemarksOutputFile();
       if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
               ctx, file, llvm::remarks::Format::Bitstream, cats)))
         return failure();
diff --git a/mlir/test/Pass/remarks.mlir b/mlir/test/Pass/remarks.mlir
index 548215e640006..1f57261874739 100644
--- a/mlir/test/Pass/remarks.mlir
+++ b/mlir/test/Pass/remarks.mlir
@@ -1,9 +1,9 @@
-// RUN: mlir-opt %s --test-remark-pipeline --remarks-passed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-PASSED 
-// RUN: mlir-opt %s --test-remark-pipeline --remarks-missed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-MISSED
-// RUN: mlir-opt %s --test-remark-pipeline --remarks-failed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-FAILED
-// RUN: mlir-opt %s --test-remark-pipeline --remarks-analyse="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ANALYSIS
-// RUN: mlir-opt %s --test-remark-pipeline --remarks="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL
-// RUN: mlir-opt %s --test-remark-pipeline --remarks="category-1" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL1
+// RUN: mlir-opt %s --test-remark --remarks-passed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-PASSED 
+// RUN: mlir-opt %s --test-remark --remarks-missed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-MISSED
+// RUN: mlir-opt %s --test-remark --remarks-failed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-FAILED
+// RUN: mlir-opt %s --test-remark --remarks-analyse="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ANALYSIS
+// RUN: mlir-opt %s --test-remark --remarks="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL
+// RUN: mlir-opt %s --test-remark --remarks="category-1" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL1
 module @foo {
   "test.op"() : () -> ()
   "test.op2"() : () -> ()
@@ -46,3 +46,5 @@ module @foo {
 // CHECK-ALL1: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
 // CHECK-ALL1: remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
 // CHECK-ALL1: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL1-NOT: remarks.mlir:8:3: remark: [Failure]
+// CHECK-ALL1-NOT: remarks.mlir:8:3: remark: [Analysis]
diff --git a/mlir/test/lib/Pass/TestRemarksPipeline.cpp b/mlir/test/lib/Pass/TestRemarksPipeline.cpp
index c3c9b16f63b79..3e90ff7adbf85 100644
--- a/mlir/test/lib/Pass/TestRemarksPipeline.cpp
+++ b/mlir/test/lib/Pass/TestRemarksPipeline.cpp
@@ -20,23 +20,16 @@ using namespace mlir;
 
 namespace {
 
-class TestRemarkPipelinePass
-    : public PassWrapper<TestRemarkPipelinePass, OperationPass<>> {
+class TestRemarkPass : public PassWrapper<TestRemarkPass, OperationPass<>> {
 public:
-  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestRemarkPipelinePass)
+  MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestRemarkPass)
 
-  StringRef getArgument() const final { return "test-remark-pipeline"; }
+  StringRef getArgument() const final { return "test-remark"; }
   StringRef getDescription() const final {
     return "Tests the remark pipeline feature";
   }
-  void getDependentDialects(DialectRegistry &registry) const override {
-    OpPassManager pm(ModuleOp::getOperationName(),
-                     OpPassManager::Nesting::Implicit);
 
-    pm.getDependentDialects(registry);
-  }
-
-  TestRemarkPipelinePass() = default;
+  TestRemarkPass() = default;
 
   void runOnOperation() override {
 
@@ -73,8 +66,6 @@ class TestRemarkPipelinePass
 
 namespace mlir {
 namespace test {
-void registerTestRemarkPipelinePass() {
-  PassRegistration<TestRemarkPipelinePass>();
-}
+void registerTestRemarkPass() { PassRegistration<TestRemarkPass>(); }
 } // namespace test
 } // namespace mlir
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp
index 3dd8199bb09c0..e4620c009af8c 100644
--- a/mlir/tools/mlir-opt/mlir-opt.cpp
+++ b/mlir/tools/mlir-opt/mlir-opt.cpp
@@ -97,7 +97,7 @@ void registerTestDiagnosticsPass();
 void registerTestDiagnosticsMetadataPass();
 void registerTestDominancePass();
 void registerTestDynamicPipelinePass();
-void registerTestRemarkPipelinePass();
+void registerTestRemarkPass();
 void registerTestEmulateNarrowTypePass();
 void registerTestFooAnalysisPass();
 void registerTestComposeSubView();
@@ -244,7 +244,7 @@ void registerTestPasses() {
   mlir::test::registerTestDiagnosticsMetadataPass();
   mlir::test::registerTestDominancePass();
   mlir::test::registerTestDynamicPipelinePass();
-  mlir::test::registerTestRemarkPipelinePass();
+  mlir::test::registerTestRemarkPass();
   mlir::test::registerTestEmulateNarrowTypePass();
   mlir::test::registerTestFooAnalysisPass();
   mlir::test::registerTestComposeSubView();

>From 88f649de14b3a3f7eb80170a9863c1ce9c62d95e Mon Sep 17 00:00:00 2001
From: Guray Ozen <gozen at nvidia.com>
Date: Mon, 8 Sep 2025 14:03:16 +0200
Subject: [PATCH 4/6] name change

---
 mlir/test/lib/Pass/CMakeLists.txt                               | 2 +-
 .../lib/Pass/{TestRemarksPipeline.cpp => TestRemarksPass.cpp}   | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename mlir/test/lib/Pass/{TestRemarksPipeline.cpp => TestRemarksPass.cpp} (100%)

diff --git a/mlir/test/lib/Pass/CMakeLists.txt b/mlir/test/lib/Pass/CMakeLists.txt
index 622864398930f..04c91635def85 100644
--- a/mlir/test/lib/Pass/CMakeLists.txt
+++ b/mlir/test/lib/Pass/CMakeLists.txt
@@ -4,7 +4,7 @@ add_mlir_library(MLIRTestPass
   TestConvertToSPIRVPass.cpp
   TestDynamicPipeline.cpp
   TestPassManager.cpp
-  TestRemarksPipeline.cpp
+  TestRemarksPass.cpp
   TestSPIRVCPURunnerPipeline.cpp
   TestVulkanRunnerPipeline.cpp
 
diff --git a/mlir/test/lib/Pass/TestRemarksPipeline.cpp b/mlir/test/lib/Pass/TestRemarksPass.cpp
similarity index 100%
rename from mlir/test/lib/Pass/TestRemarksPipeline.cpp
rename to mlir/test/lib/Pass/TestRemarksPass.cpp

>From d724f85bb9fa6878051c40ea4e240c16402e9108 Mon Sep 17 00:00:00 2001
From: Guray Ozen <gozen at nvidia.com>
Date: Mon, 8 Sep 2025 15:21:27 +0200
Subject: [PATCH 5/6] fx

---
 mlir/include/mlir/IR/Remarks.h          |  2 +-
 mlir/lib/IR/Remarks.cpp                 | 47 ++++++++++++++--
 mlir/lib/Tools/mlir-opt/MlirOptMain.cpp | 72 +++++++++++--------------
 mlir/test/Pass/remarks.mlir             | 44 ++++-----------
 mlir/test/lib/Pass/TestRemarksPass.cpp  |  9 ++--
 5 files changed, 91 insertions(+), 83 deletions(-)

diff --git a/mlir/include/mlir/IR/Remarks.h b/mlir/include/mlir/IR/Remarks.h
index 26d65472f2b1c..20e84ec83cd01 100644
--- a/mlir/include/mlir/IR/Remarks.h
+++ b/mlir/include/mlir/IR/Remarks.h
@@ -29,7 +29,7 @@ namespace mlir::remark {
 /// Define an the set of categories to accept. By default none are, the provided
 /// regex matches against the category names for each kind of remark.
 struct RemarkCategories {
-  std::optional<std::string> passed, missed, analysis, failed;
+  std::optional<std::string> all, passed, missed, analysis, failed;
 };
 
 /// Categories describe the outcome of an transformation, not the mechanics of
diff --git a/mlir/lib/IR/Remarks.cpp b/mlir/lib/IR/Remarks.cpp
index 78c964427868f..29088bd360e23 100644
--- a/mlir/lib/IR/Remarks.cpp
+++ b/mlir/lib/IR/Remarks.cpp
@@ -248,17 +248,56 @@ RemarkEngine::initialize(std::unique_ptr<MLIRRemarkStreamerBase> streamer,
   return success();
 }
 
+/// Returns true if filter is already anchored like ^...$
+static bool isAnchored(llvm::StringRef s) {
+  s = s.trim();
+  return s.starts_with("^") && s.ends_with("$"); // note: startswith/endswith
+}
+
+/// Anchor the entire pattern so it matches the whole string.
+static std::string anchorWhole(llvm::StringRef filter) {
+  if (isAnchored(filter))
+    return filter.str();
+  return (llvm::Twine("^(") + filter + ")$").str();
+}
+
+/// Build a combined filter from cats.all and a category-specific pattern.
+/// If neither is present, return std::nullopt. Otherwise "(all|specific)"
+/// and anchor once. Also validate before returning.
+static std::optional<llvm::Regex>
+buildFilter(const mlir::remark::RemarkCategories &cats,
+            const std::optional<std::string> &specific) {
+  llvm::SmallVector<llvm::StringRef, 2> parts;
+  if (cats.all && !cats.all->empty())
+    parts.emplace_back(*cats.all);
+  if (specific && !specific->empty())
+    parts.emplace_back(*specific);
+
+  if (parts.empty())
+    return std::nullopt;
+
+  std::string joined = llvm::join(parts, "|");
+  std::string anchored = anchorWhole(joined);
+
+  llvm::Regex rx(anchored);
+  std::string err;
+  if (!rx.isValid(err))
+    return std::nullopt;
+
+  return rx;
+}
+
 RemarkEngine::RemarkEngine(bool printAsEmitRemarks,
                            const RemarkCategories &cats)
     : printAsEmitRemarks(printAsEmitRemarks) {
   if (cats.passed)
-    passedFilter = llvm::Regex(cats.passed.value());
+    passedFilter = buildFilter(cats, cats.passed);
   if (cats.missed)
-    missFilter = llvm::Regex(cats.missed.value());
+    missFilter = buildFilter(cats, cats.missed);
   if (cats.analysis)
-    analysisFilter = llvm::Regex(cats.analysis.value());
+    analysisFilter = buildFilter(cats, cats.analysis);
   if (cats.failed)
-    failedFilter = llvm::Regex(cats.failed.value());
+    failedFilter = buildFilter(cats, cats.failed);
 }
 
 llvm::LogicalResult mlir::remark::enableOptimizationRemarks(
diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
index f366d178907ec..d9ce13662a67c 100644
--- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
+++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
@@ -517,51 +517,39 @@ performActions(raw_ostream &os,
 
   context->enableMultithreading(wasThreadingEnabled);
 
-  // Set up optimization remarks.
-  if (config.shouldEmitRemarks()) {
-    auto combine = [](const std::string &a, const std::string &b) {
-      if (a.empty())
-        return b;
-      if (b.empty())
-        return a;
-      return a + "|" + b;
-    };
-
-    remark::RemarkCategories cats{
-        combine(config.getRemarksAllFilter(), config.getRemarksPassedFilter()),
-        combine(config.getRemarksAllFilter(), config.getRemarksMissedFilter()),
-        combine(config.getRemarksAllFilter(), config.getRemarksAnalyseFilter()),
-        combine(config.getRemarksAllFilter(), config.getRemarksFailedFilter())};
+  remark::RemarkCategories cats{
+      config.getRemarksAllFilter(), config.getRemarksPassedFilter(),
+      config.getRemarksMissedFilter(), config.getRemarksAnalyseFilter(),
+      config.getRemarksFailedFilter()};
 
-    mlir::MLIRContext &ctx = *context;
+  mlir::MLIRContext &ctx = *context;
 
-    switch (config.getRemarkFormat()) {
-    case REMARK_FORMAT_STDOUT:
-      if (failed(mlir::remark::enableOptimizationRemarks(
-              ctx, nullptr, cats, true /*printAsEmitRemarks*/)))
-        return failure();
-      break;
-
-    case REMARK_FORMAT_YAML: {
-      std::string file = config.getRemarksOutputFile().empty()
-                             ? "mlir-remarks.yaml"
-                             : config.getRemarksOutputFile();
-      if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
-              ctx, file, llvm::remarks::Format::YAML, cats)))
-        return failure();
-      break;
-    }
+  switch (config.getRemarkFormat()) {
+  case REMARK_FORMAT_STDOUT:
+    if (failed(mlir::remark::enableOptimizationRemarks(
+            ctx, nullptr, cats, true /*printAsEmitRemarks*/)))
+      return failure();
+    break;
+
+  case REMARK_FORMAT_YAML: {
+    std::string file = config.getRemarksOutputFile().empty()
+                           ? "mlir-remarks.yaml"
+                           : config.getRemarksOutputFile();
+    if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
+            ctx, file, llvm::remarks::Format::YAML, cats)))
+      return failure();
+    break;
+  }
 
-    case REMARK_FORMAT_BITSTREAM: {
-      std::string file = config.getRemarksOutputFile().empty()
-                             ? "mlir-remarks.bitstream"
-                             : config.getRemarksOutputFile();
-      if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
-              ctx, file, llvm::remarks::Format::Bitstream, cats)))
-        return failure();
-      break;
-    }
-    }
+  case REMARK_FORMAT_BITSTREAM: {
+    std::string file = config.getRemarksOutputFile().empty()
+                           ? "mlir-remarks.bitstream"
+                           : config.getRemarksOutputFile();
+    if (failed(mlir::remark::enableOptimizationRemarksWithLLVMStreamer(
+            ctx, file, llvm::remarks::Format::Bitstream, cats)))
+      return failure();
+    break;
+  }
   }
 
   // Prepare the pass manager, applying command-line and reproducer options.
diff --git a/mlir/test/Pass/remarks.mlir b/mlir/test/Pass/remarks.mlir
index 1f57261874739..b78c538d78385 100644
--- a/mlir/test/Pass/remarks.mlir
+++ b/mlir/test/Pass/remarks.mlir
@@ -1,50 +1,28 @@
-// RUN: mlir-opt %s --test-remark --remarks-passed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-PASSED 
-// RUN: mlir-opt %s --test-remark --remarks-missed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-MISSED
-// RUN: mlir-opt %s --test-remark --remarks-failed="category" 2>&1 | FileCheck %s -check-prefix=CHECK-FAILED
-// RUN: mlir-opt %s --test-remark --remarks-analyse="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ANALYSIS
-// RUN: mlir-opt %s --test-remark --remarks="category" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL
-// RUN: mlir-opt %s --test-remark --remarks="category-1" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL1
+// RUN: mlir-opt %s --test-remark --remarks-passed="category-1-passed" 2>&1 | FileCheck %s -check-prefix=CHECK-PASSED 
+// RUN: mlir-opt %s --test-remark --remarks-missed="a-category-1-missed" 2>&1 | FileCheck %s -check-prefix=CHECK-MISSED
+// RUN: mlir-opt %s --test-remark --remarks-failed="category-2-failed" 2>&1 | FileCheck %s -check-prefix=CHECK-FAILED
+// RUN: mlir-opt %s --test-remark --remarks-analyse="category-2-analysis" 2>&1 | FileCheck %s -check-prefix=CHECK-ANALYSIS
+// RUN: mlir-opt %s --test-remark --remarks="category.*" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL
+// RUN: mlir-opt %s --test-remark --remarks="category-1.*" 2>&1 | FileCheck %s -check-prefix=CHECK-ALL1
 module @foo {
   "test.op"() : () -> ()
-  "test.op2"() : () -> ()
+  
 }
 
 
 // CHECK-PASSED: remarks.mlir:8:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-PASSED: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-PASSED: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
-
-// CHECK-MISSED:remarks.mlir:8:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-MISSED:remarks.mlir:9:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-MISSED:remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
-
+// CHECK-MISSED:remarks.mlir:8:3: remark: [Missed] test-remark | Category:a-category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
 // CHECK-FAILED: remarks.mlir:8:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-FAILED: remarks.mlir:9:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-FAILED: remarks.mlir:7:1: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
-
 // CHECK-ANALYSIS: remarks.mlir:8:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
-// CHECK-ANALYSIS: remarks.mlir:9:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
-// CHECK-ANALYSIS: remarks.mlir:7:1: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
 
 
-// CHECK-ALL: remarks.mlir:8:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
 // CHECK-ALL: remarks.mlir:8:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
 // CHECK-ALL: remarks.mlir:8:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
 // CHECK-ALL: remarks.mlir:8:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
-// CHECK-ALL: remarks.mlir:9:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL: remarks.mlir:9:3: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL: remarks.mlir:9:3: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
-// CHECK-ALL: remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL: remarks.mlir:7:1: remark: [Failure] test-remark | Category:category-2-failed | Reason="because we are testing the remark pipeline", Remark="This is a test failed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL: remarks.mlir:7:1: remark: [Analysis] test-remark | Category:category-2-analysis | Remark="This is a test analysis remark"
 
-// CHECK-ALL1: remarks.mlir:8:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
 // CHECK-ALL1: remarks.mlir:8:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL1: remarks.mlir:9:3: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL1: remarks.mlir:9:3: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL1: remarks.mlir:7:1: remark: [Missed] test-remark | Category:category-1-missed | Reason="because we are testing the remark pipeline", Remark="This is a test missed remark", Suggestion="try using the remark pipeline feature"
-// CHECK-ALL1: remarks.mlir:7:1: remark: [Passed] test-remark | Category:category-1-passed | Reason="because we are testing the remark pipeline", Remark="This is a test passed remark", Suggestion="try using the remark pipeline feature"
+// CHECK-ALL1-NOT: remarks.mlir:8:3: remark: [Missed]
 // CHECK-ALL1-NOT: remarks.mlir:8:3: remark: [Failure]
 // CHECK-ALL1-NOT: remarks.mlir:8:3: remark: [Analysis]
+
+
diff --git a/mlir/test/lib/Pass/TestRemarksPass.cpp b/mlir/test/lib/Pass/TestRemarksPass.cpp
index 3e90ff7adbf85..3b25686b3dc14 100644
--- a/mlir/test/lib/Pass/TestRemarksPass.cpp
+++ b/mlir/test/lib/Pass/TestRemarksPass.cpp
@@ -15,6 +15,7 @@
 #include "mlir/IR/Remarks.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Pass/PassManager.h"
+#include "mlir/Support/WalkResult.h"
 
 using namespace mlir;
 
@@ -34,10 +35,11 @@ class TestRemarkPass : public PassWrapper<TestRemarkPass, OperationPass<>> {
   void runOnOperation() override {
 
     getOperation()->walk([](Operation *op) {
+      if (isa<ModuleOp>(op))
+        return WalkResult::advance();
       Location loc = op->getLoc();
-      mlir::remark::missed(
-          loc,
-          remark::RemarkOpts::name("test-remark").category("category-1-missed"))
+      mlir::remark::missed(loc, remark::RemarkOpts::name("test-remark")
+                                    .category("a-category-1-missed"))
           << remark::add("This is a test missed remark")
           << remark::reason("because we are testing the remark pipeline")
           << remark::suggest("try using the remark pipeline feature");
@@ -59,6 +61,7 @@ class TestRemarkPass : public PassWrapper<TestRemarkPass, OperationPass<>> {
       mlir::remark::analysis(loc, remark::RemarkOpts::name("test-remark")
                                       .category("category-2-analysis"))
           << remark::add("This is a test analysis remark");
+      return WalkResult::advance();
     });
   }
 };

>From a117fe5a74faffcc2f6a2dff666b1646ebbb141e Mon Sep 17 00:00:00 2001
From: Guray Ozen <gozen at nvidia.com>
Date: Mon, 8 Sep 2025 16:23:45 +0200
Subject: [PATCH 6/6] fx

---
 mlir/unittests/IR/RemarkTest.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/mlir/unittests/IR/RemarkTest.cpp b/mlir/unittests/IR/RemarkTest.cpp
index 65e1e08b83838..5bfca255c22ca 100644
--- a/mlir/unittests/IR/RemarkTest.cpp
+++ b/mlir/unittests/IR/RemarkTest.cpp
@@ -48,7 +48,8 @@ TEST(Remark, TestOutputOptimizationRemark) {
     context.printStackTraceOnDiagnostic(true);
 
     // Setup the remark engine
-    mlir::remark::RemarkCategories cats{/*passed=*/categoryVectorizer,
+    mlir::remark::RemarkCategories cats{/*all=*/"",
+                                        /*passed=*/categoryVectorizer,
                                         /*missed=*/categoryUnroll,
                                         /*analysis=*/categoryRegister,
                                         /*failed=*/categoryInliner};
@@ -197,7 +198,8 @@ TEST(Remark, TestOutputOptimizationRemarkDiagnostic) {
     });
 
     // Setup the remark engine
-    mlir::remark::RemarkCategories cats{/*passed=*/categoryVectorizer,
+    mlir::remark::RemarkCategories cats{/*all=*/"",
+                                        /*passed=*/categoryVectorizer,
                                         /*missed=*/categoryUnroll,
                                         /*analysis=*/categoryRegister,
                                         /*failed=*/categoryUnroll};
@@ -278,7 +280,8 @@ TEST(Remark, TestCustomOptimizationRemarkDiagnostic) {
     Location loc = UnknownLoc::get(&context);
 
     // Setup the remark engine
-    mlir::remark::RemarkCategories cats{/*passed=*/categoryLoopunroll,
+    mlir::remark::RemarkCategories cats{/*all=*/"",
+                                        /*passed=*/categoryLoopunroll,
                                         /*missed=*/std::nullopt,
                                         /*analysis=*/std::nullopt,
                                         /*failed=*/categoryLoopunroll};



More information about the Mlir-commits mailing list