[Mlir-commits] [mlir] [mlir][Rewrite] Add match failure/success diagnostics to `PatternApplicator` (PR #180165)
Matthias Springer
llvmlistbot at llvm.org
Fri Feb 6 02:59:58 PST 2026
https://github.com/matthias-springer created https://github.com/llvm/llvm-project/pull/180165
It is a best practice to write "negative" test cases to check that a (canonicalization) does not accidentally apply to IR where it should not match. To that end, users have to FileCheck for the original IR to make sure that no pattern was applied.
This commit adds a new testing flag to `mlir-opt`: `-mlir-emit-pattern-match-diagnostics="match-success"` emits a diagnostic remark for every successful pattern application. Together with `-verify-diagnostics`, this flag can be used to ensure that no pattern was applied to a certain piece of IR.
Note: This flag was motivated by a test case pattern that I found in a downstream project:
```
// RUN: mlir-opt -split-input-file %s -canonicalize -debug 2>&1 | FileCheck %s
// CHECK: Trying to match "(pattern name)"
// CHECK-NEXT: matchAndRewrite failed
```
>From ce26915d706f799de994cd93336e9fed30e6ced3 Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Fri, 6 Feb 2026 10:53:35 +0000
Subject: [PATCH] [mlir][Rewrite] Add match failure/success diagnostics to
`PatternApplicator`
---
mlir/include/mlir/Rewrite/PatternApplicator.h | 3 +
mlir/lib/Rewrite/PatternApplicator.cpp | 55 +++++++++++++++++++
mlir/lib/Tools/mlir-opt/MlirOptMain.cpp | 2 +
.../test-pattern-applicator-diagnostics.mlir | 10 ++++
4 files changed, 70 insertions(+)
create mode 100644 mlir/test/Rewrite/test-pattern-applicator-diagnostics.mlir
diff --git a/mlir/include/mlir/Rewrite/PatternApplicator.h b/mlir/include/mlir/Rewrite/PatternApplicator.h
index f7871f819a273..0fb00154a67b7 100644
--- a/mlir/include/mlir/Rewrite/PatternApplicator.h
+++ b/mlir/include/mlir/Rewrite/PatternApplicator.h
@@ -96,6 +96,9 @@ class PatternApplicator {
std::unique_ptr<detail::PDLByteCodeMutableState> mutableByteCodeState;
};
+/// Register command-line options for the pattern applicator.
+void registerPatternApplicatorCLOptions();
+
} // namespace mlir
#endif // MLIR_REWRITE_PATTERNAPPLICATOR_H
diff --git a/mlir/lib/Rewrite/PatternApplicator.cpp b/mlir/lib/Rewrite/PatternApplicator.cpp
index e1b56fd6efda0..1d64dc2df1706 100644
--- a/mlir/lib/Rewrite/PatternApplicator.cpp
+++ b/mlir/lib/Rewrite/PatternApplicator.cpp
@@ -13,7 +13,10 @@
#include "mlir/Rewrite/PatternApplicator.h"
#include "ByteCode.h"
+#include "mlir/IR/Diagnostics.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DebugLog.h"
+#include "llvm/Support/ManagedStatic.h"
#ifndef NDEBUG
#include "llvm/ADT/ScopeExit.h"
@@ -24,6 +27,41 @@
using namespace mlir;
using namespace mlir::detail;
+namespace {
+enum PatternMatchingRemarkMode {
+ /// Do not emit any diagnostic remarks for pattern matching.
+ None,
+ /// Emit a remark for successful pattern matching.
+ MatchSuccess,
+ /// Emit a remark for failed pattern matching.
+ MatchFailure,
+ /// Emit a remark for both successful and failed pattern matching.
+ MatchSuccessAndFailure,
+};
+struct PatternApplicatorOptions {
+ llvm::cl::opt<PatternMatchingRemarkMode> mode{
+ "mlir-emit-pattern-match-diagnostics",
+ llvm::cl::desc("Emit diagnostic remarks for pattern matching"),
+ llvm::cl::init(PatternMatchingRemarkMode::None), // default value
+ llvm::cl::values(
+ clEnumValN(PatternMatchingRemarkMode::None, "none", "no remarks"),
+ clEnumValN(PatternMatchingRemarkMode::MatchSuccess, "match-success",
+ "pattern match success"),
+ clEnumValN(PatternMatchingRemarkMode::MatchFailure, "match-failure",
+ "pattern match failure"),
+ clEnumValN(PatternMatchingRemarkMode::MatchSuccessAndFailure,
+ "match-success-and-failure",
+ "pattern match success and failure"))};
+};
+} // namespace
+
+static llvm::ManagedStatic<PatternApplicatorOptions> clOptions;
+
+void mlir::registerPatternApplicatorCLOptions() {
+ // Make sure that the options struct has been initialized.
+ *clOptions;
+}
+
PatternApplicator::PatternApplicator(
const FrozenRewritePatternSet &frozenPatternList)
: frozenPatternList(frozenPatternList) {
@@ -220,9 +258,26 @@ LogicalResult PatternApplicator::matchAndRewrite(
llvm::scope_exit resetListenerCallback(
[&] { rewriter.setListener(oldListener); });
#endif
+ Location loc = op->getLoc();
result = pattern->matchAndRewrite(op, rewriter);
LDBG() << " -> matchAndRewrite "
<< (succeeded(result) ? "successful" : "failed");
+ bool shouldEmitMatchSuccessRemark =
+ clOptions->mode == PatternMatchingRemarkMode::MatchSuccess ||
+ clOptions->mode ==
+ PatternMatchingRemarkMode::MatchSuccessAndFailure;
+ bool shouldEmitMatchFailureRemark =
+ clOptions->mode == PatternMatchingRemarkMode::MatchFailure ||
+ clOptions->mode ==
+ PatternMatchingRemarkMode::MatchSuccessAndFailure;
+ if (succeeded(result) && shouldEmitMatchSuccessRemark) {
+ mlir::emitRemark(loc)
+ << "pattern match success: " << pattern->getDebugName();
+ }
+ if (failed(result) && shouldEmitMatchFailureRemark) {
+ mlir::emitRemark(loc)
+ << "pattern match failure: " << pattern->getDebugName();
+ }
}
// Process the result of the pattern application.
diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
index 560ef6effd2fb..4d03ae66dbea2 100644
--- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
+++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp
@@ -28,6 +28,7 @@
#include "mlir/Pass/PassManager.h"
#include "mlir/Pass/PassRegistry.h"
#include "mlir/Remark/RemarkStreamer.h"
+#include "mlir/Rewrite/PatternApplicator.h"
#include "mlir/Support/FileUtilities.h"
#include "mlir/Support/Timing.h"
#include "mlir/Support/ToolUtilities.h"
@@ -688,6 +689,7 @@ std::string mlir::registerCLIOptions(llvm::StringRef toolName,
registerMLIRContextCLOptions();
registerPassManagerCLOptions();
registerDefaultTimingManagerCLOptions();
+ registerPatternApplicatorCLOptions();
tracing::DebugCounter::registerCLOptions();
// Build the list of dialects as a header for the --help message.
diff --git a/mlir/test/Rewrite/test-pattern-applicator-diagnostics.mlir b/mlir/test/Rewrite/test-pattern-applicator-diagnostics.mlir
new file mode 100644
index 0000000000000..77cc465db323b
--- /dev/null
+++ b/mlir/test/Rewrite/test-pattern-applicator-diagnostics.mlir
@@ -0,0 +1,10 @@
+// RUN: mlir-opt %s -canonicalize -mlir-emit-pattern-match-diagnostics="match-success"
+
+func.func @tensor_empty_canonicalization() -> tensor<?xf32> {
+ %c4 = arith.constant 4 : index
+ // Do not match "(anonymous namespace)::", as it may render differently
+ // depending on the C++ compiler.
+ // expected-remark-re @+1 {{pattern match success: {{.*}}ReplaceEmptyTensorStaticShapeDims}}
+ %r = tensor.empty(%c4) : tensor<?xf32>
+ return %r : tensor<?xf32>
+}
More information about the Mlir-commits
mailing list