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 @@ -2235,13 +2235,22 @@ bool IsAShr = Shr->getOpcode() == Instruction::AShr; const APInt *ShiftValC; - if (match(Shr->getOperand(0), m_APInt(ShiftValC))) { + if (match(X, m_APInt(ShiftValC))) { if (Cmp.isEquality()) return foldICmpShrConstConst(Cmp, Shr->getOperand(1), C, *ShiftValC); + // (ShiftValC >> Y) >s -1 --> Y != 0 with ShiftValC < 0 + // (ShiftValC >> Y) Y == 0 with ShiftValC < 0 + bool TrueIfSigned; + if (!IsAShr && ShiftValC->isNegative() && + isSignBitCheck(Pred, C, TrueIfSigned)) + return new ICmpInst(TrueIfSigned ? CmpInst::ICMP_EQ : CmpInst::ICMP_NE, + Shr->getOperand(1), + ConstantInt::getNullValue(X->getType())); + // If the shifted constant is a power-of-2, test the shift amount directly: - // (ShiftValC >> X) >u C --> X > X) X >=u (LZ(C-1) - LZ(ShiftValC)) + // (ShiftValC >> Y) >u C --> X > Y) X >=u (LZ(C-1) - LZ(ShiftValC)) if (!IsAShr && ShiftValC->isPowerOf2() && (Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_ULT)) { bool IsUGT = Pred == CmpInst::ICMP_UGT; diff --git a/llvm/test/Transforms/InstCombine/icmp-shr.ll b/llvm/test/Transforms/InstCombine/icmp-shr.ll --- a/llvm/test/Transforms/InstCombine/icmp-shr.ll +++ b/llvm/test/Transforms/InstCombine/icmp-shr.ll @@ -1146,12 +1146,9 @@ ret i1 %r } -; TODO: This should reduce to X != 0. - define i1 @lshr_pow2_ult_smin(i8 %x) { ; CHECK-LABEL: @lshr_pow2_ult_smin( -; CHECK-NEXT: [[S:%.*]] = lshr i8 -128, [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[S]], -1 +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %s = lshr i8 128, %x @@ -1189,8 +1186,7 @@ define i1 @lshr_neg_sgt_minus_1(i8 %x) { ; CHECK-LABEL: @lshr_neg_sgt_minus_1( -; CHECK-NEXT: [[S:%.*]] = lshr i8 -17, [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[S]], -1 +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %s = lshr i8 -17, %x @@ -1200,8 +1196,7 @@ define <2 x i1> @lshr_neg_sgt_minus_1_vector(<2 x i8> %x) { ; CHECK-LABEL: @lshr_neg_sgt_minus_1_vector( -; CHECK-NEXT: [[S:%.*]] = lshr <2 x i8> , [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i8> [[S]], +; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[X:%.*]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[R]] ; %s = lshr <2 x i8> , %x @@ -1209,13 +1204,11 @@ ret <2 x i1> %r } -; Negative tests - define i1 @lshr_neg_sgt_minus_1_extra_use(i8 %x) { ; CHECK-LABEL: @lshr_neg_sgt_minus_1_extra_use( ; CHECK-NEXT: [[S:%.*]] = lshr i8 -17, [[X:%.*]] ; CHECK-NEXT: call void @use(i8 [[S]]) -; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[S]], -1 +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %s = lshr i8 -17, %x @@ -1224,6 +1217,8 @@ ret i1 %r } +; Negative tests + define i1 @lshr_neg_sgt_minus_2(i8 %x) { ; CHECK-LABEL: @lshr_neg_sgt_minus_2( ; CHECK-NEXT: [[S:%.*]] = lshr i8 -17, [[X:%.*]] @@ -1250,8 +1245,7 @@ define i1 @lshr_neg_slt_zero(i8 %x) { ; CHECK-LABEL: @lshr_neg_slt_zero( -; CHECK-NEXT: [[S:%.*]] = lshr i8 -17, [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[S]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %s = lshr i8 -17, %x @@ -1261,8 +1255,7 @@ define <2 x i1> @lshr_neg_slt_zero_vector(<2 x i8> %x) { ; CHECK-LABEL: @lshr_neg_slt_zero_vector( -; CHECK-NEXT: [[S:%.*]] = lshr <2 x i8> , [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i8> [[S]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[R]] ; %s = lshr <2 x i8> , %x @@ -1270,13 +1263,11 @@ ret <2 x i1> %r } -; Negative tests - define i1 @lshr_neg_slt_zero_extra_use(i8 %x) { ; CHECK-LABEL: @lshr_neg_slt_zero_extra_use( ; CHECK-NEXT: [[S:%.*]] = lshr i8 -17, [[X:%.*]] ; CHECK-NEXT: call void @use(i8 [[S]]) -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[S]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %s = lshr i8 -17, %x @@ -1285,6 +1276,8 @@ ret i1 %r } +; Negative tests + define i1 @lshr_neg_slt_non-zero(i8 %x) { ; CHECK-LABEL: @lshr_neg_slt_non-zero( ; CHECK-NEXT: [[S:%.*]] = lshr i8 -17, [[X:%.*]]