[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