[instcombine] Fold overflow check using overflow intrinsic to comparison
authorPhilip Reames <listmail@philipreames.com>
Thu, 1 Jul 2021 16:17:04 +0000 (09:17 -0700)
committerPhilip Reames <listmail@philipreames.com>
Thu, 1 Jul 2021 16:41:55 +0000 (09:41 -0700)
This follows up to D104665 (which added umulo handling alongside the existing uaddo case), and generalizes for the remaining overflow intrinsics.

I went to add analogous handling to LVI, and discovered that LVI already had a more general implementation. Instead, we can port was LVI does to instcombine. (For context, LVI uses makeExactNoWrapRegion to constrain the value 'x' in blocks reached after a branch on the condition `op.with.overflow(x, C).overflow`.)

Differential Revision: https://reviews.llvm.org/D104932

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
llvm/test/Transforms/InstCombine/saddo.ll
llvm/test/Transforms/InstCombine/smulo.ll
llvm/test/Transforms/InstCombine/ssubo.ll
llvm/test/Transforms/InstCombine/usubo.ll

index 25b7405..8f75a7e 100644 (file)
@@ -3089,33 +3089,32 @@ Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) {
       assert(*EV.idx_begin() == 1 &&
              "unexpected extract index for overflow inst");
 
-      // If the normal result of the computation is dead, and the RHS is a
-      // constant, we can transform this into a range comparison for many cases.
-      // TODO: We can generalize these for non-constant rhs when the newly
-      // formed expressions are known to simplify.  Constants are merely one
-      // such case.
-      // TODO: Handle vector splats.
-      switch (WO->getIntrinsicID()) {
-      default:
-        break;
-      case Intrinsic::uadd_with_overflow:
-        // overflow = uadd a, -4  -->  overflow = icmp ugt a, 3
-        if (ConstantInt *CI = dyn_cast<ConstantInt>(WO->getRHS()))
-          return new ICmpInst(ICmpInst::ICMP_UGT, WO->getLHS(),
-                              ConstantExpr::getNot(CI));
-        break;
-      case Intrinsic::umul_with_overflow:
-        // overflow for umul a, C  --> a > UINT_MAX udiv C
-        // (unless C == 0, in which case no overflow ever occurs)
-        if (ConstantInt *CI = dyn_cast<ConstantInt>(WO->getRHS())) {
-          assert(!CI->isZero() && "handled by instruction simplify");
-          auto UMax = APInt::getMaxValue(CI->getType()->getBitWidth());
-          auto *Op =
-            ConstantExpr::getUDiv(ConstantInt::get(CI->getType(), UMax), CI);
-          return new ICmpInst(ICmpInst::ICMP_UGT, WO->getLHS(), Op);
+      // If only the overflow result is used, and the right hand side is a
+      // constant (or constant splat), we can remove the intrinsic by directly
+      // checking for overflow.
+      const APInt *C;
+      if (match(WO->getRHS(), m_APInt(C))) {
+        // Compute the no-wrap range [X,Y) for LHS given RHS=C, then
+        // check for the inverted range using range offset trick (i.e.
+        // use a subtract to shift the range to bottom of either the
+        // signed or unsigned domain and then use a single compare to
+        // check range membership).
+        ConstantRange NWR =
+          ConstantRange::makeExactNoWrapRegion(WO->getBinaryOp(), *C,
+                                               WO->getNoWrapKind());
+        APInt Min = WO->isSigned() ? NWR.getSignedMin() : NWR.getUnsignedMin();
+        NWR = NWR.subtract(Min);
+
+        CmpInst::Predicate Pred;
+        APInt NewRHSC;
+        if (NWR.getEquivalentICmp(Pred, NewRHSC)) {
+          auto *OpTy = WO->getRHS()->getType();
+          auto *NewLHS = Builder.CreateSub(WO->getLHS(),
+                                           ConstantInt::get(OpTy, Min));
+          return new ICmpInst(ICmpInst::getInversePredicate(Pred), NewLHS,
+                              ConstantInt::get(OpTy, NewRHSC));
         }
-        break;
-      };
+      }
     }
   }
   if (LoadInst *L = dyn_cast<LoadInst>(Agg))
