summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/ConstantRange.cpp
diff options
context:
space:
mode:
authorMax Kazantsev <max.kazantsev@azul.com>2017-12-18 13:01:32 +0000
committerMax Kazantsev <max.kazantsev@azul.com>2017-12-18 13:01:32 +0000
commitd792171efbf155fc741290e87b7d1e54fb1ece29 (patch)
tree1b4993291e157235c9c5c2b1a40999276df30594 /llvm/lib/IR/ConstantRange.cpp
parentf70af977af43380e760f7c722ec089ae10e86208 (diff)
downloadbcm5719-llvm-d792171efbf155fc741290e87b7d1e54fb1ece29.tar.gz
bcm5719-llvm-d792171efbf155fc741290e87b7d1e54fb1ece29.zip
[ConstantRange] Support for ashr in ConstantRange computation
Extend the ConstantRange implementation to compute the range of possible values resulting from an arithmetic right shift operation. There will be a follow up patch to leverage this constant range infrastructure in LazyValueInfo. Patch by Surya Kumari Jangala! Differential Revision: https://reviews.llvm.org/D40881 llvm-svn: 320976
Diffstat (limited to 'llvm/lib/IR/ConstantRange.cpp')
-rw-r--r--llvm/lib/IR/ConstantRange.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 77ecd7a9077..48d16f334ba 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -680,6 +680,8 @@ ConstantRange ConstantRange::binaryOp(Instruction::BinaryOps BinOp,
return shl(Other);
case Instruction::LShr:
return lshr(Other);
+ case Instruction::AShr:
+ return ashr(Other);
case Instruction::And:
return binaryAnd(Other);
case Instruction::Or:
@@ -946,6 +948,60 @@ ConstantRange::lshr(const ConstantRange &Other) const {
return ConstantRange(std::move(min), std::move(max));
}
+ConstantRange
+ConstantRange::ashr(const ConstantRange &Other) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+
+ // May straddle zero, so handle both positive and negative cases.
+ // 'PosMax' is the upper bound of the result of the ashr
+ // operation, when Upper of the LHS of ashr is a non-negative.
+ // number. Since ashr of a non-negative number will result in a
+ // smaller number, the Upper value of LHS is shifted right with
+ // the minimum value of 'Other' instead of the maximum value.
+ APInt PosMax = getSignedMax().ashr(Other.getUnsignedMin()) + 1;
+
+ // 'PosMin' is the lower bound of the result of the ashr
+ // operation, when Lower of the LHS is a non-negative number.
+ // Since ashr of a non-negative number will result in a smaller
+ // number, the Lower value of LHS is shifted right with the
+ // maximum value of 'Other'.
+ APInt PosMin = getSignedMin().ashr(Other.getUnsignedMax());
+
+ // 'NegMax' is the upper bound of the result of the ashr
+ // operation, when Upper of the LHS of ashr is a negative number.
+ // Since 'ashr' of a negative number will result in a bigger
+ // number, the Upper value of LHS is shifted right with the
+ // maximum value of 'Other'.
+ APInt NegMax = getSignedMax().ashr(Other.getUnsignedMax()) + 1;
+
+ // 'NegMin' is the lower bound of the result of the ashr
+ // operation, when Lower of the LHS of ashr is a negative number.
+ // Since 'ashr' of a negative number will result in a bigger
+ // number, the Lower value of LHS is shifted right with the
+ // minimum value of 'Other'.
+ APInt NegMin = getSignedMin().ashr(Other.getUnsignedMin());
+
+ APInt max, min;
+ if (getSignedMin().isNonNegative()) {
+ // Upper and Lower of LHS are non-negative.
+ min = PosMin;
+ max = PosMax;
+ } else if (getSignedMax().isNegative()) {
+ // Upper and Lower of LHS are negative.
+ min = NegMin;
+ max = NegMax;
+ } else {
+ // Upper is non-negative and Lower is negative.
+ min = NegMin;
+ max = PosMax;
+ }
+ if (min == max)
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ return ConstantRange(std::move(min), std::move(max));
+}
+
ConstantRange ConstantRange::inverse() const {
if (isFullSet())
return ConstantRange(getBitWidth(), /*isFullSet=*/false);
OpenPOWER on IntegriCloud