diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2018-11-28 16:36:59 +0000 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2018-11-28 16:36:59 +0000 |
commit | 78a9295e150190c5a4efe345d731cb78e037d28f (patch) | |
tree | 2f696badafeeef5e5a6031d99fdabb735972600d /llvm/lib | |
parent | 085d24a8b3928cd1c4c2c15103537ae104c8841e (diff) | |
download | bcm5719-llvm-78a9295e150190c5a4efe345d731cb78e037d28f.tar.gz bcm5719-llvm-78a9295e150190c5a4efe345d731cb78e037d28f.zip |
[InstCombine] Use known overflow information for saturating add/sub
If ValueTracking can determine that the add/sub can newer overflow,
replace it with the corresponding nuw/nsw add/sub.
Additionally, for the unsigned case, if ValueTracking determines
that the add/sub always overflows, replace the result with the
saturation value.
This change is part of https://reviews.llvm.org/D54534.
llvm-svn: 347770
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index a36e7304cce..2dc80b2947e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2065,7 +2065,45 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { case Intrinsic::sadd_sat: if (Instruction *I = canonicalizeConstantArg0ToArg1(CI)) return I; + LLVM_FALLTHROUGH; + case Intrinsic::usub_sat: + case Intrinsic::ssub_sat: { + Value *Arg0 = II->getArgOperand(0); + Value *Arg1 = II->getArgOperand(1); + Intrinsic::ID IID = II->getIntrinsicID(); + + // Make use of known overflow information. + OverflowResult OR; + switch (IID) { + default: + llvm_unreachable("Unexpected intrinsic!"); + case Intrinsic::uadd_sat: + OR = computeOverflowForUnsignedAdd(Arg0, Arg1, II); + if (OR == OverflowResult::NeverOverflows) + return BinaryOperator::CreateNUWAdd(Arg0, Arg1); + if (OR == OverflowResult::AlwaysOverflows) + return replaceInstUsesWith(*II, + ConstantInt::getAllOnesValue(II->getType())); + break; + case Intrinsic::usub_sat: + OR = computeOverflowForUnsignedSub(Arg0, Arg1, II); + if (OR == OverflowResult::NeverOverflows) + return BinaryOperator::CreateNUWSub(Arg0, Arg1); + if (OR == OverflowResult::AlwaysOverflows) + return replaceInstUsesWith(*II, + ConstantInt::getNullValue(II->getType())); + break; + case Intrinsic::sadd_sat: + if (willNotOverflowSignedAdd(Arg0, Arg1, *II)) + return BinaryOperator::CreateNSWAdd(Arg0, Arg1); + break; + case Intrinsic::ssub_sat: + if (willNotOverflowSignedSub(Arg0, Arg1, *II)) + return BinaryOperator::CreateNSWSub(Arg0, Arg1); + break; + } break; + } case Intrinsic::minnum: case Intrinsic::maxnum: |