summaryrefslogtreecommitdiff
path: root/lib/IR/ConstantRange.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/IR/ConstantRange.cpp')
-rw-r--r--lib/IR/ConstantRange.cpp73
1 files changed, 65 insertions, 8 deletions
diff --git a/lib/IR/ConstantRange.cpp b/lib/IR/ConstantRange.cpp
index 48d16f334ba3..39a0b13c4e0c 100644
--- a/lib/IR/ConstantRange.cpp
+++ b/lib/IR/ConstantRange.cpp
@@ -22,6 +22,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/APInt.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstrTypes.h"
@@ -190,8 +191,7 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
return CR0.inverse().unionWith(CR1.inverse()).inverse();
};
- assert(BinOp >= Instruction::BinaryOpsBegin &&
- BinOp < Instruction::BinaryOpsEnd && "Binary operators only!");
+ assert(Instruction::isBinaryOp(BinOp) && "Binary operators only!");
assert((NoWrapKind == OBO::NoSignedWrap ||
NoWrapKind == OBO::NoUnsignedWrap ||
@@ -255,6 +255,64 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
APInt::getSignedMinValue(BitWidth) + SignedMin));
}
return Result;
+ case Instruction::Mul: {
+ if (NoWrapKind == (OBO::NoSignedWrap | OBO::NoUnsignedWrap)) {
+ return SubsetIntersect(
+ makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoSignedWrap),
+ makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoUnsignedWrap));
+ }
+
+ // 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 ConstantRange(BitWidth, true);
+
+ 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);
+ }
+ if (Unsigned) {
+ Lower = Lower.zextOrSelf(BitWidth);
+ Upper = Upper.zextOrSelf(BitWidth);
+ } else {
+ Lower = Lower.sextOrSelf(BitWidth);
+ Upper = Upper.sextOrSelf(BitWidth);
+ }
+ // 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);
+ };
+
+ if (Unsigned)
+ return makeSingleValueRegion(Other.getUnsignedMax());
+
+ return SubsetIntersect(makeSingleValueRegion(Other.getSignedMin()),
+ makeSingleValueRegion(Other.getSignedMax()));
+ }
}
}
@@ -358,7 +416,7 @@ bool ConstantRange::contains(const ConstantRange &Other) const {
ConstantRange ConstantRange::subtract(const APInt &Val) const {
assert(Val.getBitWidth() == getBitWidth() && "Wrong bit width");
// If the set is empty or full, don't modify the endpoints.
- if (Lower == Upper)
+ if (Lower == Upper)
return *this;
return ConstantRange(Lower - Val, Upper - Val);
}
@@ -368,7 +426,7 @@ ConstantRange ConstantRange::difference(const ConstantRange &CR) const {
}
ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
- assert(getBitWidth() == CR.getBitWidth() &&
+ assert(getBitWidth() == CR.getBitWidth() &&
"ConstantRange types don't agree!");
// Handle common cases.
@@ -442,7 +500,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
}
ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
- assert(getBitWidth() == CR.getBitWidth() &&
+ assert(getBitWidth() == CR.getBitWidth() &&
"ConstantRange types don't agree!");
if ( isFullSet() || CR.isEmptySet()) return *this;
@@ -664,8 +722,7 @@ ConstantRange ConstantRange::sextOrTrunc(uint32_t DstTySize) const {
ConstantRange ConstantRange::binaryOp(Instruction::BinaryOps BinOp,
const ConstantRange &Other) const {
- assert(BinOp >= Instruction::BinaryOpsBegin &&
- BinOp < Instruction::BinaryOpsEnd && "Binary operators only!");
+ assert(Instruction::isBinaryOp(BinOp) && "Binary operators only!");
switch (BinOp) {
case Instruction::Add:
@@ -797,7 +854,7 @@ ConstantRange::multiply(const ConstantRange &Other) const {
this_max = getSignedMax().sext(getBitWidth() * 2);
Other_min = Other.getSignedMin().sext(getBitWidth() * 2);
Other_max = Other.getSignedMax().sext(getBitWidth() * 2);
-
+
auto L = {this_min * Other_min, this_min * Other_max,
this_max * Other_min, this_max * Other_max};
auto Compare = [](const APInt &A, const APInt &B) { return A.slt(B); };