diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1555,17 +1555,23 @@ // TODO: Handle any shifted constant by subtracting trailing zeros. // TODO: Handle non-equality predicates. Value *Y; - if (Cmp.isEquality() && match(X, m_Shl(m_One(), m_Value(Y)))) { - // (trunc (1 << Y) to iN) == 0 --> Y u>= N - // (trunc (1 << Y) to iN) != 0 --> Y u< N - if (C.isZero()) { - auto NewPred = (Pred == Cmp.ICMP_EQ) ? Cmp.ICMP_UGE : Cmp.ICMP_ULT; - return new ICmpInst(NewPred, Y, ConstantInt::get(SrcTy, DstBits)); + const APInt *C1; + if (Cmp.isEquality() && match(X, m_Shl(m_APIntAllowUndef(C1), m_Value(Y)))) { + if (C1->isPowerOf2()) { + // (trunc (2**C1 << Y) to iN) == 0 -> Y u> N - C1 + 1 + // (trunc (2**C1 << Y) to iN) != 0 -> Y u<= N - C1 + 1 + if (C.isZero()) { + auto NewPred = (Pred == Cmp.ICMP_EQ) ? Cmp.ICMP_UGT : Cmp.ICMP_ULE; + return new ICmpInst( + NewPred, Y, + ConstantInt::get(SrcTy, C1->trunc(DstBits).countLeadingZeros())); + } + // (trunc (2**C1 << Y) to iN) == 2**C --> Y == C - C1 + // (trunc (2**C1 << Y) to iN) != 2**C --> Y != C - C1 + if (C.isPowerOf2() && C.uge(*C1)) + return new ICmpInst( + Pred, Y, ConstantInt::get(SrcTy, C.logBase2() - C1->logBase2())); } - // (trunc (1 << Y) to iN) == 2**C --> Y == C - // (trunc (1 << Y) to iN) != 2**C --> Y != C - if (C.isPowerOf2()) - return new ICmpInst(Pred, Y, ConstantInt::get(SrcTy, C.logBase2())); } if (Cmp.isEquality() && Trunc->hasOneUse()) { diff --git a/llvm/test/Transforms/InstCombine/icmp-trunc.ll b/llvm/test/Transforms/InstCombine/icmp-trunc.ll --- a/llvm/test/Transforms/InstCombine/icmp-trunc.ll +++ b/llvm/test/Transforms/InstCombine/icmp-trunc.ll @@ -410,9 +410,7 @@ define i1 @shl2_trunc_eq0(i9 %a) { ; CHECK-LABEL: @shl2_trunc_eq0( -; CHECK-NEXT: [[SHL:%.*]] = shl i9 2, [[A:%.*]] -; CHECK-NEXT: [[T:%.*]] = trunc i9 [[SHL]] to i6 -; CHECK-NEXT: [[R:%.*]] = icmp eq i6 [[T]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ugt i9 [[A:%.*]], 4 ; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i9 2, %a @@ -423,9 +421,7 @@ define i1 @shl2_trunc_ne0(i9 %a) { ; CHECK-LABEL: @shl2_trunc_ne0( -; CHECK-NEXT: [[SHL:%.*]] = shl i9 2, [[A:%.*]] -; CHECK-NEXT: [[T:%.*]] = trunc i9 [[SHL]] to i6 -; CHECK-NEXT: [[R:%.*]] = icmp ne i6 [[T]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ult i9 [[A:%.*]], 5 ; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i9 2, %a @@ -449,9 +445,7 @@ define <2 x i1> @shl4_trunc_ne0(<2 x i8> %a) { ; CHECK-LABEL: @shl4_trunc_ne0( -; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i8> , [[A:%.*]] -; CHECK-NEXT: [[T:%.*]] = trunc <2 x i8> [[SHL]] to <2 x i5> -; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i5> [[T]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i8> [[A:%.*]], ; CHECK-NEXT: ret <2 x i1> [[R]] ; %shl = shl <2 x i8> , %a @@ -506,17 +500,9 @@ } define i1 @shl2_trunc_eq8_i32(i32 %a) { -; DL64-LABEL: @shl2_trunc_eq8_i32( -; DL64-NEXT: [[SHL:%.*]] = shl i32 2, [[A:%.*]] -; DL64-NEXT: [[TMP1:%.*]] = and i32 [[SHL]], 65534 -; DL64-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 8 -; DL64-NEXT: ret i1 [[R]] -; -; DL8-LABEL: @shl2_trunc_eq8_i32( -; DL8-NEXT: [[SHL:%.*]] = shl i32 2, [[A:%.*]] -; DL8-NEXT: [[T:%.*]] = trunc i32 [[SHL]] to i16 -; DL8-NEXT: [[R:%.*]] = icmp eq i16 [[T]], 8 -; DL8-NEXT: ret i1 [[R]] +; CHECK-LABEL: @shl2_trunc_eq8_i32( +; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[A:%.*]], 2 +; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i32 2, %a %t = trunc i32 %shl to i16 @@ -525,17 +511,9 @@ } define i1 @shl2_trunc_ne8_i32(i32 %a) { -; DL64-LABEL: @shl2_trunc_ne8_i32( -; DL64-NEXT: [[SHL:%.*]] = shl i32 2, [[A:%.*]] -; DL64-NEXT: [[TMP1:%.*]] = and i32 [[SHL]], 65534 -; DL64-NEXT: [[R:%.*]] = icmp ne i32 [[TMP1]], 8 -; DL64-NEXT: ret i1 [[R]] -; -; DL8-LABEL: @shl2_trunc_ne8_i32( -; DL8-NEXT: [[SHL:%.*]] = shl i32 2, [[A:%.*]] -; DL8-NEXT: [[T:%.*]] = trunc i32 [[SHL]] to i16 -; DL8-NEXT: [[R:%.*]] = icmp ne i16 [[T]], 8 -; DL8-NEXT: ret i1 [[R]] +; CHECK-LABEL: @shl2_trunc_ne8_i32( +; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[A:%.*]], 2 +; CHECK-NEXT: ret i1 [[R]] ; %shl = shl i32 2, %a %t = trunc i32 %shl to i16