summaryrefslogtreecommitdiff
path: root/lib/IR
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2017-12-05 18:14:23 +0000
committerJoel Galenson <jgalenson@google.com>2017-12-05 18:14:23 +0000
commit0e19a2ac5cd1ece20eee0a426b7b1824c942542c (patch)
treefcd5c9892edb6511793586170896dfacfeebeb80 /lib/IR
parent05c71a9ebe57f1f5a77b20d7a0ad033d6ab3ed4a (diff)
[ConstantRange] Support subtraction in makeGuaranteedNoWrapRegion.
Previously ConstantRange::makeGuaranteedNoWrapRegion only handled addition. This adds support for subtraction. Differential Revision: https://reviews.llvm.org/D40036 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319806 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/IR')
-rw-r--r--lib/IR/ConstantRange.cpp80
1 files changed, 52 insertions, 28 deletions
diff --git a/lib/IR/ConstantRange.cpp b/lib/IR/ConstantRange.cpp
index 4bd17257016..77ecd7a9077 100644
--- a/lib/IR/ConstantRange.cpp
+++ b/lib/IR/ConstantRange.cpp
@@ -199,39 +199,63 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
"NoWrapKind invalid!");
unsigned BitWidth = Other.getBitWidth();
- if (BinOp != Instruction::Add)
+ ConstantRange Result(BitWidth);
+
+ switch (BinOp) {
+ default:
// Conservative answer: empty set
return ConstantRange(BitWidth, false);
- if (auto *C = Other.getSingleElement())
- if (C->isNullValue())
- // Full set: nothing signed / unsigned wraps when added to 0.
- return ConstantRange(BitWidth);
-
- ConstantRange Result(BitWidth);
+ case Instruction::Add:
+ if (auto *C = Other.getSingleElement())
+ if (C->isNullValue())
+ // Full set: nothing signed / unsigned wraps when added to 0.
+ return ConstantRange(BitWidth);
+ if (NoWrapKind & OBO::NoUnsignedWrap)
+ Result =
+ SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth),
+ -Other.getUnsignedMax()));
+ if (NoWrapKind & OBO::NoSignedWrap) {
+ const APInt &SignedMin = Other.getSignedMin();
+ const APInt &SignedMax = Other.getSignedMax();
+ if (SignedMax.isStrictlyPositive())
+ Result = SubsetIntersect(
+ Result,
+ ConstantRange(APInt::getSignedMinValue(BitWidth),
+ APInt::getSignedMinValue(BitWidth) - SignedMax));
+ if (SignedMin.isNegative())
+ Result = SubsetIntersect(
+ Result,
+ ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin,
+ APInt::getSignedMinValue(BitWidth)));
+ }
+ return Result;
- if (NoWrapKind & OBO::NoUnsignedWrap)
- Result =
- SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth),
- -Other.getUnsignedMax()));
-
- if (NoWrapKind & OBO::NoSignedWrap) {
- const APInt &SignedMin = Other.getSignedMin();
- const APInt &SignedMax = Other.getSignedMax();
-
- if (SignedMax.isStrictlyPositive())
- Result = SubsetIntersect(
- Result,
- ConstantRange(APInt::getSignedMinValue(BitWidth),
- APInt::getSignedMinValue(BitWidth) - SignedMax));
-
- if (SignedMin.isNegative())
- Result = SubsetIntersect(
- Result, ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin,
- APInt::getSignedMinValue(BitWidth)));
+ case Instruction::Sub:
+ if (auto *C = Other.getSingleElement())
+ if (C->isNullValue())
+ // Full set: nothing signed / unsigned wraps when subtracting 0.
+ return ConstantRange(BitWidth);
+ if (NoWrapKind & OBO::NoUnsignedWrap)
+ Result =
+ SubsetIntersect(Result, ConstantRange(Other.getUnsignedMax(),
+ APInt::getMinValue(BitWidth)));
+ if (NoWrapKind & OBO::NoSignedWrap) {
+ const APInt &SignedMin = Other.getSignedMin();
+ const APInt &SignedMax = Other.getSignedMax();
+ if (SignedMax.isStrictlyPositive())
+ Result = SubsetIntersect(
+ Result,
+ ConstantRange(APInt::getSignedMinValue(BitWidth) + SignedMax,
+ APInt::getSignedMinValue(BitWidth)));
+ if (SignedMin.isNegative())
+ Result = SubsetIntersect(
+ Result,
+ ConstantRange(APInt::getSignedMinValue(BitWidth),
+ APInt::getSignedMinValue(BitWidth) + SignedMin));
+ }
+ return Result;
}
-
- return Result;
}
bool ConstantRange::isFullSet() const {