diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-04-26 16:50:31 +0000 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-04-26 16:50:31 +0000 |
commit | c0fa4ec01dd1c3837b31e142ceb20845421e34ab (patch) | |
tree | 6042ac43d048e3a892c23205d17652c9ef4d025d /llvm/lib/IR/ConstantRange.cpp | |
parent | f30f261dc531b289bc74c157178e5bbc4a6ff7c9 (diff) | |
download | bcm5719-llvm-c0fa4ec01dd1c3837b31e142ceb20845421e34ab.tar.gz bcm5719-llvm-c0fa4ec01dd1c3837b31e142ceb20845421e34ab.zip |
[ConstantRange] Add abs() support
Add support for abs() to ConstantRange. This will allow to handle
SPF_ABS select flavor in LVI and will also come in handy as a
primitive for the srem implementation.
The implementation is slightly tricky, because a) abs of signed min
is signed min and b) sign-wrapped ranges may have an abs() that is
smaller than a full range, so we need to explicitly handle them.
Differential Revision: https://reviews.llvm.org/D61084
llvm-svn: 359321
Diffstat (limited to 'llvm/lib/IR/ConstantRange.cpp')
-rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index af71fd3ac65..76e0b0ca5b3 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -1156,6 +1156,37 @@ ConstantRange ConstantRange::inverse() const { return ConstantRange(Upper, Lower); } +ConstantRange ConstantRange::abs() const { + if (isEmptySet()) + return getEmpty(); + + if (isSignWrappedSet()) { + APInt Lo; + // Check whether the range crosses zero. + if (Upper.isStrictlyPositive() || !Lower.isStrictlyPositive()) + Lo = APInt::getNullValue(getBitWidth()); + else + Lo = APIntOps::umin(Lower, -Upper + 1); + + // SignedMin is included in the result range. + return ConstantRange(Lo, APInt::getSignedMinValue(getBitWidth()) + 1); + } + + APInt SMin = getSignedMin(), SMax = getSignedMax(); + + // All non-negative. + if (SMin.isNonNegative()) + return *this; + + // All negative. + if (SMax.isNegative()) + return ConstantRange(-SMax, -SMin + 1); + + // Range crosses zero. + return ConstantRange(APInt::getNullValue(getBitWidth()), + APIntOps::umax(-SMin, SMax) + 1); +} + ConstantRange::OverflowResult ConstantRange::unsignedAddMayOverflow( const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) |