summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp16
-rw-r--r--test/Transforms/InstCombine/intrinsics.ll10
2 files changed, 26 insertions, 0 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index d53f3291e7..f3a5e724c6 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -523,6 +523,21 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
return InsertValueInst::Create(Struct, Add, 0);
}
}
+
+ // If the normal result of the add is dead, and the RHS is a constant, we
+ // can transform this into a range comparison.
+ // overflow = uadd a, -4 --> overflow = icmp ugt a, 3
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS))
+ if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(II->use_back()))
+ if (II->hasOneUse() && EVI->getNumIndices() == 1 && !EVI->use_empty() &&
+ *EVI->idx_begin() == 1) { // Extract of overflow result.
+ Builder->SetInsertPoint(EVI);
+ Value *R = Builder->CreateICmpUGT(LHS, ConstantExpr::getNot(CI));
+ R->takeName(EVI);
+ ReplaceInstUsesWith(*EVI, R);
+ return II;
+ }
+
}
// FALL THROUGH uadd into sadd
case Intrinsic::sadd_with_overflow:
@@ -550,6 +565,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
return InsertValueInst::Create(Struct, II->getArgOperand(0), 0);
}
}
+
break;
case Intrinsic::usub_with_overflow:
case Intrinsic::ssub_with_overflow:
diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll
index d672d8c153..ed9c7b3840 100644
--- a/test/Transforms/InstCombine/intrinsics.ll
+++ b/test/Transforms/InstCombine/intrinsics.ll
@@ -71,6 +71,16 @@ define i8 @uaddtest5(i8 %A, i1* %overflowPtr) {
; CHECK: ret i8 %A
}
+define i1 @uaddtest6(i8 %A, i8 %B) {
+ %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 -4)
+ %z = extractvalue %overflow.result %x, 1
+ ret i1 %z
+; CHECK: @uaddtest6
+; CHECK-NEXT: %z = icmp ugt i8 %A, 3
+; CHECK-NEXT: ret i1 %z
+}
+
+
define i8 @umultest1(i8 %A, i1* %overflowPtr) {
%x = call %overflow.result @llvm.umul.with.overflow.i8(i8 0, i8 %A)
%y = extractvalue %overflow.result %x, 0