[Mlir-commits] [mlir] [MLIR][Remark] Expose RemarkEngine filter queries (PR #222262)

Guray Ozen llvmlistbot at llvm.org
Wed Sep 9 01:04:22 PDT 2026


https://github.com/grypp created https://github.com/llvm/llvm-project/pull/222262

Expose following filter APIs publicly:

```
| Query                                        | Answers                                              |
|----------------------------------------------|------------------------------------------------------|
| `isAnyRemarkEnabled()`                       | At least one category filter is active               |
| `isAnyRemarkEnabled(category)`               | Some kind of remark is enabled for the category      |
| `isRemarkEnabled(kind, category)`            | Remarks of `kind` are enabled for the category       |
| `is{Passed,Missed,Analysis,Failed}OptRemarkEnabled(category)` | Per-kind query                      |
```

>From 95265221cc1835d3fbfdc1a82e4bc97011f65e77 Mon Sep 17 00:00:00 2001
From: Guray Ozen <gozen at nvidia.com>
Date: Wed, 9 Sep 2026 10:02:40 +0200
Subject: [PATCH] [MLIR][Remark] Expose RemarkEngine filter queries

Expose filter apis publicly
---
 mlir/docs/Remarks.md             |  27 ++++++++
 mlir/include/mlir/IR/Remarks.h   |  63 ++++++++++++-------
 mlir/lib/IR/Remarks.cpp          |  17 +++++
 mlir/unittests/IR/RemarkTest.cpp | 104 +++++++++++++++++++++++++++++++
 4 files changed, 187 insertions(+), 24 deletions(-)

diff --git a/mlir/docs/Remarks.md b/mlir/docs/Remarks.md
index b44ec2cc3f055..43f5d4da12247 100644
--- a/mlir/docs/Remarks.md
+++ b/mlir/docs/Remarks.md
@@ -221,6 +221,33 @@ You can also implement custom policies by inheriting from the policy interface.
 
 ***
 
+## Querying Enabled Remarks
+
+A remark is only built when its kind and category match the configured
+filters. The `remark::passed`, `remark::missed`, `remark::failed` and
+`remark::analysis` helpers perform this check themselves, so passes do not need
+to do anything. Code that produces remarks from another source, for example a
+bridge that imports remarks from a different compiler, can ask the engine what
+is enabled before doing any work:
+
+```c++
+remark::detail::RemarkEngine *engine = context.getRemarkEngine();
+if (!engine || !engine->isAnyRemarkEnabled())
+  return; // No remark engine, or no category filter is active.
+
+if (engine->isRemarkEnabled(remark::RemarkKind::RemarkPassed, "Vectorizer"))
+  remark::passed(loc, opts) << "vectorized loop";
+```
+
+| Query                                        | Answers                                              |
+|----------------------------------------------|------------------------------------------------------|
+| `isAnyRemarkEnabled()`                       | At least one category filter is active               |
+| `isAnyRemarkEnabled(category)`               | Some kind of remark is enabled for the category      |
+| `isRemarkEnabled(kind, category)`            | Remarks of `kind` are enabled for the category       |
+| `is{Passed,Missed,Analysis,Failed}OptRemarkEnabled(category)` | Per-kind query                      |
+
+***
+
 ## Enabling Remarks
 
 ### Option 1: LLVM Remark Streamer (YAML or Bitstream)
diff --git a/mlir/include/mlir/IR/Remarks.h b/mlir/include/mlir/IR/Remarks.h
index 5cfb888be44a2..81073efa4e026 100644
--- a/mlir/include/mlir/IR/Remarks.h
+++ b/mlir/include/mlir/IR/Remarks.h
@@ -515,30 +515,6 @@ class RemarkEngine {
   /// Atomic counter for generating unique remark IDs.
   std::atomic<uint64_t> nextRemarkId{1};
 
-  /// Return true if missed optimization remarks are enabled, override
-  /// to provide different implementation.
-  bool isMissedOptRemarkEnabled(StringRef categoryName) const;
-
-  /// Return true if passed optimization remarks are enabled, override
-  /// to provide different implementation.
-  bool isPassedOptRemarkEnabled(StringRef categoryName) const;
-
-  /// Return true if analysis optimization remarks are enabled, override
-  /// to provide different implementation.
-  bool isAnalysisOptRemarkEnabled(StringRef categoryName) const;
-
-  /// Return true if analysis optimization remarks are enabled, override
-  /// to provide different implementation.
-  bool isFailedOptRemarkEnabled(StringRef categoryName) const;
-
-  /// Return true if any type of remarks are enabled for this pass.
-  bool isAnyRemarkEnabled(StringRef categoryName) const {
-    return isMissedOptRemarkEnabled(categoryName) ||
-           isPassedOptRemarkEnabled(categoryName) ||
-           isFailedOptRemarkEnabled(categoryName) ||
-           isAnalysisOptRemarkEnabled(categoryName);
-  }
-
   /// Emit a remark using the given maker function, which should return
   /// a Remark instance. The remark will be emitted using the main
   /// remark streamer.
@@ -581,6 +557,45 @@ class RemarkEngine {
     return RemarkId(nextRemarkId.fetch_add(1, std::memory_order_relaxed));
   }
 
+  //===--------------------------------------------------------------------===//
+  // Remark Filtering - query which remarks are enabled
+  //===--------------------------------------------------------------------===//
+
+  /// Return true if missed optimization remarks are enabled for the given
+  /// category.
+  bool isMissedOptRemarkEnabled(StringRef categoryName) const;
+
+  /// Return true if passed optimization remarks are enabled for the given
+  /// category.
+  bool isPassedOptRemarkEnabled(StringRef categoryName) const;
+
+  /// Return true if analysis remarks are enabled for the given category.
+  bool isAnalysisOptRemarkEnabled(StringRef categoryName) const;
+
+  /// Return true if failed optimization remarks are enabled for the given
+  /// category.
+  bool isFailedOptRemarkEnabled(StringRef categoryName) const;
+
+  /// Return true if remarks of the given kind are enabled for the given
+  /// category. Always returns false for `RemarkKind::RemarkUnknown`.
+  bool isRemarkEnabled(RemarkKind kind, StringRef categoryName) const;
+
+  /// Return true if any kind of remark is enabled for the given category.
+  bool isAnyRemarkEnabled(StringRef categoryName) const {
+    return isMissedOptRemarkEnabled(categoryName) ||
+           isPassedOptRemarkEnabled(categoryName) ||
+           isFailedOptRemarkEnabled(categoryName) ||
+           isAnalysisOptRemarkEnabled(categoryName);
+  }
+
+  /// Return true if any kind of remark is enabled for any category, i.e. if at
+  /// least one category filter is active. This is a cheap check that external
+  /// remark producers can use before doing any work to build a remark.
+  bool isAnyRemarkEnabled() const {
+    return missFilter.has_value() || passedFilter.has_value() ||
+           analysisFilter.has_value() || failedFilter.has_value();
+  }
+
   //===--------------------------------------------------------------------===//
   // Remark Linking - query previously emitted remarks
   //===--------------------------------------------------------------------===//
diff --git a/mlir/lib/IR/Remarks.cpp b/mlir/lib/IR/Remarks.cpp
index 273918171746d..85c19dbd89250 100644
--- a/mlir/lib/IR/Remarks.cpp
+++ b/mlir/lib/IR/Remarks.cpp
@@ -205,6 +205,23 @@ bool RemarkEngine::isFailedOptRemarkEnabled(StringRef categoryName) const {
   return failedFilter && failedFilter->match(categoryName);
 }
 
+bool RemarkEngine::isRemarkEnabled(RemarkKind kind,
+                                   StringRef categoryName) const {
+  switch (kind) {
+  case RemarkKind::RemarkUnknown:
+    return false;
+  case RemarkKind::RemarkPassed:
+    return isPassedOptRemarkEnabled(categoryName);
+  case RemarkKind::RemarkMissed:
+    return isMissedOptRemarkEnabled(categoryName);
+  case RemarkKind::RemarkFailure:
+    return isFailedOptRemarkEnabled(categoryName);
+  case RemarkKind::RemarkAnalysis:
+    return isAnalysisOptRemarkEnabled(categoryName);
+  }
+  llvm_unreachable("Unknown remark kind");
+}
+
 InFlightRemark RemarkEngine::emitOptimizationRemark(Location loc,
                                                     RemarkOpts opts) {
   return emitIfEnabled<OptRemarkPass>(loc, opts,
diff --git a/mlir/unittests/IR/RemarkTest.cpp b/mlir/unittests/IR/RemarkTest.cpp
index 81bfcd1446455..c02f1e1c14bf5 100644
--- a/mlir/unittests/IR/RemarkTest.cpp
+++ b/mlir/unittests/IR/RemarkTest.cpp
@@ -518,6 +518,110 @@ TEST(Remark, TestRemarkOwnsStringData) {
       << "Expected message not found in output. Got: " << errOut;
 }
 
+// Test that the engine exposes which remark kinds and categories are enabled,
+// so that external remark producers can query the filters before building
+// remarks.
+TEST(Remark, TestEngineFilterQueries) {
+  using remark::RemarkKind;
+
+  // No filter is set: nothing is enabled.
+  {
+    MLIRContext context;
+    mlir::remark::RemarkCategories cats{/*all=*/std::nullopt,
+                                        /*passed=*/std::nullopt,
+                                        /*missed=*/std::nullopt,
+                                        /*analysis=*/std::nullopt,
+                                        /*failed=*/std::nullopt};
+    ASSERT_TRUE(succeeded(remark::enableOptimizationRemarks(
+        context, nullptr, std::make_unique<remark::RemarkEmittingPolicyAll>(),
+        cats)));
+    remark::detail::RemarkEngine *engine = context.getRemarkEngine();
+    ASSERT_TRUE(engine);
+    EXPECT_FALSE(engine->isAnyRemarkEnabled());
+    EXPECT_FALSE(engine->isAnyRemarkEnabled("Vectorizer"));
+    EXPECT_FALSE(engine->isPassedOptRemarkEnabled("Vectorizer"));
+  }
+
+  // Empty filter strings are equivalent to unset filters.
+  {
+    MLIRContext context;
+    mlir::remark::RemarkCategories cats{/*all=*/"", /*passed=*/"",
+                                        /*missed=*/"", /*analysis=*/"",
+                                        /*failed=*/""};
+    ASSERT_TRUE(succeeded(remark::enableOptimizationRemarks(
+        context, nullptr, std::make_unique<remark::RemarkEmittingPolicyAll>(),
+        cats)));
+    remark::detail::RemarkEngine *engine = context.getRemarkEngine();
+    ASSERT_TRUE(engine);
+    EXPECT_FALSE(engine->isAnyRemarkEnabled());
+  }
+
+  // Per-kind filters are matched against the whole category name.
+  {
+    MLIRContext context;
+    mlir::remark::RemarkCategories cats{/*all=*/std::nullopt,
+                                        /*passed=*/"Vectorizer",
+                                        /*missed=*/"Unroll|Inliner",
+                                        /*analysis=*/std::nullopt,
+                                        /*failed=*/std::nullopt};
+    ASSERT_TRUE(succeeded(remark::enableOptimizationRemarks(
+        context, nullptr, std::make_unique<remark::RemarkEmittingPolicyAll>(),
+        cats)));
+    remark::detail::RemarkEngine *engine = context.getRemarkEngine();
+    ASSERT_TRUE(engine);
+
+    EXPECT_TRUE(engine->isAnyRemarkEnabled());
+
+    EXPECT_TRUE(engine->isPassedOptRemarkEnabled("Vectorizer"));
+    EXPECT_FALSE(engine->isPassedOptRemarkEnabled("Vectorizer2"));
+    EXPECT_FALSE(engine->isPassedOptRemarkEnabled("Unroll"));
+
+    EXPECT_TRUE(engine->isMissedOptRemarkEnabled("Unroll"));
+    EXPECT_TRUE(engine->isMissedOptRemarkEnabled("Inliner"));
+    EXPECT_FALSE(engine->isMissedOptRemarkEnabled("Vectorizer"));
+
+    EXPECT_FALSE(engine->isAnalysisOptRemarkEnabled("Vectorizer"));
+    EXPECT_FALSE(engine->isFailedOptRemarkEnabled("Vectorizer"));
+
+    EXPECT_TRUE(engine->isAnyRemarkEnabled("Vectorizer"));
+    EXPECT_TRUE(engine->isAnyRemarkEnabled("Unroll"));
+    EXPECT_FALSE(engine->isAnyRemarkEnabled("Register"));
+
+    EXPECT_TRUE(
+        engine->isRemarkEnabled(RemarkKind::RemarkPassed, "Vectorizer"));
+    EXPECT_TRUE(engine->isRemarkEnabled(RemarkKind::RemarkMissed, "Unroll"));
+    EXPECT_FALSE(
+        engine->isRemarkEnabled(RemarkKind::RemarkAnalysis, "Vectorizer"));
+    EXPECT_FALSE(
+        engine->isRemarkEnabled(RemarkKind::RemarkFailure, "Vectorizer"));
+    EXPECT_FALSE(
+        engine->isRemarkEnabled(RemarkKind::RemarkUnknown, "Vectorizer"));
+  }
+
+  // The `all` filter enables every kind for the matching categories.
+  {
+    MLIRContext context;
+    mlir::remark::RemarkCategories cats{/*all=*/"loop-.*",
+                                        /*passed=*/std::nullopt,
+                                        /*missed=*/"",
+                                        /*analysis=*/"",
+                                        /*failed=*/""};
+    ASSERT_TRUE(succeeded(remark::enableOptimizationRemarks(
+        context, nullptr, std::make_unique<remark::RemarkEmittingPolicyAll>(),
+        cats)));
+    remark::detail::RemarkEngine *engine = context.getRemarkEngine();
+    ASSERT_TRUE(engine);
+
+    EXPECT_TRUE(engine->isAnyRemarkEnabled());
+    // `passed` is unset, so `all` does not enable it.
+    EXPECT_FALSE(engine->isPassedOptRemarkEnabled("loop-unroll"));
+    EXPECT_TRUE(engine->isMissedOptRemarkEnabled("loop-unroll"));
+    EXPECT_TRUE(engine->isAnalysisOptRemarkEnabled("loop-vectorize"));
+    EXPECT_TRUE(engine->isFailedOptRemarkEnabled("loop-unroll"));
+    EXPECT_FALSE(engine->isMissedOptRemarkEnabled("inline"));
+  }
+}
+
 // Test that remarks can be linked together using RemarkId.
 TEST(Remark, TestRemarkLinking) {
   testing::internal::CaptureStderr();



More information about the Mlir-commits mailing list