diff options
author | Roman Lebedev <lebedev.ri@gmail.com> | 2019-11-07 01:21:29 +0300 |
---|---|---|
committer | Roman Lebedev <lebedev.ri@gmail.com> | 2019-11-07 01:30:53 +0300 |
commit | 7fbe5d4b2ab905792158669149ae4f547761ac9c (patch) | |
tree | 6e1d7e2cfdd45aa9c941ac3403f14c19be330794 /llvm/lib/IR/ConstantRange.cpp | |
parent | 365d729e1075a9391b7520306d8d9beee84d52b5 (diff) | |
download | bcm5719-llvm-7fbe5d4b2ab905792158669149ae4f547761ac9c.tar.gz bcm5719-llvm-7fbe5d4b2ab905792158669149ae4f547761ac9c.zip |
[ConstantRange] Add `subWithNoWrap()` method
Summary:
Much like D67339, adds ConstantRange handling for
when we know no-wrap behavior of the `sub`.
Unlike addWithNoWrap(), we only get lucky re returning empty set
for signed wrap. For unsigned, we must perform overflow check manually.
A patch that makes use of this in LVI (CVP) to be posted later.
Reviewers: nikic, shchenz, efriedma
Reviewed By: nikic
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D69918
Diffstat (limited to 'llvm/lib/IR/ConstantRange.cpp')
-rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index cc1d86ba1b1..4914c50c203 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -898,6 +898,36 @@ ConstantRange::sub(const ConstantRange &Other) const { return X; } +ConstantRange ConstantRange::subWithNoWrap(const ConstantRange &Other, + unsigned NoWrapKind, + PreferredRangeType RangeType) const { + // Calculate the range for "X - Y" which is guaranteed not to wrap(overflow). + // (X is from this, and Y is from Other) + if (isEmptySet() || Other.isEmptySet()) + return getEmpty(); + if (isFullSet() && Other.isFullSet()) + return getFull(); + + using OBO = OverflowingBinaryOperator; + ConstantRange Result = sub(Other); + + // If an overflow happens for every value pair in these two constant ranges, + // we must return Empty set. In signed case, we get that for free, because we + // get lucky that intersection of add() with ssub_sat() results in an + // empty set. But for unsigned we must perform the overflow check manually. + + if (NoWrapKind & OBO::NoSignedWrap) + Result = Result.intersectWith(ssub_sat(Other), RangeType); + + if (NoWrapKind & OBO::NoUnsignedWrap) { + if (getUnsignedMax().ult(Other.getUnsignedMin())) + return getEmpty(); // Always overflows. + Result = Result.intersectWith(usub_sat(Other), RangeType); + } + + return Result; +} + ConstantRange ConstantRange::multiply(const ConstantRange &Other) const { // TODO: If either operand is a single element and the multiply is known to |