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,19 @@ 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 + if (!IsAShr && Pred == CmpInst::ICMP_SGT && C.isAllOnes() && + ShiftValC->isNegative()) + return new ICmpInst(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 @@ -1184,3 +1181,48 @@ %r = icmp slt i8 %s, 3 ret i1 %r } + +define i1 @lshr_neg_sgt_minus_1(i8 %x) { +; CHECK-LABEL: @lshr_neg_sgt_minus_1( +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %s = lshr i8 -17, %x + %r = icmp sgt i8 %s, -1 + ret i1 %r +} + +; Negtive test +define i1 @lshr_neg_sgt_minus_2(i8 %x) { +; CHECK-LABEL: @lshr_neg_sgt_minus_2( +; CHECK-NEXT: [[S:%.*]] = lshr i8 -17, [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[S]], -2 +; CHECK-NEXT: ret i1 [[R]] +; + %s = lshr i8 -17, %x + %r = icmp sgt i8 %s, -2 + ret i1 %r +} + +; Negtive test +define i1 @lshr_neg_slt_minus_1(i8 %x) { +; CHECK-LABEL: @lshr_neg_slt_minus_1( +; CHECK-NEXT: [[S:%.*]] = lshr i8 -17, [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[S]], -1 +; CHECK-NEXT: ret i1 [[R]] +; + %s = lshr i8 -17, %x + %r = icmp slt i8 %s, -1 + ret i1 %r +} + +; Negtive test +define i1 @lshr_sgt_minus_1(i8 %x) { +; CHECK-LABEL: @lshr_sgt_minus_1( +; CHECK-NEXT: ret i1 true +; + %s = lshr i8 17, %x + %r = icmp sgt i8 %s, -1 + ret i1 %r +} +