Skip to content

Commit

Permalink
[InstCombine] fold add-carry of bools to logic
Browse files Browse the repository at this point in the history
((zext BoolX) + (zext BoolY)) >> 1 --> zext (BoolX && BoolY)
https://alive2.llvm.org/ce/z/LvZFKj

This was noted as a missing fold in D138814.
  • Loading branch information
rotateright committed Dec 6, 2022
1 parent 924233c commit 71df24d
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 11 deletions.
12 changes: 12 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
Expand Up @@ -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)) {
Expand Down
27 changes: 16 additions & 11 deletions llvm/test/Transforms/InstCombine/lshr.ll
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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>
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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>
Expand Down

0 comments on commit 71df24d

Please sign in to comment.