summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/ConstantRange.cpp
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-04-26 16:50:31 +0000
committerNikita Popov <nikita.ppv@gmail.com>2019-04-26 16:50:31 +0000
commitc0fa4ec01dd1c3837b31e142ceb20845421e34ab (patch)
tree6042ac43d048e3a892c23205d17652c9ef4d025d /llvm/lib/IR/ConstantRange.cpp
parentf30f261dc531b289bc74c157178e5bbc4a6ff7c9 (diff)
downloadbcm5719-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.cpp31
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())
OpenPOWER on IntegriCloud