summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-05-07 20:34:46 +0000
committerNikita Popov <nikita.ppv@gmail.com>2019-05-07 20:34:46 +0000
commitf610110f1ac1177950f7727175fc299391401a9d (patch)
tree7cbeff3dabdd209d80f3e2751fd864ef5f349b58
parent34e9c41164335d7797bd20a8a9f989e5b2ef29df (diff)
downloadbcm5719-llvm-f610110f1ac1177950f7727175fc299391401a9d.tar.gz
bcm5719-llvm-f610110f1ac1177950f7727175fc299391401a9d.zip
[ConstantRange] Simplify makeGNWR implementation; NFC
Compute results in more direct ways, avoid subset intersect operations. Extract the core code for computing mul nowrap ranges into separate static functions, so they can be reused. llvm-svn: 360189
-rw-r--r--llvm/lib/IR/ConstantRange.cpp170
1 files changed, 67 insertions, 103 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 7079d0e8251..549886271ff 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -180,132 +180,96 @@ bool ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred,
return Success;
}
+/// Exact mul nuw region for single element RHS.
+static ConstantRange makeExactMulNUWRegion(const APInt &V) {
+ unsigned BitWidth = V.getBitWidth();
+ if (V == 0)
+ return ConstantRange::getFull(V.getBitWidth());
+
+ return ConstantRange::getNonEmpty(
+ APIntOps::RoundingUDiv(APInt::getMinValue(BitWidth), V,
+ APInt::Rounding::UP),
+ APIntOps::RoundingUDiv(APInt::getMaxValue(BitWidth), V,
+ APInt::Rounding::DOWN) + 1);
+}
+
+/// Exact mul nsw region for single element RHS.
+static ConstantRange makeExactMulNSWRegion(const APInt &V) {
+ // Handle special case for 0, -1 and 1. See the last for reason why we
+ // specialize -1 and 1.
+ unsigned BitWidth = V.getBitWidth();
+ if (V == 0 || V.isOneValue())
+ return ConstantRange::getFull(BitWidth);
+
+ APInt MinValue = APInt::getSignedMinValue(BitWidth);
+ APInt MaxValue = APInt::getSignedMaxValue(BitWidth);
+ // e.g. Returning [-127, 127], represented as [-127, -128).
+ if (V.isAllOnesValue())
+ return ConstantRange(-MaxValue, MinValue);
+
+ APInt Lower, Upper;
+ if (V.isNegative()) {
+ Lower = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::UP);
+ Upper = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::DOWN);
+ } else {
+ Lower = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::UP);
+ Upper = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::DOWN);
+ }
+ // ConstantRange ctor take a half inclusive interval [Lower, Upper + 1).
+ // Upper + 1 is guaranteed not to overflow, because |divisor| > 1. 0, -1,
+ // and 1 are already handled as special cases.
+ return ConstantRange(Lower, Upper + 1);
+}
+
ConstantRange
ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
const ConstantRange &Other,
unsigned NoWrapKind) {
using OBO = OverflowingBinaryOperator;
- // Computes the intersection of CR0 and CR1. It is different from
- // intersectWith in that the ConstantRange returned will only contain elements
- // in both CR0 and CR1 (i.e. SubsetIntersect(X, Y) is a *subset*, proper or
- // not, of both X and Y).
- auto SubsetIntersect =
- [](const ConstantRange &CR0, const ConstantRange &CR1) {
- return CR0.inverse().unionWith(CR1.inverse()).inverse();
- };
-
assert(Instruction::isBinaryOp(BinOp) && "Binary operators only!");
assert((NoWrapKind == OBO::NoSignedWrap ||
NoWrapKind == OBO::NoUnsignedWrap) &&
"NoWrapKind invalid!");
+ bool Unsigned = NoWrapKind == OBO::NoUnsignedWrap;
unsigned BitWidth = Other.getBitWidth();
- ConstantRange Result(BitWidth, /* full */ true);
switch (BinOp) {
default:
// Conservative answer: empty set
return getEmpty(BitWidth);
- case Instruction::Add:
- if (auto *C = Other.getSingleElement())
- if (C->isNullValue())
- // Full set: nothing signed / unsigned wraps when added to 0.
- return getFull(BitWidth);
-
- if (NoWrapKind == OBO::NoUnsignedWrap)
- return 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;
-
- case Instruction::Sub:
- if (auto *C = Other.getSingleElement())
- if (C->isNullValue())
- // Full set: nothing signed / unsigned wraps when subtracting 0.
- return getFull(BitWidth);
-
- if (NoWrapKind == OBO::NoUnsignedWrap)
- return 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;
-
- case Instruction::Mul: {
- // Equivalent to calling makeGuaranteedNoWrapRegion() on [V, V+1).
- const bool Unsigned = NoWrapKind == OBO::NoUnsignedWrap;
- const auto makeSingleValueRegion = [Unsigned,
- BitWidth](APInt V) -> ConstantRange {
- // Handle special case for 0, -1 and 1. See the last for reason why we
- // specialize -1 and 1.
- if (V == 0 || V.isOneValue())
- return getFull(BitWidth);
-
- APInt MinValue, MaxValue;
- if (Unsigned) {
- MinValue = APInt::getMinValue(BitWidth);
- MaxValue = APInt::getMaxValue(BitWidth);
- } else {
- MinValue = APInt::getSignedMinValue(BitWidth);
- MaxValue = APInt::getSignedMaxValue(BitWidth);
- }
- // e.g. Returning [-127, 127], represented as [-127, -128).
- if (!Unsigned && V.isAllOnesValue())
- return ConstantRange(-MaxValue, MinValue);
-
- APInt Lower, Upper;
- if (!Unsigned && V.isNegative()) {
- Lower = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::UP);
- Upper = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::DOWN);
- } else if (Unsigned) {
- Lower = APIntOps::RoundingUDiv(MinValue, V, APInt::Rounding::UP);
- Upper = APIntOps::RoundingUDiv(MaxValue, V, APInt::Rounding::DOWN);
- } else {
- Lower = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::UP);
- Upper = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::DOWN);
- }
- // ConstantRange ctor take a half inclusive interval [Lower, Upper + 1).
- // Upper + 1 is guanranteed not to overflow, because |divisor| > 1. 0, -1,
- // and 1 are already handled as special cases.
- return ConstantRange(Lower, Upper + 1);
- };
+ case Instruction::Add: {
+ if (Unsigned)
+ return getNonEmpty(APInt::getNullValue(BitWidth),
+ -Other.getUnsignedMax());
+
+ APInt SignedMinVal = APInt::getSignedMinValue(BitWidth);
+ APInt SMin = Other.getSignedMin(), SMax = Other.getSignedMax();
+ return getNonEmpty(
+ SMin.isNegative() ? SignedMinVal - SMin : SignedMinVal,
+ SMax.isStrictlyPositive() ? SignedMinVal - SMax : SignedMinVal);
+ }
+ case Instruction::Sub: {
if (Unsigned)
- return makeSingleValueRegion(Other.getUnsignedMax());
+ return getNonEmpty(Other.getUnsignedMax(), APInt::getMinValue(BitWidth));
- return SubsetIntersect(makeSingleValueRegion(Other.getSignedMin()),
- makeSingleValueRegion(Other.getSignedMax()));
+ APInt SignedMinVal = APInt::getSignedMinValue(BitWidth);
+ APInt SMin = Other.getSignedMin(), SMax = Other.getSignedMax();
+ return getNonEmpty(
+ SMax.isStrictlyPositive() ? SignedMinVal + SMax : SignedMinVal,
+ SMin.isNegative() ? SignedMinVal + SMin : SignedMinVal);
}
+
+ case Instruction::Mul:
+ if (Unsigned)
+ return makeExactMulNUWRegion(Other.getUnsignedMax());
+
+ return makeExactMulNSWRegion(Other.getSignedMin())
+ .intersectWith(makeExactMulNSWRegion(Other.getSignedMax()));
}
}
OpenPOWER on IntegriCloud