[llvm] [InstCombine] Fold bool (((A & B) ^ 1) & C) & A into ((B ^ 1) & A) & C (PR #78150)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 15 03:47:21 PST 2024


https://github.com/adamszilagyi created https://github.com/llvm/llvm-project/pull/78150

Issue #75004

Proof: https://alive2.llvm.org/ce/z/fQ62US

>From bf66997fdd12279ef6d3261ccbb002716c2d0f7a Mon Sep 17 00:00:00 2001
From: Adam Szilagyi <adam.szilagyi97 at gmail.com>
Date: Mon, 15 Jan 2024 12:41:25 +0100
Subject: [PATCH] [InstCombine] Fold bool (((A & B) ^ 1) & C) & A into ((B ^ 1)
 & A) & C

---
 .../InstCombine/InstCombineAndOrXor.cpp          | 10 ++++++++++
 llvm/test/Transforms/InstCombine/and.ll          | 16 ++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 0620752e3213945..21b2a6f181fe7a3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2539,6 +2539,16 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
         return BinaryOperator::CreateAnd(Op1, Builder.CreateNot(C));
     }
 
+    // (((A & B) ^ 1) & C) & A -> ((B ^ 1) & A) & C
+    if (match(&I, m_And(m_And(m_Xor(m_And(m_Value(A), m_Value(B)), m_One()),
+                              m_Value(C)),
+                        m_Value(A))) &&
+        A->getType()->isIntOrIntVectorTy(1) &&
+        B->getType()->isIntOrIntVectorTy(1) &&
+        C->getType()->isIntOrIntVectorTy(1))
+      return BinaryOperator::CreateAnd(
+          Builder.CreateAnd(Builder.CreateXor(B, 1), A), C);
+
     // (A | B) & (~A ^ B) -> A & B
     // (A | B) & (B ^ ~A) -> A & B
     // (B | A) & (~A ^ B) -> A & B
diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 2e37fee07cc47bf..ee7d4ecf18f576e 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -2411,6 +2411,22 @@ define i8 @negate_lowbitmask_use1(i8 %x, i8 %y) {
   ret i8 %r
 }
 
+define i32 @fold_and_and_xor1_and(i1 %k, i1 %c, i1 %c1) {
+; CHECK-LABEL: @fold_and_and_xor1_and(
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[C:%.*]], true
+; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[K:%.*]]
+; CHECK-NEXT:    [[NARROW:%.*]] = and i1 [[TMP2]], [[C1:%.*]]
+; CHECK-NEXT:    [[COND:%.*]] = zext i1 [[NARROW]] to i32
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %and12 = and i1 %k, %c
+  %not.and12 = xor i1 %and12, true
+  %1 = and i1 %not.and12, %c1
+  %narrow = and i1 %k, %1
+  %cond = zext i1 %narrow to i32
+  ret i32 %cond
+}
+
 ; negative test
 
 define i8 @negate_lowbitmask_use2(i8 %x, i8 %y) {



More information about the llvm-commits mailing list