summaryrefslogtreecommitdiff
path: root/llvm/lib/IR/ConstantRange.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/ConstantRange.cpp')
-rw-r--r--llvm/lib/IR/ConstantRange.cpp49
1 files changed, 39 insertions, 10 deletions
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 4b0ad1bd25a0..0649776dbc22 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -181,6 +181,11 @@ bool ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred,
return Success;
}
+bool ConstantRange::icmp(CmpInst::Predicate Pred,
+ const ConstantRange &Other) const {
+ return makeSatisfyingICmpRegion(Pred, Other).contains(*this);
+}
+
/// Exact mul nuw region for single element RHS.
static ConstantRange makeExactMulNUWRegion(const APInt &V) {
unsigned BitWidth = V.getBitWidth();
@@ -1058,7 +1063,10 @@ ConstantRange::smax(const ConstantRange &Other) const {
return getEmpty();
APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin());
APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1;
- return getNonEmpty(std::move(NewL), std::move(NewU));
+ ConstantRange Res = getNonEmpty(std::move(NewL), std::move(NewU));
+ if (isSignWrappedSet() || Other.isSignWrappedSet())
+ return Res.intersectWith(unionWith(Other, Signed), Signed);
+ return Res;
}
ConstantRange
@@ -1069,7 +1077,10 @@ ConstantRange::umax(const ConstantRange &Other) const {
return getEmpty();
APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1;
- return getNonEmpty(std::move(NewL), std::move(NewU));
+ ConstantRange Res = getNonEmpty(std::move(NewL), std::move(NewU));
+ if (isWrappedSet() || Other.isWrappedSet())
+ return Res.intersectWith(unionWith(Other, Unsigned), Unsigned);
+ return Res;
}
ConstantRange
@@ -1080,7 +1091,10 @@ ConstantRange::smin(const ConstantRange &Other) const {
return getEmpty();
APInt NewL = APIntOps::smin(getSignedMin(), Other.getSignedMin());
APInt NewU = APIntOps::smin(getSignedMax(), Other.getSignedMax()) + 1;
- return getNonEmpty(std::move(NewL), std::move(NewU));
+ ConstantRange Res = getNonEmpty(std::move(NewL), std::move(NewU));
+ if (isSignWrappedSet() || Other.isSignWrappedSet())
+ return Res.intersectWith(unionWith(Other, Signed), Signed);
+ return Res;
}
ConstantRange
@@ -1091,7 +1105,10 @@ ConstantRange::umin(const ConstantRange &Other) const {
return getEmpty();
APInt NewL = APIntOps::umin(getUnsignedMin(), Other.getUnsignedMin());
APInt NewU = APIntOps::umin(getUnsignedMax(), Other.getUnsignedMax()) + 1;
- return getNonEmpty(std::move(NewL), std::move(NewU));
+ ConstantRange Res = getNonEmpty(std::move(NewL), std::move(NewU));
+ if (isWrappedSet() || Other.isWrappedSet())
+ return Res.intersectWith(unionWith(Other, Unsigned), Unsigned);
+ return Res;
}
ConstantRange
@@ -1204,6 +1221,15 @@ ConstantRange ConstantRange::urem(const ConstantRange &RHS) const {
if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isNullValue())
return getEmpty();
+ if (const APInt *RHSInt = RHS.getSingleElement()) {
+ // UREM by null is UB.
+ if (RHSInt->isNullValue())
+ return getEmpty();
+ // Use APInt's implementation of UREM for single element ranges.
+ if (const APInt *LHSInt = getSingleElement())
+ return {LHSInt->urem(*RHSInt)};
+ }
+
// L % R for L < R is L.
if (getUnsignedMax().ult(RHS.getUnsignedMin()))
return *this;
@@ -1217,6 +1243,15 @@ ConstantRange ConstantRange::srem(const ConstantRange &RHS) const {
if (isEmptySet() || RHS.isEmptySet())
return getEmpty();
+ if (const APInt *RHSInt = RHS.getSingleElement()) {
+ // SREM by null is UB.
+ if (RHSInt->isNullValue())
+ return getEmpty();
+ // Use APInt's implementation of SREM for single element ranges.
+ if (const APInt *LHSInt = getSingleElement())
+ return {LHSInt->srem(*RHSInt)};
+ }
+
ConstantRange AbsRHS = RHS.abs();
APInt MinAbsRHS = AbsRHS.getUnsignedMin();
APInt MaxAbsRHS = AbsRHS.getUnsignedMax();
@@ -1256,12 +1291,6 @@ ConstantRange ConstantRange::srem(const ConstantRange &RHS) const {
}
ConstantRange ConstantRange::binaryNot() const {
- if (isEmptySet())
- return getEmpty();
-
- if (isWrappedSet())
- return getFull();
-
return ConstantRange(APInt::getAllOnesValue(getBitWidth())).sub(*this);
}