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 @@ -2255,8 +2255,11 @@ } if (Pred == CmpInst::ICMP_UGT) { // icmp ugt (ashr X, ShAmtC), C --> icmp ugt X, ((C + 1) << ShAmtC) - 1 + // 'C + 1 << ShAmtC' can overflow as a signed number, so the 2nd + // clause accounts for that pattern. APInt ShiftedC = (C + 1).shl(ShAmtVal) - 1; - if ((ShiftedC + 1).ashr(ShAmtVal) == (C + 1)) + if ((ShiftedC + 1).ashr(ShAmtVal) == (C + 1) || + (C + 1).shl(ShAmtVal).isMinSignedValue()) return new ICmpInst(Pred, X, ConstantInt::get(ShrTy, ShiftedC)); } 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 @@ -594,13 +594,9 @@ ret i1 %r } -; negative test -; TODO: This is a sign-bit test, but we don't recognize the pattern. - define i1 @ashr_ugt_3(i4 %x) { ; CHECK-LABEL: @ashr_ugt_3( -; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1 -; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], 3 +; CHECK-NEXT: [[R:%.*]] = icmp slt i4 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %s = ashr i4 %x, 1 @@ -859,7 +855,6 @@ } ; negative test -; TODO: This is a sign-bit test, but we don't recognize the pattern. define i1 @ashr_ult_12(i4 %x) { ; CHECK-LABEL: @ashr_ult_12(