From 21d3871b7c90f85b3ae417724d7864369173bde0 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 8 Jan 2023 11:36:21 -0500 Subject: [PATCH] [InstCombine] fold not-shift of signbit to icmp+zext, part 2 Follow-up to: 6c39a3aae1dc That converted a pattern with ashr directly to icmp+zext, and this updates the pattern that we used to convert to. This canonicalizes to icmp for better analysis in the minimum case and shortens patterns where the source type is not the same as dest type: https://alive2.llvm.org/ce/z/tpXJ64 https://alive2.llvm.org/ce/z/dQ405O This requires an adjustment to an icmp transform to avoid infinite looping. --- .../Transforms/InstCombine/InstCombineCasts.cpp | 5 ++++- .../Transforms/InstCombine/InstCombineShifts.cpp | 10 ++++++++-- llvm/test/Transforms/InstCombine/and-xor-merge.ll | 6 +++--- llvm/test/Transforms/InstCombine/icmp-mul-zext.ll | 4 ++-- llvm/test/Transforms/InstCombine/lshr.ll | 22 ++++++++++------------ .../test/Transforms/InstCombine/negated-bitmask.ll | 5 ++--- llvm/test/Transforms/InstCombine/xor.ll | 4 ++-- llvm/test/Transforms/InstCombine/zext.ll | 8 ++++---- 8 files changed, 35 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 43d359a..6c59185 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1027,8 +1027,11 @@ Instruction *InstCombinerImpl::transformZExtICmp(ICmpInst *Cmp, ZExtInst &Zext) // If Op1C some other power of two, convert: KnownBits Known = computeKnownBits(Cmp->getOperand(0), 0, &Zext); + // Exactly 1 possible 1? But not the high-bit because that is + // canonicalized to this form. APInt KnownZeroMask(~Known.Zero); - if (KnownZeroMask.isPowerOf2()) { // Exactly 1 possible 1? + if (KnownZeroMask.isPowerOf2() && + (Zext.getType()->getScalarSizeInBits() != KnownZeroMask.logBase2() + 1)) { bool isNE = Cmp->getPredicate() == ICmpInst::ICMP_NE; uint32_t ShAmt = KnownZeroMask.logBase2(); Value *In = Cmp->getOperand(0); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp index 1fce517..9ac1fd7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -1091,10 +1091,17 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); Type *Ty = I.getType(); + Value *X; const APInt *C; + unsigned BitWidth = Ty->getScalarSizeInBits(); + + // (iN (~X) u>> (N - 1)) --> zext (X > -1) + if (match(Op0, m_OneUse(m_Not(m_Value(X)))) && + match(Op1, m_SpecificIntAllowUndef(BitWidth - 1))) + return new ZExtInst(Builder.CreateIsNotNeg(X, "isnotneg"), Ty); + if (match(Op1, m_APInt(C))) { unsigned ShAmtC = C->getZExtValue(); - unsigned BitWidth = Ty->getScalarSizeInBits(); auto *II = dyn_cast(Op0); if (II && isPowerOf2_32(BitWidth) && Log2_32(BitWidth) == ShAmtC && (II->getIntrinsicID() == Intrinsic::ctlz || @@ -1320,7 +1327,6 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) { } // Transform (x << y) >> y to x & (-1 >> y) - Value *X; if (match(Op0, m_OneUse(m_Shl(m_Value(X), m_Specific(Op1))))) { Constant *AllOnes = ConstantInt::getAllOnesValue(Ty); Value *Mask = Builder.CreateLShr(AllOnes, Op1); diff --git a/llvm/test/Transforms/InstCombine/and-xor-merge.ll b/llvm/test/Transforms/InstCombine/and-xor-merge.ll index 57d3f20..baf3248 100644 --- a/llvm/test/Transforms/InstCombine/and-xor-merge.ll +++ b/llvm/test/Transforms/InstCombine/and-xor-merge.ll @@ -28,9 +28,9 @@ define i32 @test2(i32 %x, i32 %y, i32 %z) { define i32 @PR38781(i32 %a, i32 %b) { ; CHECK-LABEL: @PR38781( -; CHECK-NEXT: [[B_LOBIT_NOT1_DEMORGAN:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[B_LOBIT_NOT1:%.*]] = xor i32 [[B_LOBIT_NOT1_DEMORGAN]], -1 -; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[B_LOBIT_NOT1]], 31 +; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], -1 +; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP2]] to i32 ; CHECK-NEXT: ret i32 [[AND]] ; %a.lobit = lshr i32 %a, 31 diff --git a/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll b/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll index 27d812a..581f945 100644 --- a/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll +++ b/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll @@ -19,10 +19,10 @@ define i32 @sterix(i32, i8, i64) { ; CHECK-NEXT: [[AND:%.*]] = and i64 [[MUL3]], [[TMP2]] ; CHECK-NEXT: [[CONV4:%.*]] = trunc i64 [[AND]] to i32 ; CHECK-NEXT: [[TOBOOL7_NOT:%.*]] = icmp eq i32 [[CONV4]], 0 -; CHECK-NEXT: [[PHITMP:%.*]] = zext i1 [[TOBOOL7_NOT]] to i32 +; CHECK-NEXT: [[PHI_CAST:%.*]] = zext i1 [[TOBOOL7_NOT]] to i32 ; CHECK-NEXT: br label [[LOR_END]] ; CHECK: lor.end: -; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHITMP]], [[LOR_RHS]] ] +; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHI_CAST]], [[LOR_RHS]] ] ; CHECK-NEXT: ret i32 [[TMP4]] ; entry: diff --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll index 715c58c..2d58c53 100644 --- a/llvm/test/Transforms/InstCombine/lshr.ll +++ b/llvm/test/Transforms/InstCombine/lshr.ll @@ -947,8 +947,8 @@ define i32 @not_narrow_bswap(i24 %x) { define i8 @not_signbit(i8 %x) { ; CHECK-LABEL: @not_signbit( -; CHECK-NEXT: [[A:%.*]] = xor i8 [[X:%.*]], -1 -; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 7 +; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1 +; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8 ; CHECK-NEXT: ret i8 [[R]] ; %a = xor i8 %x, -1 @@ -958,8 +958,8 @@ define i8 @not_signbit(i8 %x) { define <2 x i6> @not_signbit_vec(<2 x i6> %x) { ; CHECK-LABEL: @not_signbit_vec( -; CHECK-NEXT: [[A:%.*]] = xor <2 x i6> [[X:%.*]], -; CHECK-NEXT: [[R:%.*]] = lshr <2 x i6> [[A]], +; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt <2 x i6> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = zext <2 x i1> [[ISNOTNEG]] to <2 x i6> ; CHECK-NEXT: ret <2 x i6> [[R]] ; %a = xor <2 x i6> %x, @@ -969,8 +969,8 @@ define <2 x i6> @not_signbit_vec(<2 x i6> %x) { define i8 @not_signbit_alt_xor(i8 %x) { ; CHECK-LABEL: @not_signbit_alt_xor( -; CHECK-NEXT: [[A:%.*]] = xor i8 [[X:%.*]], -1 -; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 7 +; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1 +; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i8 ; CHECK-NEXT: ret i8 [[R]] ; %a = xor i8 %x, -2 @@ -1004,9 +1004,8 @@ define i32 @not_signbit_use(i32 %x) { define i32 @not_signbit_zext(i16 %x) { ; CHECK-LABEL: @not_signbit_zext( -; CHECK-NEXT: [[A:%.*]] = xor i16 [[X:%.*]], -1 -; CHECK-NEXT: [[R:%.*]] = lshr i16 [[A]], 15 -; CHECK-NEXT: [[R2:%.*]] = zext i16 [[R]] to i32 +; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1 +; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i32 ; CHECK-NEXT: ret i32 [[R2]] ; %a = xor i16 %x, -1 @@ -1017,9 +1016,8 @@ define i32 @not_signbit_zext(i16 %x) { define i8 @not_signbit_trunc(i16 %x) { ; CHECK-LABEL: @not_signbit_trunc( -; CHECK-NEXT: [[A:%.*]] = xor i16 [[X:%.*]], -1 -; CHECK-NEXT: [[R:%.*]] = lshr i16 [[A]], 15 -; CHECK-NEXT: [[R2:%.*]] = trunc i16 [[R]] to i8 +; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i16 [[X:%.*]], -1 +; CHECK-NEXT: [[R2:%.*]] = zext i1 [[ISNOTNEG]] to i8 ; CHECK-NEXT: ret i8 [[R2]] ; %a = xor i16 %x, -1 diff --git a/llvm/test/Transforms/InstCombine/negated-bitmask.ll b/llvm/test/Transforms/InstCombine/negated-bitmask.ll index fdd8e7e..e1d3a03 100644 --- a/llvm/test/Transforms/InstCombine/negated-bitmask.ll +++ b/llvm/test/Transforms/InstCombine/negated-bitmask.ll @@ -233,9 +233,8 @@ define i8 @neg_signbit_use2(i5 %x) { define i32 @neg_not_signbit1(i8 %x) { ; CHECK-LABEL: @neg_not_signbit1( -; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], -1 -; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP1]], 7 -; CHECK-NEXT: [[R:%.*]] = zext i8 [[TMP2]] to i32 +; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1 +; CHECK-NEXT: [[R:%.*]] = zext i1 [[ISNOTNEG]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %s = lshr i8 %x, 7 diff --git a/llvm/test/Transforms/InstCombine/xor.ll b/llvm/test/Transforms/InstCombine/xor.ll index 7ad8d79..bb956c0 100644 --- a/llvm/test/Transforms/InstCombine/xor.ll +++ b/llvm/test/Transforms/InstCombine/xor.ll @@ -1061,8 +1061,8 @@ define i8 @not_lshr(i8 %x) { define <2 x i8> @not_lshr_vec(<2 x i8> %x) { ; CHECK-LABEL: @not_lshr_vec( -; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[R:%.*]] = lshr <2 x i8> [[TMP1]], +; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = zext <2 x i1> [[ISNOTNEG]] to <2 x i8> ; CHECK-NEXT: ret <2 x i8> [[R]] ; %a = lshr <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll index 43e50ed..430685e 100644 --- a/llvm/test/Transforms/InstCombine/zext.ll +++ b/llvm/test/Transforms/InstCombine/zext.ll @@ -501,10 +501,10 @@ define i8 @notneg_zext_narrower_use(i32 %x) { define i8 @disguised_signbit_clear_test(i64 %x) { ; CHECK-LABEL: @disguised_signbit_clear_test( -; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i8 -; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[TMP1]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = lshr i8 [[TMP2]], 7 -; CHECK-NEXT: ret i8 [[TMP3]] +; CHECK-NEXT: [[A1:%.*]] = and i64 [[X:%.*]], 128 +; CHECK-NEXT: [[T4:%.*]] = icmp eq i64 [[A1]], 0 +; CHECK-NEXT: [[T6:%.*]] = zext i1 [[T4]] to i8 +; CHECK-NEXT: ret i8 [[T6]] ; %a1 = and i64 %x, 128 %t4 = icmp eq i64 %a1, 0 -- 2.7.4