[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