[Mlir-commits] [mlir] [mlir] Add option to ignore commutativity in OperationEquality (PR #181507)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sun Feb 15 14:00:47 PST 2026
https://github.com/jumerckx updated https://github.com/llvm/llvm-project/pull/181507
>From 1b39f5788bac7fa74aff16c90ce6dd32c27249a4 Mon Sep 17 00:00:00 2001
From: jumerckx <31353884+jumerckx at users.noreply.github.com>
Date: Sat, 14 Feb 2026 17:22:12 +0100
Subject: [PATCH 1/4] fix docstring
---
mlir/include/mlir/IR/OperationSupport.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mlir/include/mlir/IR/OperationSupport.h b/mlir/include/mlir/IR/OperationSupport.h
index 1ff7c56ddca38..a05e0ae387164 100644
--- a/mlir/include/mlir/IR/OperationSupport.h
+++ b/mlir/include/mlir/IR/OperationSupport.h
@@ -1348,8 +1348,8 @@ struct OperationEquivalence {
/// Helper that can be used with `computeHash` above to ignore operation
/// operands/result mapping.
static llvm::hash_code ignoreHashValue(Value) { return llvm::hash_code{}; }
- /// Helper that can be used with `computeHash` above to ignore operation
- /// operands/result mapping.
+ /// Helper that can be used with `computeHash` to compute the hash value
+ /// of operands/results directly.
static llvm::hash_code directHashValue(Value v) { return hash_value(v); }
/// Compare two operations (including their regions) and return if they are
>From 179b5806470f4d301f410de5937f344f5f5cec9f Mon Sep 17 00:00:00 2001
From: jumerckx <31353884+jumerckx at users.noreply.github.com>
Date: Sat, 14 Feb 2026 17:22:41 +0100
Subject: [PATCH 2/4] IgnoreCommutativity flag
---
mlir/include/mlir/IR/OperationSupport.h | 6 +++++-
mlir/lib/IR/OperationSupport.cpp | 5 +++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/mlir/include/mlir/IR/OperationSupport.h b/mlir/include/mlir/IR/OperationSupport.h
index a05e0ae387164..3b79f263568dd 100644
--- a/mlir/include/mlir/IR/OperationSupport.h
+++ b/mlir/include/mlir/IR/OperationSupport.h
@@ -1331,7 +1331,11 @@ struct OperationEquivalence {
// When provided, the properties attached to the operation are ignored.
IgnoreProperties = 4,
- LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IgnoreProperties)
+ // When provided, the commutativity of the operation is ignored, and
+ // operands are compared in an order-sensitive way.
+ IgnoreCommutativity = 8,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IgnoreCommutativity)
};
/// Compute a hash for the given operation.
diff --git a/mlir/lib/IR/OperationSupport.cpp b/mlir/lib/IR/OperationSupport.cpp
index 2a37f3860fe00..3ff61daaac60b 100644
--- a/mlir/lib/IR/OperationSupport.cpp
+++ b/mlir/lib/IR/OperationSupport.cpp
@@ -689,7 +689,8 @@ llvm::hash_code OperationEquivalence::computeHash(
hash = llvm::hash_combine(hash, op->getLoc());
// - Operands
- if (op->hasTrait<mlir::OpTrait::IsCommutative>() &&
+ if (!(flags & Flags::IgnoreCommutativity) &&
+ op->hasTrait<mlir::OpTrait::IsCommutative>() &&
op->getNumOperands() > 0) {
size_t operandHash = hashOperands(op->getOperand(0));
for (auto operand : op->getOperands().drop_front())
@@ -854,7 +855,7 @@ OperationEquivalence::isRegionEquivalentTo(Region *lhs, Region *rhs,
return false;
// 2. Compare operands.
- if (checkCommutativeEquivalent &&
+ if (!(flags & IgnoreCommutativity) && checkCommutativeEquivalent &&
lhs->hasTrait<mlir::OpTrait::IsCommutative>()) {
auto lhsRange = lhs->getOperands();
auto rhsRange = rhs->getOperands();
>From 0ea2d2e4aa63e3cf2416d89d59d0ec3363dcbcad Mon Sep 17 00:00:00 2001
From: jumerckx <julesmerckx12 at gmail.com>
Date: Sun, 15 Feb 2026 21:35:20 +0100
Subject: [PATCH 3/4] add ignore_commutativity attribute check in test pass
---
mlir/test/lib/IR/TestOperationEquals.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mlir/test/lib/IR/TestOperationEquals.cpp b/mlir/test/lib/IR/TestOperationEquals.cpp
index 03cf5f4facf82..a8ff7752ebb2c 100644
--- a/mlir/test/lib/IR/TestOperationEquals.cpp
+++ b/mlir/test/lib/IR/TestOperationEquals.cpp
@@ -35,6 +35,8 @@ struct TestOperationEqualPass
OperationEquivalence::Flags flags{};
if (!first->hasAttr("strict_loc_check"))
flags |= OperationEquivalence::IgnoreLocations;
+ if (first->hasAttr("ignore_commutativity"))
+ flags |= OperationEquivalence::IgnoreCommutativity;
if (OperationEquivalence::isEquivalentTo(first, &module.getBody()->back(),
flags))
llvm::outs() << " compares equals.\n";
>From b75ca8fdd9a312d0c7ba0c9e587033d1b00f0d9f Mon Sep 17 00:00:00 2001
From: jumerckx <julesmerckx12 at gmail.com>
Date: Sun, 15 Feb 2026 21:31:54 +0100
Subject: [PATCH 4/4] Add test for ignore_commutativity that works without
further changes to equality
---
mlir/test/IR/operation-equality.mlir | 15 +++++++++++++++
mlir/test/lib/IR/TestOperationEquals.cpp | 17 ++++++++++++-----
2 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/mlir/test/IR/operation-equality.mlir b/mlir/test/IR/operation-equality.mlir
index f382d7d0fbf1b..7bdbfdd19a62d 100644
--- a/mlir/test/IR/operation-equality.mlir
+++ b/mlir/test/IR/operation-equality.mlir
@@ -184,3 +184,18 @@
%0:2 = "test.producer"() : () -> (i32, i32)
"test.consumer"(%0#1, %0#0) : (i32, i32) -> ()
}) : () -> ()
+
+// -----
+
+// CHECK-LABEL: test.ignore_commutatively_equal_permutation
+// CHECK-SAME: compares NOT equals
+
+builtin.module attributes {test.includes_setup} {
+ %0:2 = "test.producer"() : () -> (i32, i32)
+ "test.ignore_commutatively_equal_permutation"() ({
+ arith.addi %0#0, %0#1 : i32
+ }) { ignore_commutativity } : () -> ()
+ "test.ignore_commutatively_equal_permutation"() ({
+ arith.addi %0#1, %0#0 : i32
+ }) { ignore_commutativity } : () -> ()
+}
diff --git a/mlir/test/lib/IR/TestOperationEquals.cpp b/mlir/test/lib/IR/TestOperationEquals.cpp
index a8ff7752ebb2c..cf05056ff613e 100644
--- a/mlir/test/lib/IR/TestOperationEquals.cpp
+++ b/mlir/test/lib/IR/TestOperationEquals.cpp
@@ -23,13 +23,20 @@ struct TestOperationEqualPass
ModuleOp module = getOperation();
// Expects two operations at the top-level:
int opCount = module.getBody()->getOperations().size();
- if (opCount != 2) {
- module.emitError() << "expected 2 top-level ops in the module, got "
- << opCount;
- return signalPassFailure();
+ if (module->hasAttr("test.includes_setup")) {
+ if (opCount < 2) {
+ module.emitError() << "expected at least 2 top-level ops in the module, got "
+ << opCount;
+ return signalPassFailure();
+ }
+ } else if (opCount != 2) {
+ module.emitError() << "expected 2 top-level ops in the module, got "
+ << opCount;
+ return signalPassFailure();
}
+ Operation* second = &module.getBody()->back();
+ Operation* first = second->getPrevNode();
- Operation *first = &module.getBody()->front();
llvm::outs() << first->getName().getStringRef() << " with attr "
<< first->getDiscardableAttrDictionary();
OperationEquivalence::Flags flags{};
More information about the Mlir-commits
mailing list