[mlir][arith] Fold `andi x, not(x)` to zero
authorMarkus Böck <markus.boeck02@gmail.com>
Wed, 24 Aug 2022 11:09:46 +0000 (13:09 +0200)
committerMarkus Böck <markus.boeck02@gmail.com>
Wed, 24 Aug 2022 11:10:01 +0000 (13:10 +0200)
A bitwise and with the bitwise negate of itself is always 0, regardless of the integer type. This patch adds detection of such a pattern in `arith.andi`s `fold` method.

Differential Revision: https://reviews.llvm.org/D131860

mlir/lib/Dialect/Arithmetic/IR/ArithmeticOps.cpp
mlir/test/Dialect/Arithmetic/canonicalize.mlir

index 8546a37..11e64ff 100644 (file)
@@ -574,6 +574,16 @@ OpFoldResult arith::AndIOp::fold(ArrayRef<Attribute> operands) {
   APInt intValue;
   if (matchPattern(getRhs(), m_ConstantInt(&intValue)) && intValue.isAllOnes())
     return getLhs();
+  /// and(x, not(x)) -> 0
+  if (matchPattern(getRhs(), m_Op<XOrIOp>(matchers::m_Val(getLhs()),
+                                          m_ConstantInt(&intValue))) &&
+      intValue.isAllOnes())
+    return IntegerAttr::get(getType(), 0);
+  /// and(not(x), x) -> 0
+  if (matchPattern(getLhs(), m_Op<XOrIOp>(matchers::m_Val(getRhs()),
+                                          m_ConstantInt(&intValue))) &&
+      intValue.isAllOnes())
+    return IntegerAttr::get(getType(), 0);
 
   return constFoldBinaryOp<IntegerAttr>(
       operands, [](APInt a, const APInt &b) { return std::move(a) & b; });
index f99a070..a1ab1be 100644 (file)
@@ -1532,3 +1532,30 @@ func.func @test_remf_vec() -> (vector<4xf32>) {
   %0 = arith.remf %v1, %v2 : vector<4xf32>
   return %0 : vector<4xf32>
 }
+
+// -----
+
+// CHECK-LABEL: @test_andi_not_fold_rhs(
+// CHECK-SAME: %[[ARG0:[[:alnum:]]+]]
+// CHECK: %[[C:.*]] = arith.constant 0 : index
+// CHECK: return %[[C]]
+
+func.func @test_andi_not_fold_rhs(%arg0 : index) -> index {
+    %0 = arith.constant -1 : index
+    %1 = arith.xori %arg0, %0 : index
+    %2 = arith.andi %arg0, %1 : index
+    return %2 : index
+}
+
+
+// CHECK-LABEL: @test_andi_not_fold_lhs(
+// CHECK-SAME: %[[ARG0:[[:alnum:]]+]]
+// CHECK: %[[C:.*]] = arith.constant 0 : index
+// CHECK: return %[[C]]
+
+func.func @test_andi_not_fold_lhs(%arg0 : index) -> index {
+    %0 = arith.constant -1 : index
+    %1 = arith.xori %arg0, %0 : index
+    %2 = arith.andi %1, %arg0 : index
+    return %2 : index
+}