[llvm] 2614672 - [InstCombine] Fold ((cst << x) & 1) --> x == 0 when cst is odd (#79772)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 5 07:27:57 PST 2024
Author: elhewaty
Date: 2024-02-05T16:27:53+01:00
New Revision: 2614672cc12258d2b07db2657e475ad70e01d5ba
URL: https://github.com/llvm/llvm-project/commit/2614672cc12258d2b07db2657e475ad70e01d5ba
DIFF: https://github.com/llvm/llvm-project/commit/2614672cc12258d2b07db2657e475ad70e01d5ba.diff
LOG: [InstCombine] Fold ((cst << x) & 1) --> x == 0 when cst is odd (#79772)
Fold ((cst << x) & 1) to zext(x == 0) when cst is odd.
Fixes: https://github.com/llvm/llvm-project/issues/73384
Alive2: https://alive2.llvm.org/ce/z/5RbaK6
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/and.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 1cfa797be2207..6ca4d6d673068 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2263,10 +2263,12 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
Value *X, *Y;
- if (match(Op0, m_OneUse(m_LogicalShift(m_One(), m_Value(X)))) &&
+ const APInt *C;
+ if ((match(Op0, m_OneUse(m_LogicalShift(m_One(), m_Value(X)))) ||
+ (match(Op0, m_OneUse(m_Shl(m_APInt(C), m_Value(X)))) && (*C)[0])) &&
match(Op1, m_One())) {
- // (1 << X) & 1 --> zext(X == 0)
// (1 >> X) & 1 --> zext(X == 0)
+ // (C << X) & 1 --> zext(X == 0), when C is odd
Value *IsZero = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, 0));
return new ZExtInst(IsZero, Ty);
}
@@ -2289,7 +2291,6 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
isKnownToBeAPowerOfTwo(Y, /*OrZero*/ true, /*Depth*/ 0, &I))
return BinaryOperator::CreateAnd(Builder.CreateNot(X), Y);
- const APInt *C;
if (match(Op1, m_APInt(C))) {
const APInt *XorC;
if (match(Op0, m_OneUse(m_Xor(m_Value(X), m_APInt(XorC))))) {
diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 2e37fee07cc47..c5d8b578b4dc9 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -7,6 +7,92 @@ declare void @use32(i32)
; There should be no 'and' instructions left in any test.
+define i32 @test_with_1(i32 %x) {
+; CHECK-LABEL: @test_with_1(
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP1]] to i32
+; CHECK-NEXT: ret i32 [[AND]]
+;
+ %shl = shl i32 1, %x
+ %and = and i32 %shl, 1
+ ret i32 %and
+}
+
+define i32 @test_with_3(i32 %x) {
+; CHECK-LABEL: @test_with_3(
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP1]] to i32
+; CHECK-NEXT: ret i32 [[AND]]
+;
+ %shl = shl i32 3, %x
+ %and = and i32 %shl, 1
+ ret i32 %and
+}
+
+define i32 @test_with_5(i32 %x) {
+; CHECK-LABEL: @test_with_5(
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP1]] to i32
+; CHECK-NEXT: ret i32 [[AND]]
+;
+ %shl = shl i32 5, %x
+ %and = and i32 %shl, 1
+ ret i32 %and
+}
+
+define i32 @test_with_neg_5(i32 %x) {
+; CHECK-LABEL: @test_with_neg_5(
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP1]] to i32
+; CHECK-NEXT: ret i32 [[AND]]
+;
+ %shl = shl i32 -5, %x
+ %and = and i32 %shl, 1
+ ret i32 %and
+}
+
+define i32 @test_with_even(i32 %x) {
+; CHECK-LABEL: @test_with_even(
+; CHECK-NEXT: ret i32 0
+;
+ %shl = shl i32 4, %x
+ %and = and i32 %shl, 1
+ ret i32 %and
+}
+
+define <2 x i32> @test_vec(<2 x i32> %x) {
+; CHECK-LABEL: @test_vec(
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i32> [[X:%.*]], zeroinitializer
+; CHECK-NEXT: [[AND:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i32>
+; CHECK-NEXT: ret <2 x i32> [[AND]]
+;
+ %shl = shl <2 x i32> <i32 5, i32 5>, %x
+ %and = and <2 x i32> %shl, <i32 1, i32 1>
+ ret <2 x i32> %and
+}
+
+define i32 @test_with_neg_even(i32 %x) {
+; CHECK-LABEL: @test_with_neg_even(
+; CHECK-NEXT: ret i32 0
+;
+ %shl = shl i32 -4, %x
+ %and = and i32 %shl, 1
+ ret i32 %and
+}
+
+define i32 @test_with_more_one_use(i32 %x) {
+; CHECK-LABEL: @test_with_more_one_use(
+; CHECK-NEXT: [[SHL:%.*]] = shl i32 7, [[X:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL]], 1
+; CHECK-NEXT: call void @use32(i32 [[SHL]])
+; CHECK-NEXT: ret i32 [[AND]]
+;
+ %shl = shl i32 7, %x
+ %and = and i32 %shl, 1
+ call void @use32(i32 %shl)
+ ret i32 %and
+}
+
define i32 @test1(i32 %A) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: ret i32 0
More information about the llvm-commits
mailing list