[llvm] 71df24d - [InstCombine] fold add-carry of bools to logic

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 6 10:42:59 PST 2022


Author: Sanjay Patel
Date: 2022-12-06T13:42:42-05:00
New Revision: 71df24dd39177ecfc440a04cd92fa4845d88347d

URL: https://github.com/llvm/llvm-project/commit/71df24dd39177ecfc440a04cd92fa4845d88347d
DIFF: https://github.com/llvm/llvm-project/commit/71df24dd39177ecfc440a04cd92fa4845d88347d.diff

LOG: [InstCombine] fold add-carry of bools to logic

((zext BoolX) + (zext BoolY)) >> 1 --> zext (BoolX && BoolY)
https://alive2.llvm.org/ce/z/LvZFKj

This was noted as a missing fold in D138814.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
    llvm/test/Transforms/InstCombine/lshr.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 9f5d1478e6df7..df5613cd2ee0b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1289,6 +1289,18 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
       }
     }
 
+    // Reduce add-carry of bools to logic:
+    // ((zext BoolX) + (zext BoolY)) >> 1 --> zext (BoolX && BoolY)
+    Value *BoolX, *BoolY;
+    if (ShAmtC == 1 && match(Op0, m_Add(m_Value(X), m_Value(Y))) &&
+        match(X, m_ZExt(m_Value(BoolX))) && match(Y, m_ZExt(m_Value(BoolY))) &&
+        BoolX->getType()->isIntOrIntVectorTy(1) &&
+        BoolY->getType()->isIntOrIntVectorTy(1) &&
+        (X->hasOneUse() || Y->hasOneUse() || Op0->hasOneUse())) {
+      Value *And = Builder.CreateAnd(BoolX, BoolY);
+      return new ZExtInst(And, Ty);
+    }
+
     // If the shifted-out value is known-zero, then this is an exact shift.
     if (!I.isExact() &&
         MaskedValueIsZero(Op0, APInt::getLowBitsSet(BitWidth, ShAmtC), 0, &I)) {

diff  --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll
index b3c8fb02cd77d..715c58c3d8b63 100644
--- a/llvm/test/Transforms/InstCombine/lshr.ll
+++ b/llvm/test/Transforms/InstCombine/lshr.ll
@@ -1030,10 +1030,8 @@ define i8 @not_signbit_trunc(i16 %x) {
 
 define i2 @bool_add_lshr(i1 %a, i1 %b) {
 ; CHECK-LABEL: @bool_add_lshr(
-; CHECK-NEXT:    [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i2
-; CHECK-NEXT:    [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i2
-; CHECK-NEXT:    [[ADD:%.*]] = add nuw i2 [[ZEXT_A]], [[ZEXT_B]]
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i2 [[ADD]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[LSHR:%.*]] = zext i1 [[TMP1]] to i2
 ; CHECK-NEXT:    ret i2 [[LSHR]]
 ;
   %zext.a = zext i1 %a to i2
@@ -1043,6 +1041,8 @@ define i2 @bool_add_lshr(i1 %a, i1 %b) {
   ret i2 %lshr
 }
 
+; negative test - need bools
+
 define i4 @not_bool_add_lshr(i2 %a, i2 %b) {
 ; CHECK-LABEL: @not_bool_add_lshr(
 ; CHECK-NEXT:    [[ZEXT_A:%.*]] = zext i2 [[A:%.*]] to i4
@@ -1058,6 +1058,8 @@ define i4 @not_bool_add_lshr(i2 %a, i2 %b) {
   ret i4 %lshr
 }
 
+; TODO: This could be sext(and a, b).
+
 define i2 @bool_add_ashr(i1 %a, i1 %b) {
 ; CHECK-LABEL: @bool_add_ashr(
 ; CHECK-NEXT:    [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i2
@@ -1075,10 +1077,8 @@ define i2 @bool_add_ashr(i1 %a, i1 %b) {
 
 define <2 x i8> @bool_add_lshr_vec(<2 x i1> %a, <2 x i1> %b) {
 ; CHECK-LABEL: @bool_add_lshr_vec(
-; CHECK-NEXT:    [[ZEXT_A:%.*]] = zext <2 x i1> [[A:%.*]] to <2 x i8>
-; CHECK-NEXT:    [[ZEXT_B:%.*]] = zext <2 x i1> [[B:%.*]] to <2 x i8>
-; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw <2 x i8> [[ZEXT_A]], [[ZEXT_B]]
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i8> [[ADD]], <i8 1, i8 1>
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[LSHR:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
 ; CHECK-NEXT:    ret <2 x i8> [[LSHR]]
 ;
   %zext.a = zext <2 x i1> %a to <2 x i8>
@@ -1094,8 +1094,8 @@ define i32 @bool_add_lshr_uses(i1 %a, i1 %b) {
 ; CHECK-NEXT:    call void @use(i32 [[ZEXT_A]])
 ; CHECK-NEXT:    [[ZEXT_B:%.*]] = zext i1 [[B:%.*]] to i32
 ; CHECK-NEXT:    call void @use(i32 [[ZEXT_B]])
-; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[ZEXT_A]], [[ZEXT_B]]
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[ADD]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[LSHR:%.*]] = zext i1 [[TMP1]] to i32
 ; CHECK-NEXT:    ret i32 [[LSHR]]
 ;
   %zext.a = zext i1 %a to i32
@@ -1114,7 +1114,8 @@ define i32 @bool_add_lshr_uses2(i1 %a, i1 %b) {
 ; CHECK-NEXT:    call void @use(i32 [[ZEXT_B]])
 ; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[ZEXT_A]], [[ZEXT_B]]
 ; CHECK-NEXT:    call void @use(i32 [[ADD]])
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[ADD]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i1 [[A]], [[B]]
+; CHECK-NEXT:    [[LSHR:%.*]] = zext i1 [[TMP1]] to i32
 ; CHECK-NEXT:    ret i32 [[LSHR]]
 ;
   %zext.a = zext i1 %a to i32
@@ -1126,6 +1127,8 @@ define i32 @bool_add_lshr_uses2(i1 %a, i1 %b) {
   ret i32 %lshr
 }
 
+; negative test - too many extra uses
+
 define i32 @bool_add_lshr_uses3(i1 %a, i1 %b) {
 ; CHECK-LABEL: @bool_add_lshr_uses3(
 ; CHECK-NEXT:    [[ZEXT_A:%.*]] = zext i1 [[A:%.*]] to i32
@@ -1147,6 +1150,8 @@ define i32 @bool_add_lshr_uses3(i1 %a, i1 %b) {
   ret i32 %lshr
 }
 
+; negative test
+
 define <2 x i8> @bool_add_lshr_vec_wrong_shift_amt(<2 x i1> %a, <2 x i1> %b) {
 ; CHECK-LABEL: @bool_add_lshr_vec_wrong_shift_amt(
 ; CHECK-NEXT:    [[ZEXT_A:%.*]] = zext <2 x i1> [[A:%.*]] to <2 x i8>


        


More information about the llvm-commits mailing list