[Mlir-commits] [mlir] [MLIR][arith] Fold or(a, or(a, b)) to or(a, b) (PR #228386)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Oct 2 03:35:47 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Chibuoyim (Wilson) Ogbonna (bruteforceboy)
<details>
<summary>Changes</summary>
`arith.andi` already folds `and(a, and(a, b))` to `and(a, b)`, but `arith.ori` doesn't perform the equivalent fold, so using canonicalize misses this opportunity.
Generalize the existing helper and use it for both ops.
---
Full diff: https://github.com/llvm/llvm-project/pull/228386.diff
2 Files Affected:
- (modified) mlir/lib/Dialect/Arith/IR/ArithOps.cpp (+10-4)
- (modified) mlir/test/Dialect/Arith/canonicalize.mlir (+54)
``````````diff
diff --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
index 01d0c18670cb8..be02143ea2771 100644
--- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
+++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
@@ -1132,11 +1132,13 @@ Speculation::Speculatability arith::RemSIOp::getSpeculatability() {
// AndIOp
//===----------------------------------------------------------------------===//
-/// Fold `and(a, and(a, b))` to `and(a, b)`
-static Value foldAndIofAndI(arith::AndIOp op) {
+/// Fold `op(a, op(a, b))` to `op(a, b)` for an associative, commutative and
+/// idempotent `op` (e.g. `and`, `or`).
+template <typename OpTy>
+static Value foldIdempotentOfSameOp(OpTy op) {
for (bool reversePrev : {false, true}) {
auto prev = (reversePrev ? op.getRhs() : op.getLhs())
- .getDefiningOp<arith::AndIOp>();
+ .template getDefiningOp<OpTy>();
if (!prev)
continue;
@@ -1170,7 +1172,7 @@ OpFoldResult arith::AndIOp::fold(FoldAdaptor adaptor) {
return Builder(getContext()).getZeroAttr(getType());
/// and(a, and(a, b)) -> and(a, b)
- if (Value result = foldAndIofAndI(*this))
+ if (Value result = foldIdempotentOfSameOp(*this))
return result;
return constFoldBinaryOp<IntegerAttr>(
@@ -1204,6 +1206,10 @@ OpFoldResult arith::OrIOp::fold(FoldAdaptor adaptor) {
intValue.isAllOnes())
return getLhs().getDefiningOp<XOrIOp>().getRhs();
+ /// or(a, or(a, b)) -> or(a, b)
+ if (Value result = foldIdempotentOfSameOp(*this))
+ return result;
+
return constFoldBinaryOp<IntegerAttr>(
adaptor.getOperands(),
[](APInt a, const APInt &b) { return std::move(a) | b; });
diff --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir
index 8a46c963f02d7..9c512cd605d7d 100644
--- a/mlir/test/Dialect/Arith/canonicalize.mlir
+++ b/mlir/test/Dialect/Arith/canonicalize.mlir
@@ -4437,6 +4437,60 @@ func.func @andand3(%a : i32, %b : i32) -> i32 {
// -----
+/// or(a, or(a, b)) -> or(a, b)
+
+// CHECK-LABEL: @oror0
+// CHECK-SAME: (%[[A:.*]]: i32, %[[B:.*]]: i32)
+// CHECK: %[[RES:.*]] = arith.ori %[[A]], %[[B]] : i32
+// CHECK: return %[[RES]]
+func.func @oror0(%a : i32, %b : i32) -> i32 {
+ %c = arith.ori %a, %b : i32
+ %res = arith.ori %a, %c : i32
+ return %res : i32
+}
+
+// CHECK-LABEL: @oror1
+// CHECK-SAME: (%[[A:.*]]: i32, %[[B:.*]]: i32)
+// CHECK: %[[RES:.*]] = arith.ori %[[A]], %[[B]] : i32
+// CHECK: return %[[RES]]
+func.func @oror1(%a : i32, %b : i32) -> i32 {
+ %c = arith.ori %a, %b : i32
+ %res = arith.ori %c, %a : i32
+ return %res : i32
+}
+
+// CHECK-LABEL: @oror2
+// CHECK-SAME: (%[[A:.*]]: i32, %[[B:.*]]: i32)
+// CHECK: %[[RES:.*]] = arith.ori %[[A]], %[[B]] : i32
+// CHECK: return %[[RES]]
+func.func @oror2(%a : i32, %b : i32) -> i32 {
+ %c = arith.ori %a, %b : i32
+ %res = arith.ori %b, %c : i32
+ return %res : i32
+}
+
+// CHECK-LABEL: @oror3
+// CHECK-SAME: (%[[A:.*]]: i32, %[[B:.*]]: i32)
+// CHECK: %[[RES:.*]] = arith.ori %[[A]], %[[B]] : i32
+// CHECK: return %[[RES]]
+func.func @oror3(%a : i32, %b : i32) -> i32 {
+ %c = arith.ori %a, %b : i32
+ %res = arith.ori %c, %b : i32
+ return %res : i32
+}
+
+// CHECK-LABEL: @oror_vector
+// CHECK-SAME: (%[[A:.*]]: vector<4xi32>, %[[B:.*]]: vector<4xi32>)
+// CHECK: %[[RES:.*]] = arith.ori %[[A]], %[[B]] : vector<4xi32>
+// CHECK: return %[[RES]]
+func.func @oror_vector(%a : vector<4xi32>, %b : vector<4xi32>) -> vector<4xi32> {
+ %c = arith.ori %a, %b : vector<4xi32>
+ %res = arith.ori %c, %a : vector<4xi32>
+ return %res : vector<4xi32>
+}
+
+// -----
+
// CHECK-LABEL: @truncIShrSIToTrunciShrUI
// CHECK-SAME: (%[[A:.+]]: i64)
// CHECK-NEXT: %[[C32:.+]] = arith.constant 32 : i64
``````````
</details>
https://github.com/llvm/llvm-project/pull/228386
More information about the Mlir-commits
mailing list