[Mlir-commits] [mlir] [MLIR][Rewrite] Support unqualified pattern names in disable/enable-patterns (PR #188988)
Mehdi Amini
llvmlistbot at llvm.org
Fri Mar 27 05:59:17 PDT 2026
https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/188988
FrozenRewritePatternSet previously required exact string matching for disable-patterns and enable-patterns filter options. Pattern debug names are auto-generated as fully qualified typenames (e.g., "(anonymous namespace)::FooBar"), but users often want to filter by just the class name (e.g., "FooBar").
This change adds support for unqualified name matching: if a user-supplied filter label contains no "::", it is also matched against the unqualified part of the pattern debug name (the suffix after the last "::"). Labels containing "::" still require exact matching as before.
A new test exercises disable/enable filtering by unqualified name for a pattern living in an anonymous namespace.
Fixes #120489
Assisted-by: Claude Code
>From 7af34054d969704c21c1a1d6d62b65fb945c8d07 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Thu, 26 Mar 2026 16:03:22 -0700
Subject: [PATCH] [MLIR][Rewrite] Support unqualified pattern names in
disable/enable-patterns
FrozenRewritePatternSet previously required exact string matching for
disable-patterns and enable-patterns filter options. Pattern debug names
are auto-generated as fully qualified typenames (e.g.,
"(anonymous namespace)::FooBar"), but users often want to filter by just
the class name (e.g., "FooBar").
This change adds support for unqualified name matching: if a user-supplied
filter label contains no "::", it is also matched against the unqualified
part of the pattern debug name (the suffix after the last "::"). Labels
containing "::" still require exact matching as before.
A new test exercises disable/enable filtering by unqualified name for a
pattern living in an anonymous namespace.
Fixes #120489
Assisted-by: Claude Code
---
mlir/lib/Rewrite/FrozenRewritePatternSet.cpp | 33 ++++++++++++++-----
.../Transforms/test-canonicalize-filter.mlir | 23 +++++++++++++
2 files changed, 48 insertions(+), 8 deletions(-)
diff --git a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
index d4cd24372efbc..14a05d0f27b6c 100644
--- a/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
+++ b/mlir/lib/Rewrite/FrozenRewritePatternSet.cpp
@@ -64,10 +64,6 @@ FrozenRewritePatternSet::FrozenRewritePatternSet(
RewritePatternSet &&patterns, ArrayRef<std::string> disabledPatternLabels,
ArrayRef<std::string> enabledPatternLabels)
: impl(std::make_shared<Impl>()) {
- DenseSet<StringRef> disabledPatterns, enabledPatterns;
- disabledPatterns.insert_range(disabledPatternLabels);
- enabledPatterns.insert_range(enabledPatternLabels);
-
// Functor used to walk all of the operations registered in the context. This
// is useful for patterns that get applied to multiple operations, such as
// interface and trait based patterns.
@@ -83,20 +79,41 @@ FrozenRewritePatternSet::FrozenRewritePatternSet(
impl->nativeOpSpecificPatternList.push_back(std::move(pattern));
};
+ // Returns true if `label` (a pattern's debug name or label) matches
+ // `userLabel` (a user-supplied filter string). Supports both exact matching
+ // and unqualified-name matching: if `userLabel` contains no "::", it is also
+ // compared against the unqualified part of `label` (after the last "::").
+ // This allows users to write, e.g., `disable-patterns=FooBar` instead of
+ // `disable-patterns=(anonymous namespace)::FooBar`.
+ auto matchesLabel = [](StringRef label, StringRef userLabel) {
+ if (label == userLabel)
+ return true;
+ if (!userLabel.contains("::")) {
+ size_t pos = label.rfind("::");
+ if (pos != StringRef::npos && label.substr(pos + 2) == userLabel)
+ return true;
+ }
+ return false;
+ };
+
for (std::unique_ptr<RewritePattern> &pat : patterns.getNativePatterns()) {
// Don't add patterns that haven't been enabled by the user.
- if (!enabledPatterns.empty()) {
+ if (!enabledPatternLabels.empty()) {
auto isEnabledFn = [&](StringRef label) {
- return enabledPatterns.count(label);
+ return llvm::any_of(enabledPatternLabels, [&](StringRef ul) {
+ return matchesLabel(label, ul);
+ });
};
if (!isEnabledFn(pat->getDebugName()) &&
llvm::none_of(pat->getDebugLabels(), isEnabledFn))
continue;
}
// Don't add patterns that have been disabled by the user.
- if (!disabledPatterns.empty()) {
+ if (!disabledPatternLabels.empty()) {
auto isDisabledFn = [&](StringRef label) {
- return disabledPatterns.count(label);
+ return llvm::any_of(disabledPatternLabels, [&](StringRef ul) {
+ return matchesLabel(label, ul);
+ });
};
if (isDisabledFn(pat->getDebugName()) ||
llvm::any_of(pat->getDebugLabels(), isDisabledFn))
diff --git a/mlir/test/Transforms/test-canonicalize-filter.mlir b/mlir/test/Transforms/test-canonicalize-filter.mlir
index dba5f05e84345..ad1784e9e5cb4 100644
--- a/mlir/test/Transforms/test-canonicalize-filter.mlir
+++ b/mlir/test/Transforms/test-canonicalize-filter.mlir
@@ -1,6 +1,12 @@
// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(canonicalize))' | FileCheck %s --check-prefix=NO_FILTER
// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(canonicalize{enable-patterns=TestRemoveOpWithInnerOps}))' | FileCheck %s --check-prefix=FILTER_ENABLE
// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(canonicalize{disable-patterns=TestRemoveOpWithInnerOps}))' | FileCheck %s --check-prefix=FILTER_DISABLE
+// Test that unqualified names (without namespace prefix) also work for filtering.
+// FoldToCallOpPattern is in an anonymous namespace, so its debug name is
+// "(anonymous namespace)::FoldToCallOpPattern". Filtering by the unqualified
+// name "FoldToCallOpPattern" should still work.
+// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(canonicalize{disable-patterns=FoldToCallOpPattern}))' | FileCheck %s --check-prefix=DISABLE_ANON
+// RUN: mlir-opt %s -pass-pipeline='builtin.module(func.func(canonicalize{enable-patterns=FoldToCallOpPattern}))' | FileCheck %s --check-prefix=ENABLE_ANON
// NO_FILTER-LABEL: func @remove_op_with_inner_ops_pattern
// NO_FILTER-NEXT: return
@@ -14,3 +20,20 @@ func.func @remove_op_with_inner_ops_pattern() {
}) : () -> ()
return
}
+
+// Test filtering by unqualified pattern name (without namespace prefix).
+// FoldToCallOpPattern lives in an anonymous namespace; its debug name is
+// "(anonymous namespace)::FoldToCallOpPattern". Filters without "::" should
+// match against the unqualified part after the last "::".
+
+// NO_FILTER-LABEL: func @fold_to_call_unqualified_filter
+// NO_FILTER-NEXT: call @callee
+// DISABLE_ANON-LABEL: func @fold_to_call_unqualified_filter
+// DISABLE_ANON-NEXT: "test.fold_to_call_op"
+// ENABLE_ANON-LABEL: func @fold_to_call_unqualified_filter
+// ENABLE_ANON-NEXT: call @callee
+func.func private @callee()
+func.func @fold_to_call_unqualified_filter() {
+ "test.fold_to_call_op"() {callee = @callee} : () -> ()
+ return
+}
More information about the Mlir-commits
mailing list