index 5a3c8f5..8585c4e 100644 (file)
@@ -26,8 +26,7 @@ define i1 @test_constant0(i8 %a) {
 
 define i1 @test_constant1(i8 %a) {
 ; CHECK-LABEL: @test_constant1(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 1)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], 127
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 1)
@@ -37,8 +36,7 @@ define i1 @test_constant1(i8 %a) {
 
 define i1 @test_constant2(i8 %a) {
 ; CHECK-LABEL: @test_constant2(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 2)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp sgt i8 [[A:%.*]], 125
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 2)
@@ -48,8 +46,7 @@ define i1 @test_constant2(i8 %a) {
 
 define i1 @test_constant3(i8 %a) {
 ; CHECK-LABEL: @test_constant3(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 3)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp sgt i8 [[A:%.*]], 124
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 3)
@@ -59,8 +56,7 @@ define i1 @test_constant3(i8 %a) {
 
 define i1 @test_constant4(i8 %a) {
 ; CHECK-LABEL: @test_constant4(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 4)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp sgt i8 [[A:%.*]], 123
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 4)
@@ -70,8 +66,7 @@ define i1 @test_constant4(i8 %a) {
 
 define i1 @test_constant127(i8 %a) {
 ; CHECK-LABEL: @test_constant127(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 127)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp sgt i8 [[A:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 127)
@@ -81,8 +76,7 @@ define i1 @test_constant127(i8 %a) {
 
 define i1 @test_constant128(i8 %a) {
 ; CHECK-LABEL: @test_constant128(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 -128)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 128)
@@ -92,8 +86,7 @@ define i1 @test_constant128(i8 %a) {
 
 define i1 @test_constant255(i8 %a) {
 ; CHECK-LABEL: @test_constant255(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 -1)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], -128
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %a, i8 255)
index 4731520..c909ed1 100644 (file)
@@ -35,8 +35,8 @@ define i1 @test_constant1(i8 %a) {
 
 define i1 @test_constant2(i8 %a) {
 ; CHECK-LABEL: @test_constant2(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 2)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], 64
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp slt i8 [[TMP1]], 0
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 2)
@@ -46,8 +46,8 @@ define i1 @test_constant2(i8 %a) {
 
 define i1 @test_constant3(i8 %a) {
 ; CHECK-LABEL: @test_constant3(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 3)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], 42
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ugt i8 [[TMP1]], 84
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 3)
@@ -57,8 +57,8 @@ define i1 @test_constant3(i8 %a) {
 
 define i1 @test_constant4(i8 %a) {
 ; CHECK-LABEL: @test_constant4(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 4)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], 32
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ugt i8 [[TMP1]], 63
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 4)
@@ -69,8 +69,8 @@ define i1 @test_constant4(i8 %a) {
 
 define i1 @test_constant127(i8 %a) {
 ; CHECK-LABEL: @test_constant127(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 127)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ugt i8 [[TMP1]], 2
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 127)
@@ -80,8 +80,7 @@ define i1 @test_constant127(i8 %a) {
 
 define i1 @test_constant128(i8 %a) {
 ; CHECK-LABEL: @test_constant128(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 -128)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ugt i8 [[A:%.*]], 1
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 128)
@@ -91,8 +90,7 @@ define i1 @test_constant128(i8 %a) {
 
 define i1 @test_constant255(i8 %a) {
 ; CHECK-LABEL: @test_constant255(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[A:%.*]], i8 -1)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], -128
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 255)
index 9b11f6a..c87fe92 100644 (file)
@@ -26,8 +26,7 @@ define i1 @test_constant0(i8 %a) {
 
 define i1 @test_constant1(i8 %a) {
 ; CHECK-LABEL: @test_constant1(
-; CHECK-NEXT:    [[TMP1:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 -1)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], -128
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 1)
@@ -37,8 +36,7 @@ define i1 @test_constant1(i8 %a) {
 
 define i1 @test_constant2(i8 %a) {
 ; CHECK-LABEL: @test_constant2(
-; CHECK-NEXT:    [[TMP1:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 -2)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -126
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 2)
@@ -48,8 +46,7 @@ define i1 @test_constant2(i8 %a) {
 
 define i1 @test_constant3(i8 %a) {
 ; CHECK-LABEL: @test_constant3(
-; CHECK-NEXT:    [[TMP1:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 -3)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -125
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 3)
@@ -59,8 +56,7 @@ define i1 @test_constant3(i8 %a) {
 
 define i1 @test_constant4(i8 %a) {
 ; CHECK-LABEL: @test_constant4(
-; CHECK-NEXT:    [[TMP1:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 -4)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -124
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 4)
@@ -71,8 +67,7 @@ define i1 @test_constant4(i8 %a) {
 
 define i1 @test_constant127(i8 %a) {
 ; CHECK-LABEL: @test_constant127(
-; CHECK-NEXT:    [[TMP1:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 -127)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 127)
@@ -82,8 +77,7 @@ define i1 @test_constant127(i8 %a) {
 
 define i1 @test_constant128(i8 %a) {
 ; CHECK-LABEL: @test_constant128(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[A:%.*]], i8 -128)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp sgt i8 [[A:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 128)
@@ -93,8 +87,7 @@ define i1 @test_constant128(i8 %a) {
 
 define i1 @test_constant255(i8 %a) {
 ; CHECK-LABEL: @test_constant255(
-; CHECK-NEXT:    [[TMP1:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[A:%.*]], i8 1)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], 127
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 255)
index 26f8cd2..38ab25c 100644 (file)
@@ -26,8 +26,7 @@ define i1 @test_constant0(i8 %a) {
 
 define i1 @test_constant1(i8 %a) {
 ; CHECK-LABEL: @test_constant1(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 1)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 1)
@@ -37,8 +36,7 @@ define i1 @test_constant1(i8 %a) {
 
 define i1 @test_constant2(i8 %a) {
 ; CHECK-LABEL: @test_constant2(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 2)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ult i8 [[A:%.*]], 2
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 2)
@@ -48,8 +46,7 @@ define i1 @test_constant2(i8 %a) {
 
 define i1 @test_constant3(i8 %a) {
 ; CHECK-LABEL: @test_constant3(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 3)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ult i8 [[A:%.*]], 3
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 3)
@@ -59,8 +56,7 @@ define i1 @test_constant3(i8 %a) {
 
 define i1 @test_constant4(i8 %a) {
 ; CHECK-LABEL: @test_constant4(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 4)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ult i8 [[A:%.*]], 4
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 4)
@@ -71,8 +67,7 @@ define i1 @test_constant4(i8 %a) {
 
 define i1 @test_constant127(i8 %a) {
 ; CHECK-LABEL: @test_constant127(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 127)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ult i8 [[A:%.*]], 127
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 127)
@@ -82,8 +77,7 @@ define i1 @test_constant127(i8 %a) {
 
 define i1 @test_constant128(i8 %a) {
 ; CHECK-LABEL: @test_constant128(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 -128)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp sgt i8 [[A:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 128)
@@ -93,8 +87,7 @@ define i1 @test_constant128(i8 %a) {
 
 define i1 @test_constant255(i8 %a) {
 ; CHECK-LABEL: @test_constant255(
-; CHECK-NEXT:    [[RES:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[A:%.*]], i8 -1)
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[RES]], 1
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ne i8 [[A:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 255)