1de6cce22SEugene Zelenko //===- ConstantRange.cpp - ConstantRange implementation -------------------===//
28cd041efSChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68cd041efSChandler Carruth //
78cd041efSChandler Carruth //===----------------------------------------------------------------------===//
88cd041efSChandler Carruth //
98cd041efSChandler Carruth // Represent a range of possible values that may occur when the program is run
108cd041efSChandler Carruth // for an integral value. This keeps track of a lower and upper bound for the
118cd041efSChandler Carruth // constant, which MAY wrap around the end of the numeric range. To do this, it
128cd041efSChandler Carruth // keeps track of a [lower, upper) bound, which specifies an interval just like
138cd041efSChandler Carruth // STL iterators. When used with boolean values, the following are important
148cd041efSChandler Carruth // ranges (other integral ranges use min/max values for special range values):
158cd041efSChandler Carruth //
168cd041efSChandler Carruth // [F, F) = {} = Empty set
178cd041efSChandler Carruth // [T, F) = {T}
188cd041efSChandler Carruth // [F, T) = {F}
198cd041efSChandler Carruth // [T, T) = {F, T} = Full set
208cd041efSChandler Carruth //
218cd041efSChandler Carruth //===----------------------------------------------------------------------===//
228cd041efSChandler Carruth
23de6cce22SEugene Zelenko #include "llvm/ADT/APInt.h"
24432a3883SNico Weber #include "llvm/Config/llvm-config.h"
258cd041efSChandler Carruth #include "llvm/IR/ConstantRange.h"
26de6cce22SEugene Zelenko #include "llvm/IR/Constants.h"
276bda14b3SChandler Carruth #include "llvm/IR/InstrTypes.h"
286bda14b3SChandler Carruth #include "llvm/IR/Instruction.h"
29897bdca4SNikita Popov #include "llvm/IR/Intrinsics.h"
30de6cce22SEugene Zelenko #include "llvm/IR/Metadata.h"
316bda14b3SChandler Carruth #include "llvm/IR/Operator.h"
32de6cce22SEugene Zelenko #include "llvm/Support/Compiler.h"
338cd041efSChandler Carruth #include "llvm/Support/Debug.h"
34de6cce22SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
35ef2d9799SNikita Popov #include "llvm/Support/KnownBits.h"
368cd041efSChandler Carruth #include "llvm/Support/raw_ostream.h"
37de6cce22SEugene Zelenko #include <algorithm>
38de6cce22SEugene Zelenko #include <cassert>
39de6cce22SEugene Zelenko #include <cstdint>
40de6cce22SEugene Zelenko
418cd041efSChandler Carruth using namespace llvm;
428cd041efSChandler Carruth
ConstantRange(uint32_t BitWidth,bool Full)43ee4f22dcSCraig Topper ConstantRange::ConstantRange(uint32_t BitWidth, bool Full)
44ee4f22dcSCraig Topper : Lower(Full ? APInt::getMaxValue(BitWidth) : APInt::getMinValue(BitWidth)),
45ee4f22dcSCraig Topper Upper(Lower) {}
468cd041efSChandler Carruth
ConstantRange(APInt V)4737df0180SCraig Topper ConstantRange::ConstantRange(APInt V)
488cd041efSChandler Carruth : Lower(std::move(V)), Upper(Lower + 1) {}
498cd041efSChandler Carruth
ConstantRange(APInt L,APInt U)5037df0180SCraig Topper ConstantRange::ConstantRange(APInt L, APInt U)
518cd041efSChandler Carruth : Lower(std::move(L)), Upper(std::move(U)) {
528cd041efSChandler Carruth assert(Lower.getBitWidth() == Upper.getBitWidth() &&
538cd041efSChandler Carruth "ConstantRange with unequal bit widths");
548cd041efSChandler Carruth assert((Lower != Upper || (Lower.isMaxValue() || Lower.isMinValue())) &&
558cd041efSChandler Carruth "Lower == Upper, but they aren't min or max value!");
568cd041efSChandler Carruth }
578cd041efSChandler Carruth
fromKnownBits(const KnownBits & Known,bool IsSigned)58ef2d9799SNikita Popov ConstantRange ConstantRange::fromKnownBits(const KnownBits &Known,
59ef2d9799SNikita Popov bool IsSigned) {
605e7b62deSNikita Popov assert(!Known.hasConflict() && "Expected valid KnownBits");
615e7b62deSNikita Popov
62ef2d9799SNikita Popov if (Known.isUnknown())
63977934f0SNikita Popov return getFull(Known.getBitWidth());
64ef2d9799SNikita Popov
65ef2d9799SNikita Popov // For unsigned ranges, or signed ranges with known sign bit, create a simple
66ef2d9799SNikita Popov // range between the smallest and largest possible value.
67ef2d9799SNikita Popov if (!IsSigned || Known.isNegative() || Known.isNonNegative())
689a20c79dSRoman Lebedev return ConstantRange(Known.getMinValue(), Known.getMaxValue() + 1);
69ef2d9799SNikita Popov
70ef2d9799SNikita Popov // If we don't know the sign bit, pick the lower bound as a negative number
71ef2d9799SNikita Popov // and the upper bound as a non-negative one.
729a20c79dSRoman Lebedev APInt Lower = Known.getMinValue(), Upper = Known.getMaxValue();
73ef2d9799SNikita Popov Lower.setSignBit();
74ef2d9799SNikita Popov Upper.clearSignBit();
75ef2d9799SNikita Popov return ConstantRange(Lower, Upper + 1);
76ef2d9799SNikita Popov }
77ef2d9799SNikita Popov
toKnownBits() const788ab819adSNikita Popov KnownBits ConstantRange::toKnownBits() const {
798ab819adSNikita Popov // TODO: We could return conflicting known bits here, but consumers are
808ab819adSNikita Popov // likely not prepared for that.
818ab819adSNikita Popov if (isEmptySet())
828ab819adSNikita Popov return KnownBits(getBitWidth());
838ab819adSNikita Popov
848ab819adSNikita Popov // We can only retain the top bits that are the same between min and max.
858ab819adSNikita Popov APInt Min = getUnsignedMin();
868ab819adSNikita Popov APInt Max = getUnsignedMax();
878ab819adSNikita Popov KnownBits Known = KnownBits::makeConstant(Min);
888ab819adSNikita Popov if (Optional<unsigned> DifferentBit =
898ab819adSNikita Popov APIntOps::GetMostSignificantDifferentBit(Min, Max)) {
908ab819adSNikita Popov Known.Zero.clearLowBits(*DifferentBit + 1);
918ab819adSNikita Popov Known.One.clearLowBits(*DifferentBit + 1);
928ab819adSNikita Popov }
938ab819adSNikita Popov return Known;
948ab819adSNikita Popov }
958ab819adSNikita Popov
makeAllowedICmpRegion(CmpInst::Predicate Pred,const ConstantRange & CR)967182d36fSSanjoy Das ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred,
978cd041efSChandler Carruth const ConstantRange &CR) {
988cd041efSChandler Carruth if (CR.isEmptySet())
998cd041efSChandler Carruth return CR;
1008cd041efSChandler Carruth
1018cd041efSChandler Carruth uint32_t W = CR.getBitWidth();
1028cd041efSChandler Carruth switch (Pred) {
1037182d36fSSanjoy Das default:
1047182d36fSSanjoy Das llvm_unreachable("Invalid ICmp predicate to makeAllowedICmpRegion()");
1058cd041efSChandler Carruth case CmpInst::ICMP_EQ:
1068cd041efSChandler Carruth return CR;
1078cd041efSChandler Carruth case CmpInst::ICMP_NE:
1088cd041efSChandler Carruth if (CR.isSingleElement())
1098cd041efSChandler Carruth return ConstantRange(CR.getUpper(), CR.getLower());
110977934f0SNikita Popov return getFull(W);
1118cd041efSChandler Carruth case CmpInst::ICMP_ULT: {
1128cd041efSChandler Carruth APInt UMax(CR.getUnsignedMax());
1138cd041efSChandler Carruth if (UMax.isMinValue())
114977934f0SNikita Popov return getEmpty(W);
115b792025bSCraig Topper return ConstantRange(APInt::getMinValue(W), std::move(UMax));
1168cd041efSChandler Carruth }
1178cd041efSChandler Carruth case CmpInst::ICMP_SLT: {
1188cd041efSChandler Carruth APInt SMax(CR.getSignedMax());
1198cd041efSChandler Carruth if (SMax.isMinSignedValue())
120977934f0SNikita Popov return getEmpty(W);
121b792025bSCraig Topper return ConstantRange(APInt::getSignedMinValue(W), std::move(SMax));
1228cd041efSChandler Carruth }
123dbc3fbafSNikita Popov case CmpInst::ICMP_ULE:
124dbc3fbafSNikita Popov return getNonEmpty(APInt::getMinValue(W), CR.getUnsignedMax() + 1);
125dbc3fbafSNikita Popov case CmpInst::ICMP_SLE:
126dbc3fbafSNikita Popov return getNonEmpty(APInt::getSignedMinValue(W), CR.getSignedMax() + 1);
1278cd041efSChandler Carruth case CmpInst::ICMP_UGT: {
1288cd041efSChandler Carruth APInt UMin(CR.getUnsignedMin());
1298cd041efSChandler Carruth if (UMin.isMaxValue())
130977934f0SNikita Popov return getEmpty(W);
131735f4671SChris Lattner return ConstantRange(std::move(UMin) + 1, APInt::getZero(W));
1328cd041efSChandler Carruth }
1338cd041efSChandler Carruth case CmpInst::ICMP_SGT: {
1348cd041efSChandler Carruth APInt SMin(CR.getSignedMin());
1358cd041efSChandler Carruth if (SMin.isMaxSignedValue())
136977934f0SNikita Popov return getEmpty(W);
137b792025bSCraig Topper return ConstantRange(std::move(SMin) + 1, APInt::getSignedMinValue(W));
1388cd041efSChandler Carruth }
139dbc3fbafSNikita Popov case CmpInst::ICMP_UGE:
140735f4671SChris Lattner return getNonEmpty(CR.getUnsignedMin(), APInt::getZero(W));
141dbc3fbafSNikita Popov case CmpInst::ICMP_SGE:
142dbc3fbafSNikita Popov return getNonEmpty(CR.getSignedMin(), APInt::getSignedMinValue(W));
1438cd041efSChandler Carruth }
1448cd041efSChandler Carruth }
1458cd041efSChandler Carruth
makeSatisfyingICmpRegion(CmpInst::Predicate Pred,const ConstantRange & CR)1467182d36fSSanjoy Das ConstantRange ConstantRange::makeSatisfyingICmpRegion(CmpInst::Predicate Pred,
1477182d36fSSanjoy Das const ConstantRange &CR) {
1487182d36fSSanjoy Das // Follows from De-Morgan's laws:
1497182d36fSSanjoy Das //
1507182d36fSSanjoy Das // ~(~A union ~B) == A intersect B.
1517182d36fSSanjoy Das //
1527182d36fSSanjoy Das return makeAllowedICmpRegion(CmpInst::getInversePredicate(Pred), CR)
1537182d36fSSanjoy Das .inverse();
1547182d36fSSanjoy Das }
1557182d36fSSanjoy Das
makeExactICmpRegion(CmpInst::Predicate Pred,const APInt & C)156569eaec5SBalaram Makam ConstantRange ConstantRange::makeExactICmpRegion(CmpInst::Predicate Pred,
157569eaec5SBalaram Makam const APInt &C) {
158569eaec5SBalaram Makam // Computes the exact range that is equal to both the constant ranges returned
159569eaec5SBalaram Makam // by makeAllowedICmpRegion and makeSatisfyingICmpRegion. This is always true
160569eaec5SBalaram Makam // when RHS is a singleton such as an APInt and so the assert is valid.
161569eaec5SBalaram Makam // However for non-singleton RHS, for example ult [2,5) makeAllowedICmpRegion
162569eaec5SBalaram Makam // returns [0,4) but makeSatisfyICmpRegion returns [0,2).
163569eaec5SBalaram Makam //
164569eaec5SBalaram Makam assert(makeAllowedICmpRegion(Pred, C) == makeSatisfyingICmpRegion(Pred, C));
165569eaec5SBalaram Makam return makeAllowedICmpRegion(Pred, C);
166569eaec5SBalaram Makam }
167569eaec5SBalaram Makam
areInsensitiveToSignednessOfICmpPredicate(const ConstantRange & CR1,const ConstantRange & CR2)16803a4f1f3SRoman Lebedev bool ConstantRange::areInsensitiveToSignednessOfICmpPredicate(
16903a4f1f3SRoman Lebedev const ConstantRange &CR1, const ConstantRange &CR2) {
17003a4f1f3SRoman Lebedev if (CR1.isEmptySet() || CR2.isEmptySet())
17103a4f1f3SRoman Lebedev return true;
17203a4f1f3SRoman Lebedev
17303a4f1f3SRoman Lebedev return (CR1.isAllNonNegative() && CR2.isAllNonNegative()) ||
17403a4f1f3SRoman Lebedev (CR1.isAllNegative() && CR2.isAllNegative());
17503a4f1f3SRoman Lebedev }
17603a4f1f3SRoman Lebedev
areInsensitiveToSignednessOfInvertedICmpPredicate(const ConstantRange & CR1,const ConstantRange & CR2)17703a4f1f3SRoman Lebedev bool ConstantRange::areInsensitiveToSignednessOfInvertedICmpPredicate(
17803a4f1f3SRoman Lebedev const ConstantRange &CR1, const ConstantRange &CR2) {
17903a4f1f3SRoman Lebedev if (CR1.isEmptySet() || CR2.isEmptySet())
18003a4f1f3SRoman Lebedev return true;
18103a4f1f3SRoman Lebedev
18203a4f1f3SRoman Lebedev return (CR1.isAllNonNegative() && CR2.isAllNegative()) ||
18303a4f1f3SRoman Lebedev (CR1.isAllNegative() && CR2.isAllNonNegative());
18403a4f1f3SRoman Lebedev }
18503a4f1f3SRoman Lebedev
getEquivalentPredWithFlippedSignedness(CmpInst::Predicate Pred,const ConstantRange & CR1,const ConstantRange & CR2)18603a4f1f3SRoman Lebedev CmpInst::Predicate ConstantRange::getEquivalentPredWithFlippedSignedness(
18703a4f1f3SRoman Lebedev CmpInst::Predicate Pred, const ConstantRange &CR1,
18803a4f1f3SRoman Lebedev const ConstantRange &CR2) {
18903a4f1f3SRoman Lebedev assert(CmpInst::isIntPredicate(Pred) && CmpInst::isRelational(Pred) &&
19003a4f1f3SRoman Lebedev "Only for relational integer predicates!");
19103a4f1f3SRoman Lebedev
19203a4f1f3SRoman Lebedev CmpInst::Predicate FlippedSignednessPred =
19303a4f1f3SRoman Lebedev CmpInst::getFlippedSignednessPredicate(Pred);
19403a4f1f3SRoman Lebedev
19503a4f1f3SRoman Lebedev if (areInsensitiveToSignednessOfICmpPredicate(CR1, CR2))
19603a4f1f3SRoman Lebedev return FlippedSignednessPred;
19703a4f1f3SRoman Lebedev
19803a4f1f3SRoman Lebedev if (areInsensitiveToSignednessOfInvertedICmpPredicate(CR1, CR2))
19903a4f1f3SRoman Lebedev return CmpInst::getInversePredicate(FlippedSignednessPred);
20003a4f1f3SRoman Lebedev
20103a4f1f3SRoman Lebedev return CmpInst::Predicate::BAD_ICMP_PREDICATE;
20203a4f1f3SRoman Lebedev }
20303a4f1f3SRoman Lebedev
getEquivalentICmp(CmpInst::Predicate & Pred,APInt & RHS,APInt & Offset) const2049f0194beSNikita Popov void ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred,
2059f0194beSNikita Popov APInt &RHS, APInt &Offset) const {
2069f0194beSNikita Popov Offset = APInt(getBitWidth(), 0);
207590614c1SSanjoy Das if (isFullSet() || isEmptySet()) {
208590614c1SSanjoy Das Pred = isEmptySet() ? CmpInst::ICMP_ULT : CmpInst::ICMP_UGE;
209590614c1SSanjoy Das RHS = APInt(getBitWidth(), 0);
210c7d3291bSSanjoy Das } else if (auto *OnlyElt = getSingleElement()) {
211c7d3291bSSanjoy Das Pred = CmpInst::ICMP_EQ;
212c7d3291bSSanjoy Das RHS = *OnlyElt;
213c7d3291bSSanjoy Das } else if (auto *OnlyMissingElt = getSingleMissingElement()) {
214c7d3291bSSanjoy Das Pred = CmpInst::ICMP_NE;
215c7d3291bSSanjoy Das RHS = *OnlyMissingElt;
216590614c1SSanjoy Das } else if (getLower().isMinSignedValue() || getLower().isMinValue()) {
217590614c1SSanjoy Das Pred =
218590614c1SSanjoy Das getLower().isMinSignedValue() ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT;
219590614c1SSanjoy Das RHS = getUpper();
220590614c1SSanjoy Das } else if (getUpper().isMinSignedValue() || getUpper().isMinValue()) {
221590614c1SSanjoy Das Pred =
222590614c1SSanjoy Das getUpper().isMinSignedValue() ? CmpInst::ICMP_SGE : CmpInst::ICMP_UGE;
223590614c1SSanjoy Das RHS = getLower();
2249f0194beSNikita Popov } else {
2259f0194beSNikita Popov Pred = CmpInst::ICMP_ULT;
2269f0194beSNikita Popov RHS = getUpper() - getLower();
2279f0194beSNikita Popov Offset = -getLower();
228590614c1SSanjoy Das }
229590614c1SSanjoy Das
2309f0194beSNikita Popov assert(ConstantRange::makeExactICmpRegion(Pred, RHS) == add(Offset) &&
231590614c1SSanjoy Das "Bad result!");
2329f0194beSNikita Popov }
233590614c1SSanjoy Das
getEquivalentICmp(CmpInst::Predicate & Pred,APInt & RHS) const2349f0194beSNikita Popov bool ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred,
2359f0194beSNikita Popov APInt &RHS) const {
2369f0194beSNikita Popov APInt Offset;
2379f0194beSNikita Popov getEquivalentICmp(Pred, RHS, Offset);
2389f0194beSNikita Popov return Offset.isZero();
239590614c1SSanjoy Das }
240590614c1SSanjoy Das
icmp(CmpInst::Predicate Pred,const ConstantRange & Other) const241e8c7f43eSRoman Lebedev bool ConstantRange::icmp(CmpInst::Predicate Pred,
242e8c7f43eSRoman Lebedev const ConstantRange &Other) const {
243e8c7f43eSRoman Lebedev return makeSatisfyingICmpRegion(Pred, Other).contains(*this);
244e8c7f43eSRoman Lebedev }
245e8c7f43eSRoman Lebedev
246f610110fSNikita Popov /// Exact mul nuw region for single element RHS.
makeExactMulNUWRegion(const APInt & V)247f610110fSNikita Popov static ConstantRange makeExactMulNUWRegion(const APInt &V) {
248f610110fSNikita Popov unsigned BitWidth = V.getBitWidth();
249f610110fSNikita Popov if (V == 0)
250f610110fSNikita Popov return ConstantRange::getFull(V.getBitWidth());
251f610110fSNikita Popov
252f610110fSNikita Popov return ConstantRange::getNonEmpty(
253f610110fSNikita Popov APIntOps::RoundingUDiv(APInt::getMinValue(BitWidth), V,
254f610110fSNikita Popov APInt::Rounding::UP),
255f610110fSNikita Popov APIntOps::RoundingUDiv(APInt::getMaxValue(BitWidth), V,
256f610110fSNikita Popov APInt::Rounding::DOWN) + 1);
257f610110fSNikita Popov }
258f610110fSNikita Popov
259f610110fSNikita Popov /// Exact mul nsw region for single element RHS.
makeExactMulNSWRegion(const APInt & V)260f610110fSNikita Popov static ConstantRange makeExactMulNSWRegion(const APInt &V) {
261f610110fSNikita Popov // Handle special case for 0, -1 and 1. See the last for reason why we
262f610110fSNikita Popov // specialize -1 and 1.
263f610110fSNikita Popov unsigned BitWidth = V.getBitWidth();
264a9bceb2bSJay Foad if (V == 0 || V.isOne())
265f610110fSNikita Popov return ConstantRange::getFull(BitWidth);
266f610110fSNikita Popov
267f610110fSNikita Popov APInt MinValue = APInt::getSignedMinValue(BitWidth);
268f610110fSNikita Popov APInt MaxValue = APInt::getSignedMaxValue(BitWidth);
269f610110fSNikita Popov // e.g. Returning [-127, 127], represented as [-127, -128).
270a9bceb2bSJay Foad if (V.isAllOnes())
271f610110fSNikita Popov return ConstantRange(-MaxValue, MinValue);
272f610110fSNikita Popov
273f610110fSNikita Popov APInt Lower, Upper;
274f610110fSNikita Popov if (V.isNegative()) {
275f610110fSNikita Popov Lower = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::UP);
276f610110fSNikita Popov Upper = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::DOWN);
277f610110fSNikita Popov } else {
278f610110fSNikita Popov Lower = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::UP);
279f610110fSNikita Popov Upper = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::DOWN);
280f610110fSNikita Popov }
281f610110fSNikita Popov // ConstantRange ctor take a half inclusive interval [Lower, Upper + 1).
282f610110fSNikita Popov // Upper + 1 is guaranteed not to overflow, because |divisor| > 1. 0, -1,
283f610110fSNikita Popov // and 1 are already handled as special cases.
284f610110fSNikita Popov return ConstantRange(Lower, Upper + 1);
285f610110fSNikita Popov }
286f610110fSNikita Popov
2875079f626SSanjoy Das ConstantRange
makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,const ConstantRange & Other,unsigned NoWrapKind)2885aacc7a5SNikita Popov ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
289f3867e64SSanjoy Das const ConstantRange &Other,
290f3867e64SSanjoy Das unsigned NoWrapKind) {
291de6cce22SEugene Zelenko using OBO = OverflowingBinaryOperator;
2926ed05305SSanjoy Das
293e0a6eb1fSSimon Pilgrim assert(Instruction::isBinaryOp(BinOp) && "Binary operators only!");
2946ed05305SSanjoy Das
2956ed05305SSanjoy Das assert((NoWrapKind == OBO::NoSignedWrap ||
296a96480ebSNikita Popov NoWrapKind == OBO::NoUnsignedWrap) &&
2976ed05305SSanjoy Das "NoWrapKind invalid!");
2986ed05305SSanjoy Das
299f610110fSNikita Popov bool Unsigned = NoWrapKind == OBO::NoUnsignedWrap;
300f3867e64SSanjoy Das unsigned BitWidth = Other.getBitWidth();
301c32b0fc2SJoel Galenson
302c32b0fc2SJoel Galenson switch (BinOp) {
303c32b0fc2SJoel Galenson default:
3048b1fa076SNikita Popov llvm_unreachable("Unsupported binary op");
3056ed05305SSanjoy Das
306f610110fSNikita Popov case Instruction::Add: {
307f610110fSNikita Popov if (Unsigned)
308735f4671SChris Lattner return getNonEmpty(APInt::getZero(BitWidth), -Other.getUnsignedMax());
309a96480ebSNikita Popov
310f610110fSNikita Popov APInt SignedMinVal = APInt::getSignedMinValue(BitWidth);
311f610110fSNikita Popov APInt SMin = Other.getSignedMin(), SMax = Other.getSignedMax();
312f610110fSNikita Popov return getNonEmpty(
313f610110fSNikita Popov SMin.isNegative() ? SignedMinVal - SMin : SignedMinVal,
314f610110fSNikita Popov SMax.isStrictlyPositive() ? SignedMinVal - SMax : SignedMinVal);
3156ed05305SSanjoy Das }
316c32b0fc2SJoel Galenson
317f610110fSNikita Popov case Instruction::Sub: {
318b32823cbSTim Shen if (Unsigned)
319f610110fSNikita Popov return getNonEmpty(Other.getUnsignedMax(), APInt::getMinValue(BitWidth));
320b32823cbSTim Shen
321f610110fSNikita Popov APInt SignedMinVal = APInt::getSignedMinValue(BitWidth);
322f610110fSNikita Popov APInt SMin = Other.getSignedMin(), SMax = Other.getSignedMax();
323f610110fSNikita Popov return getNonEmpty(
324f610110fSNikita Popov SMax.isStrictlyPositive() ? SignedMinVal + SMax : SignedMinVal,
325f610110fSNikita Popov SMin.isNegative() ? SignedMinVal + SMin : SignedMinVal);
326b32823cbSTim Shen }
327f610110fSNikita Popov
328f610110fSNikita Popov case Instruction::Mul:
329f610110fSNikita Popov if (Unsigned)
330f610110fSNikita Popov return makeExactMulNUWRegion(Other.getUnsignedMax());
331f610110fSNikita Popov
332f610110fSNikita Popov return makeExactMulNSWRegion(Other.getSignedMin())
333f610110fSNikita Popov .intersectWith(makeExactMulNSWRegion(Other.getSignedMax()));
3344b622326SRoman Lebedev
3354b622326SRoman Lebedev case Instruction::Shl: {
3364b622326SRoman Lebedev // For given range of shift amounts, if we ignore all illegal shift amounts
3374b622326SRoman Lebedev // (that always produce poison), what shift amount range is left?
3384b622326SRoman Lebedev ConstantRange ShAmt = Other.intersectWith(
3394b622326SRoman Lebedev ConstantRange(APInt(BitWidth, 0), APInt(BitWidth, (BitWidth - 1) + 1)));
3404b622326SRoman Lebedev if (ShAmt.isEmptySet()) {
3414b622326SRoman Lebedev // If the entire range of shift amounts is already poison-producing,
3424b622326SRoman Lebedev // then we can freely add more poison-producing flags ontop of that.
3434b622326SRoman Lebedev return getFull(BitWidth);
3444b622326SRoman Lebedev }
3454b622326SRoman Lebedev // There are some legal shift amounts, we can compute conservatively-correct
3464b622326SRoman Lebedev // range of no-wrap inputs. Note that by now we have clamped the ShAmtUMax
3474b622326SRoman Lebedev // to be at most bitwidth-1, which results in most conservative range.
3484b622326SRoman Lebedev APInt ShAmtUMax = ShAmt.getUnsignedMax();
3494b622326SRoman Lebedev if (Unsigned)
350735f4671SChris Lattner return getNonEmpty(APInt::getZero(BitWidth),
3514b622326SRoman Lebedev APInt::getMaxValue(BitWidth).lshr(ShAmtUMax) + 1);
3524b622326SRoman Lebedev return getNonEmpty(APInt::getSignedMinValue(BitWidth).ashr(ShAmtUMax),
3534b622326SRoman Lebedev APInt::getSignedMaxValue(BitWidth).ashr(ShAmtUMax) + 1);
3544b622326SRoman Lebedev }
355c32b0fc2SJoel Galenson }
3566ed05305SSanjoy Das }
3576ed05305SSanjoy Das
makeExactNoWrapRegion(Instruction::BinaryOps BinOp,const APInt & Other,unsigned NoWrapKind)3587a94795bSNikita Popov ConstantRange ConstantRange::makeExactNoWrapRegion(Instruction::BinaryOps BinOp,
3597a94795bSNikita Popov const APInt &Other,
3607a94795bSNikita Popov unsigned NoWrapKind) {
3617a94795bSNikita Popov // makeGuaranteedNoWrapRegion() is exact for single-element ranges, as
3627a94795bSNikita Popov // "for all" and "for any" coincide in this case.
3637a94795bSNikita Popov return makeGuaranteedNoWrapRegion(BinOp, ConstantRange(Other), NoWrapKind);
3647a94795bSNikita Popov }
3657a94795bSNikita Popov
isFullSet() const3668cd041efSChandler Carruth bool ConstantRange::isFullSet() const {
3678cd041efSChandler Carruth return Lower == Upper && Lower.isMaxValue();
3688cd041efSChandler Carruth }
3698cd041efSChandler Carruth
isEmptySet() const3708cd041efSChandler Carruth bool ConstantRange::isEmptySet() const {
3718cd041efSChandler Carruth return Lower == Upper && Lower.isMinValue();
3728cd041efSChandler Carruth }
3738cd041efSChandler Carruth
isWrappedSet() const3747b4e9a1cSNikita Popov bool ConstantRange::isWrappedSet() const {
375735f4671SChris Lattner return Lower.ugt(Upper) && !Upper.isZero();
3767b4e9a1cSNikita Popov }
3777b4e9a1cSNikita Popov
isUpperWrapped() const3786d855ea0SNikita Popov bool ConstantRange::isUpperWrapped() const {
3798cd041efSChandler Carruth return Lower.ugt(Upper);
3808cd041efSChandler Carruth }
3818cd041efSChandler Carruth
isSignWrappedSet() const3828cd041efSChandler Carruth bool ConstantRange::isSignWrappedSet() const {
383e6eef49fSNikita Popov return Lower.sgt(Upper) && !Upper.isMinSignedValue();
3848cd041efSChandler Carruth }
3858cd041efSChandler Carruth
isUpperSignWrapped() const3867b4e9a1cSNikita Popov bool ConstantRange::isUpperSignWrapped() const {
3877b4e9a1cSNikita Popov return Lower.sgt(Upper);
3887b4e9a1cSNikita Popov }
3897b4e9a1cSNikita Popov
390c69955c6SMichael Zolotukhin bool
isSizeStrictlySmallerThan(const ConstantRange & Other) const391d29549e9SCraig Topper ConstantRange::isSizeStrictlySmallerThan(const ConstantRange &Other) const {
392c69955c6SMichael Zolotukhin assert(getBitWidth() == Other.getBitWidth());
393c69955c6SMichael Zolotukhin if (isFullSet())
394c69955c6SMichael Zolotukhin return false;
395c69955c6SMichael Zolotukhin if (Other.isFullSet())
396c69955c6SMichael Zolotukhin return true;
397c69955c6SMichael Zolotukhin return (Upper - Lower).ult(Other.Upper - Other.Lower);
398c69955c6SMichael Zolotukhin }
399c69955c6SMichael Zolotukhin
4007e3e7afcSCraig Topper bool
isSizeLargerThan(uint64_t MaxSize) const4017e3e7afcSCraig Topper ConstantRange::isSizeLargerThan(uint64_t MaxSize) const {
4027e3e7afcSCraig Topper // If this a full set, we need special handling to avoid needing an extra bit
4037e3e7afcSCraig Topper // to represent the size.
4047e3e7afcSCraig Topper if (isFullSet())
405cf71a5eaSNikita Popov return MaxSize == 0 || APInt::getMaxValue(getBitWidth()).ugt(MaxSize - 1);
4067e3e7afcSCraig Topper
4077e3e7afcSCraig Topper return (Upper - Lower).ugt(MaxSize);
4087e3e7afcSCraig Topper }
4097e3e7afcSCraig Topper
isAllNegative() const410bad648a2SNikita Popov bool ConstantRange::isAllNegative() const {
411bad648a2SNikita Popov // Empty set is all negative, full set is not.
412bad648a2SNikita Popov if (isEmptySet())
413bad648a2SNikita Popov return true;
414bad648a2SNikita Popov if (isFullSet())
415bad648a2SNikita Popov return false;
416bad648a2SNikita Popov
417bad648a2SNikita Popov return !isUpperSignWrapped() && !Upper.isStrictlyPositive();
418bad648a2SNikita Popov }
419bad648a2SNikita Popov
isAllNonNegative() const420bad648a2SNikita Popov bool ConstantRange::isAllNonNegative() const {
421bad648a2SNikita Popov // Empty and full set are automatically treated correctly.
422bad648a2SNikita Popov return !isSignWrappedSet() && Lower.isNonNegative();
423bad648a2SNikita Popov }
424bad648a2SNikita Popov
getUnsignedMax() const4258cd041efSChandler Carruth APInt ConstantRange::getUnsignedMax() const {
4266d855ea0SNikita Popov if (isFullSet() || isUpperWrapped())
4278cd041efSChandler Carruth return APInt::getMaxValue(getBitWidth());
4288cd041efSChandler Carruth return getUpper() - 1;
4298cd041efSChandler Carruth }
4308cd041efSChandler Carruth
getUnsignedMin() const4318cd041efSChandler Carruth APInt ConstantRange::getUnsignedMin() const {
4327b4e9a1cSNikita Popov if (isFullSet() || isWrappedSet())
4338cd041efSChandler Carruth return APInt::getMinValue(getBitWidth());
4348cd041efSChandler Carruth return getLower();
4358cd041efSChandler Carruth }
4368cd041efSChandler Carruth
getSignedMax() const4378cd041efSChandler Carruth APInt ConstantRange::getSignedMax() const {
4387b4e9a1cSNikita Popov if (isFullSet() || isUpperSignWrapped())
43988c64f32SCraig Topper return APInt::getSignedMaxValue(getBitWidth());
4408cd041efSChandler Carruth return getUpper() - 1;
4418cd041efSChandler Carruth }
4428cd041efSChandler Carruth
getSignedMin() const4438cd041efSChandler Carruth APInt ConstantRange::getSignedMin() const {
4447b4e9a1cSNikita Popov if (isFullSet() || isSignWrappedSet())
44588c64f32SCraig Topper return APInt::getSignedMinValue(getBitWidth());
4468cd041efSChandler Carruth return getLower();
4478cd041efSChandler Carruth }
4488cd041efSChandler Carruth
contains(const APInt & V) const4498cd041efSChandler Carruth bool ConstantRange::contains(const APInt &V) const {
4508cd041efSChandler Carruth if (Lower == Upper)
4518cd041efSChandler Carruth return isFullSet();
4528cd041efSChandler Carruth
4536d855ea0SNikita Popov if (!isUpperWrapped())
4548cd041efSChandler Carruth return Lower.ule(V) && V.ult(Upper);
4558cd041efSChandler Carruth return Lower.ule(V) || V.ult(Upper);
4568cd041efSChandler Carruth }
4578cd041efSChandler Carruth
contains(const ConstantRange & Other) const4588cd041efSChandler Carruth bool ConstantRange::contains(const ConstantRange &Other) const {
4598cd041efSChandler Carruth if (isFullSet() || Other.isEmptySet()) return true;
4608cd041efSChandler Carruth if (isEmptySet() || Other.isFullSet()) return false;
4618cd041efSChandler Carruth
4626d855ea0SNikita Popov if (!isUpperWrapped()) {
4636d855ea0SNikita Popov if (Other.isUpperWrapped())
4648cd041efSChandler Carruth return false;
4658cd041efSChandler Carruth
4668cd041efSChandler Carruth return Lower.ule(Other.getLower()) && Other.getUpper().ule(Upper);
4678cd041efSChandler Carruth }
4688cd041efSChandler Carruth
4696d855ea0SNikita Popov if (!Other.isUpperWrapped())
4708cd041efSChandler Carruth return Other.getUpper().ule(Upper) ||
4718cd041efSChandler Carruth Lower.ule(Other.getLower());
4728cd041efSChandler Carruth
4738cd041efSChandler Carruth return Other.getUpper().ule(Upper) && Lower.ule(Other.getLower());
4748cd041efSChandler Carruth }
4758cd041efSChandler Carruth
getActiveBits() const4762ed9c4c7SRoman Lebedev unsigned ConstantRange::getActiveBits() const {
4772ed9c4c7SRoman Lebedev if (isEmptySet())
4782ed9c4c7SRoman Lebedev return 0;
4792ed9c4c7SRoman Lebedev
4802ed9c4c7SRoman Lebedev return getUnsignedMax().getActiveBits();
4812ed9c4c7SRoman Lebedev }
4822ed9c4c7SRoman Lebedev
getMinSignedBits() const4837465da20SRoman Lebedev unsigned ConstantRange::getMinSignedBits() const {
4847465da20SRoman Lebedev if (isEmptySet())
4857465da20SRoman Lebedev return 0;
4867465da20SRoman Lebedev
4877465da20SRoman Lebedev return std::max(getSignedMin().getMinSignedBits(),
4887465da20SRoman Lebedev getSignedMax().getMinSignedBits());
4897465da20SRoman Lebedev }
4907465da20SRoman Lebedev
subtract(const APInt & Val) const4918cd041efSChandler Carruth ConstantRange ConstantRange::subtract(const APInt &Val) const {
4928cd041efSChandler Carruth assert(Val.getBitWidth() == getBitWidth() && "Wrong bit width");
4938cd041efSChandler Carruth // If the set is empty or full, don't modify the endpoints.
4948cd041efSChandler Carruth if (Lower == Upper)
4958cd041efSChandler Carruth return *this;
4968cd041efSChandler Carruth return ConstantRange(Lower - Val, Upper - Val);
4978cd041efSChandler Carruth }
4988cd041efSChandler Carruth
difference(const ConstantRange & CR) const4998cd041efSChandler Carruth ConstantRange ConstantRange::difference(const ConstantRange &CR) const {
5008cd041efSChandler Carruth return intersectWith(CR.inverse());
5018cd041efSChandler Carruth }
5028cd041efSChandler Carruth
getPreferredRange(const ConstantRange & CR1,const ConstantRange & CR2,ConstantRange::PreferredRangeType Type)5034246106aSNikita Popov static ConstantRange getPreferredRange(
5044246106aSNikita Popov const ConstantRange &CR1, const ConstantRange &CR2,
5054246106aSNikita Popov ConstantRange::PreferredRangeType Type) {
5064246106aSNikita Popov if (Type == ConstantRange::Unsigned) {
5074246106aSNikita Popov if (!CR1.isWrappedSet() && CR2.isWrappedSet())
5084246106aSNikita Popov return CR1;
5094246106aSNikita Popov if (CR1.isWrappedSet() && !CR2.isWrappedSet())
5104246106aSNikita Popov return CR2;
5114246106aSNikita Popov } else if (Type == ConstantRange::Signed) {
5124246106aSNikita Popov if (!CR1.isSignWrappedSet() && CR2.isSignWrappedSet())
5134246106aSNikita Popov return CR1;
5144246106aSNikita Popov if (CR1.isSignWrappedSet() && !CR2.isSignWrappedSet())
5154246106aSNikita Popov return CR2;
5164246106aSNikita Popov }
5174246106aSNikita Popov
5184246106aSNikita Popov if (CR1.isSizeStrictlySmallerThan(CR2))
5194246106aSNikita Popov return CR1;
5204246106aSNikita Popov return CR2;
5214246106aSNikita Popov }
5224246106aSNikita Popov
intersectWith(const ConstantRange & CR,PreferredRangeType Type) const5234246106aSNikita Popov ConstantRange ConstantRange::intersectWith(const ConstantRange &CR,
5244246106aSNikita Popov PreferredRangeType Type) const {
5258cd041efSChandler Carruth assert(getBitWidth() == CR.getBitWidth() &&
5268cd041efSChandler Carruth "ConstantRange types don't agree!");
5278cd041efSChandler Carruth
5288cd041efSChandler Carruth // Handle common cases.
5298cd041efSChandler Carruth if ( isEmptySet() || CR.isFullSet()) return *this;
5308cd041efSChandler Carruth if (CR.isEmptySet() || isFullSet()) return CR;
5318cd041efSChandler Carruth
5326d855ea0SNikita Popov if (!isUpperWrapped() && CR.isUpperWrapped())
5334246106aSNikita Popov return CR.intersectWith(*this, Type);
5348cd041efSChandler Carruth
5356d855ea0SNikita Popov if (!isUpperWrapped() && !CR.isUpperWrapped()) {
5368cd041efSChandler Carruth if (Lower.ult(CR.Lower)) {
5374246106aSNikita Popov // L---U : this
5384246106aSNikita Popov // L---U : CR
5398cd041efSChandler Carruth if (Upper.ule(CR.Lower))
540977934f0SNikita Popov return getEmpty();
5418cd041efSChandler Carruth
5424246106aSNikita Popov // L---U : this
5434246106aSNikita Popov // L---U : CR
5448cd041efSChandler Carruth if (Upper.ult(CR.Upper))
5458cd041efSChandler Carruth return ConstantRange(CR.Lower, Upper);
5468cd041efSChandler Carruth
5474246106aSNikita Popov // L-------U : this
5484246106aSNikita Popov // L---U : CR
5498cd041efSChandler Carruth return CR;
5508cd041efSChandler Carruth }
5514246106aSNikita Popov // L---U : this
5524246106aSNikita Popov // L-------U : CR
5538cd041efSChandler Carruth if (Upper.ult(CR.Upper))
5548cd041efSChandler Carruth return *this;
5558cd041efSChandler Carruth
5564246106aSNikita Popov // L-----U : this
5574246106aSNikita Popov // L-----U : CR
5588cd041efSChandler Carruth if (Lower.ult(CR.Upper))
5598cd041efSChandler Carruth return ConstantRange(Lower, CR.Upper);
5608cd041efSChandler Carruth
5614246106aSNikita Popov // L---U : this
5624246106aSNikita Popov // L---U : CR
563977934f0SNikita Popov return getEmpty();
5648cd041efSChandler Carruth }
5658cd041efSChandler Carruth
5666d855ea0SNikita Popov if (isUpperWrapped() && !CR.isUpperWrapped()) {
5678cd041efSChandler Carruth if (CR.Lower.ult(Upper)) {
5684246106aSNikita Popov // ------U L--- : this
5694246106aSNikita Popov // L--U : CR
5708cd041efSChandler Carruth if (CR.Upper.ult(Upper))
5718cd041efSChandler Carruth return CR;
5728cd041efSChandler Carruth
5734246106aSNikita Popov // ------U L--- : this
5744246106aSNikita Popov // L------U : CR
5758cd041efSChandler Carruth if (CR.Upper.ule(Lower))
5768cd041efSChandler Carruth return ConstantRange(CR.Lower, Upper);
5778cd041efSChandler Carruth
5784246106aSNikita Popov // ------U L--- : this
5794246106aSNikita Popov // L----------U : CR
5804246106aSNikita Popov return getPreferredRange(*this, CR, Type);
5818cd041efSChandler Carruth }
5828cd041efSChandler Carruth if (CR.Lower.ult(Lower)) {
5834246106aSNikita Popov // --U L---- : this
5844246106aSNikita Popov // L--U : CR
5858cd041efSChandler Carruth if (CR.Upper.ule(Lower))
586977934f0SNikita Popov return getEmpty();
5878cd041efSChandler Carruth
5884246106aSNikita Popov // --U L---- : this
5894246106aSNikita Popov // L------U : CR
5908cd041efSChandler Carruth return ConstantRange(Lower, CR.Upper);
5918cd041efSChandler Carruth }
5924246106aSNikita Popov
5934246106aSNikita Popov // --U L------ : this
5944246106aSNikita Popov // L--U : CR
5958cd041efSChandler Carruth return CR;
5968cd041efSChandler Carruth }
5978cd041efSChandler Carruth
5988cd041efSChandler Carruth if (CR.Upper.ult(Upper)) {
5994246106aSNikita Popov // ------U L-- : this
6004246106aSNikita Popov // --U L------ : CR
6014246106aSNikita Popov if (CR.Lower.ult(Upper))
6024246106aSNikita Popov return getPreferredRange(*this, CR, Type);
6038cd041efSChandler Carruth
6044246106aSNikita Popov // ----U L-- : this
6054246106aSNikita Popov // --U L---- : CR
6068cd041efSChandler Carruth if (CR.Lower.ult(Lower))
6078cd041efSChandler Carruth return ConstantRange(Lower, CR.Upper);
6088cd041efSChandler Carruth
6094246106aSNikita Popov // ----U L---- : this
6104246106aSNikita Popov // --U L-- : CR
6118cd041efSChandler Carruth return CR;
6128cd041efSChandler Carruth }
6138cd041efSChandler Carruth if (CR.Upper.ule(Lower)) {
6144246106aSNikita Popov // --U L-- : this
6154246106aSNikita Popov // ----U L---- : CR
6168cd041efSChandler Carruth if (CR.Lower.ult(Lower))
6178cd041efSChandler Carruth return *this;
6188cd041efSChandler Carruth
6194246106aSNikita Popov // --U L---- : this
6204246106aSNikita Popov // ----U L-- : CR
6218cd041efSChandler Carruth return ConstantRange(CR.Lower, Upper);
6228cd041efSChandler Carruth }
6234246106aSNikita Popov
6244246106aSNikita Popov // --U L------ : this
6254246106aSNikita Popov // ------U L-- : CR
6264246106aSNikita Popov return getPreferredRange(*this, CR, Type);
6278cd041efSChandler Carruth }
6288cd041efSChandler Carruth
unionWith(const ConstantRange & CR,PreferredRangeType Type) const629f38b46ffSNikita Popov ConstantRange ConstantRange::unionWith(const ConstantRange &CR,
630f38b46ffSNikita Popov PreferredRangeType Type) const {
6318cd041efSChandler Carruth assert(getBitWidth() == CR.getBitWidth() &&
6328cd041efSChandler Carruth "ConstantRange types don't agree!");
6338cd041efSChandler Carruth
6348cd041efSChandler Carruth if ( isFullSet() || CR.isEmptySet()) return *this;
6358cd041efSChandler Carruth if (CR.isFullSet() || isEmptySet()) return CR;
6368cd041efSChandler Carruth
637f38b46ffSNikita Popov if (!isUpperWrapped() && CR.isUpperWrapped())
638f38b46ffSNikita Popov return CR.unionWith(*this, Type);
6398cd041efSChandler Carruth
6406d855ea0SNikita Popov if (!isUpperWrapped() && !CR.isUpperWrapped()) {
641f38b46ffSNikita Popov // L---U and L---U : this
642f38b46ffSNikita Popov // L---U L---U : CR
643f38b46ffSNikita Popov // result in one of
644f38b46ffSNikita Popov // L---------U
645f38b46ffSNikita Popov // -----U L-----
646f38b46ffSNikita Popov if (CR.Upper.ult(Lower) || Upper.ult(CR.Lower))
647f38b46ffSNikita Popov return getPreferredRange(
648f38b46ffSNikita Popov ConstantRange(Lower, CR.Upper), ConstantRange(CR.Lower, Upper), Type);
6498cd041efSChandler Carruth
6508fb5a14cSCraig Topper APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower;
6518fb5a14cSCraig Topper APInt U = (CR.Upper - 1).ugt(Upper - 1) ? CR.Upper : Upper;
6528cd041efSChandler Carruth
653735f4671SChris Lattner if (L.isZero() && U.isZero())
654977934f0SNikita Popov return getFull();
6558cd041efSChandler Carruth
656b792025bSCraig Topper return ConstantRange(std::move(L), std::move(U));
6578cd041efSChandler Carruth }
6588cd041efSChandler Carruth
6596d855ea0SNikita Popov if (!CR.isUpperWrapped()) {
6608cd041efSChandler Carruth // ------U L----- and ------U L----- : this
6618cd041efSChandler Carruth // L--U L--U : CR
6628cd041efSChandler Carruth if (CR.Upper.ule(Upper) || CR.Lower.uge(Lower))
6638cd041efSChandler Carruth return *this;
6648cd041efSChandler Carruth
6658cd041efSChandler Carruth // ------U L----- : this
6668cd041efSChandler Carruth // L---------U : CR
6678cd041efSChandler Carruth if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper))
668977934f0SNikita Popov return getFull();
6698cd041efSChandler Carruth
6708cd041efSChandler Carruth // ----U L---- : this
6718cd041efSChandler Carruth // L---U : CR
672f38b46ffSNikita Popov // results in one of
673f38b46ffSNikita Popov // ----------U L----
674f38b46ffSNikita Popov // ----U L----------
675f38b46ffSNikita Popov if (Upper.ult(CR.Lower) && CR.Upper.ult(Lower))
676f38b46ffSNikita Popov return getPreferredRange(
677f38b46ffSNikita Popov ConstantRange(Lower, CR.Upper), ConstantRange(CR.Lower, Upper), Type);
6788cd041efSChandler Carruth
6798cd041efSChandler Carruth // ----U L----- : this
6808cd041efSChandler Carruth // L----U : CR
681f38b46ffSNikita Popov if (Upper.ult(CR.Lower) && Lower.ule(CR.Upper))
6828cd041efSChandler Carruth return ConstantRange(CR.Lower, Upper);
6838cd041efSChandler Carruth
6848cd041efSChandler Carruth // ------U L---- : this
6858cd041efSChandler Carruth // L-----U : CR
686f38b46ffSNikita Popov assert(CR.Lower.ule(Upper) && CR.Upper.ult(Lower) &&
6878cd041efSChandler Carruth "ConstantRange::unionWith missed a case with one range wrapped");
6888cd041efSChandler Carruth return ConstantRange(Lower, CR.Upper);
6898cd041efSChandler Carruth }
6908cd041efSChandler Carruth
6918cd041efSChandler Carruth // ------U L---- and ------U L---- : this
6928cd041efSChandler Carruth // -U L----------- and ------------U L : CR
6938cd041efSChandler Carruth if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper))
694977934f0SNikita Popov return getFull();
6958cd041efSChandler Carruth
6968fb5a14cSCraig Topper APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower;
6978fb5a14cSCraig Topper APInt U = CR.Upper.ugt(Upper) ? CR.Upper : Upper;
6988cd041efSChandler Carruth
699b792025bSCraig Topper return ConstantRange(std::move(L), std::move(U));
7008cd041efSChandler Carruth }
7018cd041efSChandler Carruth
7022060895cSNikita Popov Optional<ConstantRange>
exactIntersectWith(const ConstantRange & CR) const7032060895cSNikita Popov ConstantRange::exactIntersectWith(const ConstantRange &CR) const {
7042060895cSNikita Popov // TODO: This can be implemented more efficiently.
7052060895cSNikita Popov ConstantRange Result = intersectWith(CR);
7062060895cSNikita Popov if (Result == inverse().unionWith(CR.inverse()).inverse())
7072060895cSNikita Popov return Result;
7082060895cSNikita Popov return None;
7092060895cSNikita Popov }
7102060895cSNikita Popov
7112060895cSNikita Popov Optional<ConstantRange>
exactUnionWith(const ConstantRange & CR) const7122060895cSNikita Popov ConstantRange::exactUnionWith(const ConstantRange &CR) const {
7132060895cSNikita Popov // TODO: This can be implemented more efficiently.
7142060895cSNikita Popov ConstantRange Result = unionWith(CR);
7152060895cSNikita Popov if (Result == inverse().intersectWith(CR.inverse()).inverse())
7162060895cSNikita Popov return Result;
7172060895cSNikita Popov return None;
7182060895cSNikita Popov }
7192060895cSNikita Popov
castOp(Instruction::CastOps CastOp,uint32_t ResultBitWidth) const7204d00af1bSPhilip Reames ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp,
7214d00af1bSPhilip Reames uint32_t ResultBitWidth) const {
7224d00af1bSPhilip Reames switch (CastOp) {
7234d00af1bSPhilip Reames default:
7244d00af1bSPhilip Reames llvm_unreachable("unsupported cast type");
7254d00af1bSPhilip Reames case Instruction::Trunc:
7264d00af1bSPhilip Reames return truncate(ResultBitWidth);
7274d00af1bSPhilip Reames case Instruction::SExt:
7284d00af1bSPhilip Reames return signExtend(ResultBitWidth);
7294d00af1bSPhilip Reames case Instruction::ZExt:
7304d00af1bSPhilip Reames return zeroExtend(ResultBitWidth);
7314d00af1bSPhilip Reames case Instruction::BitCast:
7324d00af1bSPhilip Reames return *this;
7334d00af1bSPhilip Reames case Instruction::FPToUI:
7344d00af1bSPhilip Reames case Instruction::FPToSI:
7354d00af1bSPhilip Reames if (getBitWidth() == ResultBitWidth)
7364d00af1bSPhilip Reames return *this;
7374d00af1bSPhilip Reames else
738b35c585aSFlorian Hahn return getFull(ResultBitWidth);
7394d00af1bSPhilip Reames case Instruction::UIToFP: {
7404d00af1bSPhilip Reames // TODO: use input range if available
7414d00af1bSPhilip Reames auto BW = getBitWidth();
7426bec3e93SJay Foad APInt Min = APInt::getMinValue(BW);
7436bec3e93SJay Foad APInt Max = APInt::getMaxValue(BW);
7446bec3e93SJay Foad if (ResultBitWidth > BW) {
7456bec3e93SJay Foad Min = Min.zext(ResultBitWidth);
7466bec3e93SJay Foad Max = Max.zext(ResultBitWidth);
7476bec3e93SJay Foad }
748b792025bSCraig Topper return ConstantRange(std::move(Min), std::move(Max));
7494d00af1bSPhilip Reames }
7504d00af1bSPhilip Reames case Instruction::SIToFP: {
7514d00af1bSPhilip Reames // TODO: use input range if available
7524d00af1bSPhilip Reames auto BW = getBitWidth();
7536bec3e93SJay Foad APInt SMin = APInt::getSignedMinValue(BW);
7546bec3e93SJay Foad APInt SMax = APInt::getSignedMaxValue(BW);
7556bec3e93SJay Foad if (ResultBitWidth > BW) {
7566bec3e93SJay Foad SMin = SMin.sext(ResultBitWidth);
7576bec3e93SJay Foad SMax = SMax.sext(ResultBitWidth);
7586bec3e93SJay Foad }
759b792025bSCraig Topper return ConstantRange(std::move(SMin), std::move(SMax));
7604d00af1bSPhilip Reames }
7614d00af1bSPhilip Reames case Instruction::FPTrunc:
7624d00af1bSPhilip Reames case Instruction::FPExt:
7634d00af1bSPhilip Reames case Instruction::IntToPtr:
7644d00af1bSPhilip Reames case Instruction::PtrToInt:
7654d00af1bSPhilip Reames case Instruction::AddrSpaceCast:
766977934f0SNikita Popov // Conservatively return getFull set.
767b35c585aSFlorian Hahn return getFull(ResultBitWidth);
7684d00af1bSPhilip Reames };
7694d00af1bSPhilip Reames }
7704d00af1bSPhilip Reames
zeroExtend(uint32_t DstTySize) const7718cd041efSChandler Carruth ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const {
772977934f0SNikita Popov if (isEmptySet()) return getEmpty(DstTySize);
7738cd041efSChandler Carruth
7748cd041efSChandler Carruth unsigned SrcTySize = getBitWidth();
7758cd041efSChandler Carruth assert(SrcTySize < DstTySize && "Not a value extension");
7766d855ea0SNikita Popov if (isFullSet() || isUpperWrapped()) {
7778cd041efSChandler Carruth // Change into [0, 1 << src bit width)
7788cd041efSChandler Carruth APInt LowerExt(DstTySize, 0);
7798cd041efSChandler Carruth if (!Upper) // special case: [X, 0) -- not really wrapping around
7808cd041efSChandler Carruth LowerExt = Lower.zext(DstTySize);
781b792025bSCraig Topper return ConstantRange(std::move(LowerExt),
782b792025bSCraig Topper APInt::getOneBitSet(DstTySize, SrcTySize));
7838cd041efSChandler Carruth }
7848cd041efSChandler Carruth
7858cd041efSChandler Carruth return ConstantRange(Lower.zext(DstTySize), Upper.zext(DstTySize));
7868cd041efSChandler Carruth }
7878cd041efSChandler Carruth
signExtend(uint32_t DstTySize) const7888cd041efSChandler Carruth ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const {
789977934f0SNikita Popov if (isEmptySet()) return getEmpty(DstTySize);
7908cd041efSChandler Carruth
7918cd041efSChandler Carruth unsigned SrcTySize = getBitWidth();
7928cd041efSChandler Carruth assert(SrcTySize < DstTySize && "Not a value extension");
7938cd041efSChandler Carruth
7948cd041efSChandler Carruth // special case: [X, INT_MIN) -- not really wrapping around
7958cd041efSChandler Carruth if (Upper.isMinSignedValue())
7968cd041efSChandler Carruth return ConstantRange(Lower.sext(DstTySize), Upper.zext(DstTySize));
7978cd041efSChandler Carruth
7988cd041efSChandler Carruth if (isFullSet() || isSignWrappedSet()) {
7998cd041efSChandler Carruth return ConstantRange(APInt::getHighBitsSet(DstTySize,DstTySize-SrcTySize+1),
8008cd041efSChandler Carruth APInt::getLowBitsSet(DstTySize, SrcTySize-1) + 1);
8018cd041efSChandler Carruth }
8028cd041efSChandler Carruth
8038cd041efSChandler Carruth return ConstantRange(Lower.sext(DstTySize), Upper.sext(DstTySize));
8048cd041efSChandler Carruth }
8058cd041efSChandler Carruth
truncate(uint32_t DstTySize) const8068cd041efSChandler Carruth ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
8078cd041efSChandler Carruth assert(getBitWidth() > DstTySize && "Not a value truncation");
8088cd041efSChandler Carruth if (isEmptySet())
809977934f0SNikita Popov return getEmpty(DstTySize);
8108cd041efSChandler Carruth if (isFullSet())
811977934f0SNikita Popov return getFull(DstTySize);
8128cd041efSChandler Carruth
8138cd041efSChandler Carruth APInt LowerDiv(Lower), UpperDiv(Upper);
8148cd041efSChandler Carruth ConstantRange Union(DstTySize, /*isFullSet=*/false);
8158cd041efSChandler Carruth
8168cd041efSChandler Carruth // Analyze wrapped sets in their two parts: [0, Upper) \/ [Lower, MaxValue]
8178cd041efSChandler Carruth // We use the non-wrapped set code to analyze the [Lower, MaxValue) part, and
8188cd041efSChandler Carruth // then we do the union with [MaxValue, Upper)
8196d855ea0SNikita Popov if (isUpperWrapped()) {
820f6e138d7SCraig Topper // If Upper is greater than or equal to MaxValue(DstTy), it covers the whole
821f6e138d7SCraig Topper // truncated range.
822f6e138d7SCraig Topper if (Upper.getActiveBits() > DstTySize ||
823f6e138d7SCraig Topper Upper.countTrailingOnes() == DstTySize)
824977934f0SNikita Popov return getFull(DstTySize);
8258cd041efSChandler Carruth
8268cd041efSChandler Carruth Union = ConstantRange(APInt::getMaxValue(DstTySize),Upper.trunc(DstTySize));
82786616530SCraig Topper UpperDiv.setAllBits();
8288cd041efSChandler Carruth
8298cd041efSChandler Carruth // Union covers the MaxValue case, so return if the remaining range is just
830f6e138d7SCraig Topper // MaxValue(DstTy).
8318cd041efSChandler Carruth if (LowerDiv == UpperDiv)
8328cd041efSChandler Carruth return Union;
8338cd041efSChandler Carruth }
8348cd041efSChandler Carruth
8358cd041efSChandler Carruth // Chop off the most significant bits that are past the destination bitwidth.
836f6e138d7SCraig Topper if (LowerDiv.getActiveBits() > DstTySize) {
837f6e138d7SCraig Topper // Mask to just the signficant bits and subtract from LowerDiv/UpperDiv.
838f6e138d7SCraig Topper APInt Adjust = LowerDiv & APInt::getBitsSetFrom(getBitWidth(), DstTySize);
839f6e138d7SCraig Topper LowerDiv -= Adjust;
840f6e138d7SCraig Topper UpperDiv -= Adjust;
8418cd041efSChandler Carruth }
8428cd041efSChandler Carruth
843f6e138d7SCraig Topper unsigned UpperDivWidth = UpperDiv.getActiveBits();
844f6e138d7SCraig Topper if (UpperDivWidth <= DstTySize)
8458cd041efSChandler Carruth return ConstantRange(LowerDiv.trunc(DstTySize),
8468cd041efSChandler Carruth UpperDiv.trunc(DstTySize)).unionWith(Union);
8478cd041efSChandler Carruth
848bfad0155SNick Lewycky // The truncated value wraps around. Check if we can do better than fullset.
849f6e138d7SCraig Topper if (UpperDivWidth == DstTySize + 1) {
850f6e138d7SCraig Topper // Clear the MSB so that UpperDiv wraps around.
851f6e138d7SCraig Topper UpperDiv.clearBit(DstTySize);
852685327ddSCraig Topper if (UpperDiv.ult(LowerDiv))
8538cd041efSChandler Carruth return ConstantRange(LowerDiv.trunc(DstTySize),
854685327ddSCraig Topper UpperDiv.trunc(DstTySize)).unionWith(Union);
855f6e138d7SCraig Topper }
8568cd041efSChandler Carruth
857977934f0SNikita Popov return getFull(DstTySize);
8588cd041efSChandler Carruth }
8598cd041efSChandler Carruth
zextOrTrunc(uint32_t DstTySize) const8608cd041efSChandler Carruth ConstantRange ConstantRange::zextOrTrunc(uint32_t DstTySize) const {
8618cd041efSChandler Carruth unsigned SrcTySize = getBitWidth();
8628cd041efSChandler Carruth if (SrcTySize > DstTySize)
8638cd041efSChandler Carruth return truncate(DstTySize);
8648cd041efSChandler Carruth if (SrcTySize < DstTySize)
8658cd041efSChandler Carruth return zeroExtend(DstTySize);
8668cd041efSChandler Carruth return *this;
8678cd041efSChandler Carruth }
8688cd041efSChandler Carruth
sextOrTrunc(uint32_t DstTySize) const8698cd041efSChandler Carruth ConstantRange ConstantRange::sextOrTrunc(uint32_t DstTySize) const {
8708cd041efSChandler Carruth unsigned SrcTySize = getBitWidth();
8718cd041efSChandler Carruth if (SrcTySize > DstTySize)
8728cd041efSChandler Carruth return truncate(DstTySize);
8738cd041efSChandler Carruth if (SrcTySize < DstTySize)
8748cd041efSChandler Carruth return signExtend(DstTySize);
8758cd041efSChandler Carruth return *this;
8768cd041efSChandler Carruth }
8778cd041efSChandler Carruth
binaryOp(Instruction::BinaryOps BinOp,const ConstantRange & Other) const8784d00af1bSPhilip Reames ConstantRange ConstantRange::binaryOp(Instruction::BinaryOps BinOp,
8794d00af1bSPhilip Reames const ConstantRange &Other) const {
880e0a6eb1fSSimon Pilgrim assert(Instruction::isBinaryOp(BinOp) && "Binary operators only!");
8814d00af1bSPhilip Reames
8824d00af1bSPhilip Reames switch (BinOp) {
8834d00af1bSPhilip Reames case Instruction::Add:
8844d00af1bSPhilip Reames return add(Other);
8854d00af1bSPhilip Reames case Instruction::Sub:
8864d00af1bSPhilip Reames return sub(Other);
8874d00af1bSPhilip Reames case Instruction::Mul:
8884d00af1bSPhilip Reames return multiply(Other);
8894d00af1bSPhilip Reames case Instruction::UDiv:
8904d00af1bSPhilip Reames return udiv(Other);
891c061b99cSNikita Popov case Instruction::SDiv:
892c061b99cSNikita Popov return sdiv(Other);
893f945429fSNikita Popov case Instruction::URem:
894f945429fSNikita Popov return urem(Other);
895d5a403fbSNikita Popov case Instruction::SRem:
896d5a403fbSNikita Popov return srem(Other);
8974d00af1bSPhilip Reames case Instruction::Shl:
8984d00af1bSPhilip Reames return shl(Other);
8994d00af1bSPhilip Reames case Instruction::LShr:
9004d00af1bSPhilip Reames return lshr(Other);
901d792171eSMax Kazantsev case Instruction::AShr:
902d792171eSMax Kazantsev return ashr(Other);
9034d00af1bSPhilip Reames case Instruction::And:
9044d00af1bSPhilip Reames return binaryAnd(Other);
9054d00af1bSPhilip Reames case Instruction::Or:
9064d00af1bSPhilip Reames return binaryOr(Other);
9077caba339SFlorian Hahn case Instruction::Xor:
9087caba339SFlorian Hahn return binaryXor(Other);
9094d00af1bSPhilip Reames // Note: floating point operations applied to abstract ranges are just
9104d00af1bSPhilip Reames // ideal integer operations with a lossy representation
9114d00af1bSPhilip Reames case Instruction::FAdd:
9124d00af1bSPhilip Reames return add(Other);
9134d00af1bSPhilip Reames case Instruction::FSub:
9144d00af1bSPhilip Reames return sub(Other);
9154d00af1bSPhilip Reames case Instruction::FMul:
9164d00af1bSPhilip Reames return multiply(Other);
9174d00af1bSPhilip Reames default:
918977934f0SNikita Popov // Conservatively return getFull set.
919977934f0SNikita Popov return getFull();
9204d00af1bSPhilip Reames }
9214d00af1bSPhilip Reames }
9224d00af1bSPhilip Reames
overflowingBinaryOp(Instruction::BinaryOps BinOp,const ConstantRange & Other,unsigned NoWrapKind) const9231f665046SRoman Lebedev ConstantRange ConstantRange::overflowingBinaryOp(Instruction::BinaryOps BinOp,
9241f665046SRoman Lebedev const ConstantRange &Other,
9251f665046SRoman Lebedev unsigned NoWrapKind) const {
9261f665046SRoman Lebedev assert(Instruction::isBinaryOp(BinOp) && "Binary operators only!");
9271f665046SRoman Lebedev
9281f665046SRoman Lebedev switch (BinOp) {
9291f665046SRoman Lebedev case Instruction::Add:
9301f665046SRoman Lebedev return addWithNoWrap(Other, NoWrapKind);
93169ce2ae9SRoman Lebedev case Instruction::Sub:
93269ce2ae9SRoman Lebedev return subWithNoWrap(Other, NoWrapKind);
9331f665046SRoman Lebedev default:
9341f665046SRoman Lebedev // Don't know about this Overflowing Binary Operation.
9351f665046SRoman Lebedev // Conservatively fallback to plain binop handling.
9361f665046SRoman Lebedev return binaryOp(BinOp, Other);
9371f665046SRoman Lebedev }
9381f665046SRoman Lebedev }
9391f665046SRoman Lebedev
isIntrinsicSupported(Intrinsic::ID IntrinsicID)940897bdca4SNikita Popov bool ConstantRange::isIntrinsicSupported(Intrinsic::ID IntrinsicID) {
941897bdca4SNikita Popov switch (IntrinsicID) {
942897bdca4SNikita Popov case Intrinsic::uadd_sat:
943897bdca4SNikita Popov case Intrinsic::usub_sat:
944897bdca4SNikita Popov case Intrinsic::sadd_sat:
945897bdca4SNikita Popov case Intrinsic::ssub_sat:
946d8a98a9cSNikita Popov case Intrinsic::umin:
947d8a98a9cSNikita Popov case Intrinsic::umax:
948d8a98a9cSNikita Popov case Intrinsic::smin:
949d8a98a9cSNikita Popov case Intrinsic::smax:
950d8a98a9cSNikita Popov case Intrinsic::abs:
951897bdca4SNikita Popov return true;
952897bdca4SNikita Popov default:
953897bdca4SNikita Popov return false;
954897bdca4SNikita Popov }
955897bdca4SNikita Popov }
956897bdca4SNikita Popov
intrinsic(Intrinsic::ID IntrinsicID,ArrayRef<ConstantRange> Ops)957897bdca4SNikita Popov ConstantRange ConstantRange::intrinsic(Intrinsic::ID IntrinsicID,
958897bdca4SNikita Popov ArrayRef<ConstantRange> Ops) {
959897bdca4SNikita Popov switch (IntrinsicID) {
960897bdca4SNikita Popov case Intrinsic::uadd_sat:
961897bdca4SNikita Popov return Ops[0].uadd_sat(Ops[1]);
962897bdca4SNikita Popov case Intrinsic::usub_sat:
963897bdca4SNikita Popov return Ops[0].usub_sat(Ops[1]);
964897bdca4SNikita Popov case Intrinsic::sadd_sat:
965897bdca4SNikita Popov return Ops[0].sadd_sat(Ops[1]);
966897bdca4SNikita Popov case Intrinsic::ssub_sat:
967897bdca4SNikita Popov return Ops[0].ssub_sat(Ops[1]);
968d8a98a9cSNikita Popov case Intrinsic::umin:
969d8a98a9cSNikita Popov return Ops[0].umin(Ops[1]);
970d8a98a9cSNikita Popov case Intrinsic::umax:
971d8a98a9cSNikita Popov return Ops[0].umax(Ops[1]);
972d8a98a9cSNikita Popov case Intrinsic::smin:
973d8a98a9cSNikita Popov return Ops[0].smin(Ops[1]);
974d8a98a9cSNikita Popov case Intrinsic::smax:
975d8a98a9cSNikita Popov return Ops[0].smax(Ops[1]);
9769ebeac67SNikita Popov case Intrinsic::abs: {
9779ebeac67SNikita Popov const APInt *IntMinIsPoison = Ops[1].getSingleElement();
9789ebeac67SNikita Popov assert(IntMinIsPoison && "Must be known (immarg)");
9799ebeac67SNikita Popov assert(IntMinIsPoison->getBitWidth() == 1 && "Must be boolean");
9809ebeac67SNikita Popov return Ops[0].abs(IntMinIsPoison->getBoolValue());
9819ebeac67SNikita Popov }
982897bdca4SNikita Popov default:
983897bdca4SNikita Popov assert(!isIntrinsicSupported(IntrinsicID) && "Shouldn't be supported");
984897bdca4SNikita Popov llvm_unreachable("Unsupported intrinsic");
985897bdca4SNikita Popov }
986897bdca4SNikita Popov }
987897bdca4SNikita Popov
9888cd041efSChandler Carruth ConstantRange
add(const ConstantRange & Other) const9898cd041efSChandler Carruth ConstantRange::add(const ConstantRange &Other) const {
9908cd041efSChandler Carruth if (isEmptySet() || Other.isEmptySet())
991977934f0SNikita Popov return getEmpty();
9928cd041efSChandler Carruth if (isFullSet() || Other.isFullSet())
993977934f0SNikita Popov return getFull();
9948cd041efSChandler Carruth
9958cd041efSChandler Carruth APInt NewLower = getLower() + Other.getLower();
9968cd041efSChandler Carruth APInt NewUpper = getUpper() + Other.getUpper() - 1;
9978cd041efSChandler Carruth if (NewLower == NewUpper)
998977934f0SNikita Popov return getFull();
9998cd041efSChandler Carruth
1000b792025bSCraig Topper ConstantRange X = ConstantRange(std::move(NewLower), std::move(NewUpper));
1001d29549e9SCraig Topper if (X.isSizeStrictlySmallerThan(*this) ||
1002d29549e9SCraig Topper X.isSizeStrictlySmallerThan(Other))
10038cd041efSChandler Carruth // We've wrapped, therefore, full set.
1004977934f0SNikita Popov return getFull();
10058cd041efSChandler Carruth return X;
10068cd041efSChandler Carruth }
10078cd041efSChandler Carruth
addWithNoWrap(const ConstantRange & Other,unsigned NoWrapKind,PreferredRangeType RangeType) const1008bfec0456SChen Zheng ConstantRange ConstantRange::addWithNoWrap(const ConstantRange &Other,
1009bfec0456SChen Zheng unsigned NoWrapKind,
1010bfec0456SChen Zheng PreferredRangeType RangeType) const {
1011bfec0456SChen Zheng // Calculate the range for "X + Y" which is guaranteed not to wrap(overflow).
1012bfec0456SChen Zheng // (X is from this, and Y is from Other)
1013bfec0456SChen Zheng if (isEmptySet() || Other.isEmptySet())
1014bfec0456SChen Zheng return getEmpty();
1015bfec0456SChen Zheng if (isFullSet() && Other.isFullSet())
1016bfec0456SChen Zheng return getFull();
1017bfec0456SChen Zheng
1018bfec0456SChen Zheng using OBO = OverflowingBinaryOperator;
1019bfec0456SChen Zheng ConstantRange Result = add(Other);
1020bfec0456SChen Zheng
1021365d729eSRoman Lebedev // If an overflow happens for every value pair in these two constant ranges,
1022365d729eSRoman Lebedev // we must return Empty set. In this case, we get that for free, because we
1023365d729eSRoman Lebedev // get lucky that intersection of add() with uadd_sat()/sadd_sat() results
1024365d729eSRoman Lebedev // in an empty set.
1025bfec0456SChen Zheng
1026bfec0456SChen Zheng if (NoWrapKind & OBO::NoSignedWrap)
1027365d729eSRoman Lebedev Result = Result.intersectWith(sadd_sat(Other), RangeType);
1028365d729eSRoman Lebedev
1029bfec0456SChen Zheng if (NoWrapKind & OBO::NoUnsignedWrap)
1030365d729eSRoman Lebedev Result = Result.intersectWith(uadd_sat(Other), RangeType);
1031365d729eSRoman Lebedev
1032bfec0456SChen Zheng return Result;
1033bfec0456SChen Zheng }
1034bfec0456SChen Zheng
10358cd041efSChandler Carruth ConstantRange
sub(const ConstantRange & Other) const10368cd041efSChandler Carruth ConstantRange::sub(const ConstantRange &Other) const {
10378cd041efSChandler Carruth if (isEmptySet() || Other.isEmptySet())
1038977934f0SNikita Popov return getEmpty();
10398cd041efSChandler Carruth if (isFullSet() || Other.isFullSet())
1040977934f0SNikita Popov return getFull();
10418cd041efSChandler Carruth
10428cd041efSChandler Carruth APInt NewLower = getLower() - Other.getUpper() + 1;
10438cd041efSChandler Carruth APInt NewUpper = getUpper() - Other.getLower();
10448cd041efSChandler Carruth if (NewLower == NewUpper)
1045977934f0SNikita Popov return getFull();
10468cd041efSChandler Carruth
1047b792025bSCraig Topper ConstantRange X = ConstantRange(std::move(NewLower), std::move(NewUpper));
1048d29549e9SCraig Topper if (X.isSizeStrictlySmallerThan(*this) ||
1049d29549e9SCraig Topper X.isSizeStrictlySmallerThan(Other))
10508cd041efSChandler Carruth // We've wrapped, therefore, full set.
1051977934f0SNikita Popov return getFull();
10528cd041efSChandler Carruth return X;
10538cd041efSChandler Carruth }
10548cd041efSChandler Carruth
subWithNoWrap(const ConstantRange & Other,unsigned NoWrapKind,PreferredRangeType RangeType) const10557fbe5d4bSRoman Lebedev ConstantRange ConstantRange::subWithNoWrap(const ConstantRange &Other,
10567fbe5d4bSRoman Lebedev unsigned NoWrapKind,
10577fbe5d4bSRoman Lebedev PreferredRangeType RangeType) const {
10587fbe5d4bSRoman Lebedev // Calculate the range for "X - Y" which is guaranteed not to wrap(overflow).
10597fbe5d4bSRoman Lebedev // (X is from this, and Y is from Other)
10607fbe5d4bSRoman Lebedev if (isEmptySet() || Other.isEmptySet())
10617fbe5d4bSRoman Lebedev return getEmpty();
10627fbe5d4bSRoman Lebedev if (isFullSet() && Other.isFullSet())
10637fbe5d4bSRoman Lebedev return getFull();
10647fbe5d4bSRoman Lebedev
10657fbe5d4bSRoman Lebedev using OBO = OverflowingBinaryOperator;
10667fbe5d4bSRoman Lebedev ConstantRange Result = sub(Other);
10677fbe5d4bSRoman Lebedev
10687fbe5d4bSRoman Lebedev // If an overflow happens for every value pair in these two constant ranges,
10697fbe5d4bSRoman Lebedev // we must return Empty set. In signed case, we get that for free, because we
10707dddfa2aSRoman Lebedev // get lucky that intersection of sub() with ssub_sat() results in an
10717fbe5d4bSRoman Lebedev // empty set. But for unsigned we must perform the overflow check manually.
10727fbe5d4bSRoman Lebedev
10737fbe5d4bSRoman Lebedev if (NoWrapKind & OBO::NoSignedWrap)
10747fbe5d4bSRoman Lebedev Result = Result.intersectWith(ssub_sat(Other), RangeType);
10757fbe5d4bSRoman Lebedev
10767fbe5d4bSRoman Lebedev if (NoWrapKind & OBO::NoUnsignedWrap) {
10777fbe5d4bSRoman Lebedev if (getUnsignedMax().ult(Other.getUnsignedMin()))
10787fbe5d4bSRoman Lebedev return getEmpty(); // Always overflows.
10797fbe5d4bSRoman Lebedev Result = Result.intersectWith(usub_sat(Other), RangeType);
10807fbe5d4bSRoman Lebedev }
10817fbe5d4bSRoman Lebedev
10827fbe5d4bSRoman Lebedev return Result;
10837fbe5d4bSRoman Lebedev }
10847fbe5d4bSRoman Lebedev
10858cd041efSChandler Carruth ConstantRange
multiply(const ConstantRange & Other) const10868cd041efSChandler Carruth ConstantRange::multiply(const ConstantRange &Other) const {
10878cd041efSChandler Carruth // TODO: If either operand is a single element and the multiply is known to
10888cd041efSChandler Carruth // be non-wrapping, round the result min and max value to the appropriate
10898cd041efSChandler Carruth // multiple of that element. If wrapping is possible, at least adjust the
10908cd041efSChandler Carruth // range according to the greatest power-of-two factor of the single element.
10918cd041efSChandler Carruth
10928cd041efSChandler Carruth if (isEmptySet() || Other.isEmptySet())
1093977934f0SNikita Popov return getEmpty();
10948cd041efSChandler Carruth
1095dcc78ec3SJames Molloy // Multiplication is signedness-independent. However different ranges can be
1096dcc78ec3SJames Molloy // obtained depending on how the input ranges are treated. These different
1097dcc78ec3SJames Molloy // ranges are all conservatively correct, but one might be better than the
1098dcc78ec3SJames Molloy // other. We calculate two ranges; one treating the inputs as unsigned
1099dcc78ec3SJames Molloy // and the other signed, then return the smallest of these ranges.
1100dcc78ec3SJames Molloy
1101dcc78ec3SJames Molloy // Unsigned range first.
11028cd041efSChandler Carruth APInt this_min = getUnsignedMin().zext(getBitWidth() * 2);
11038cd041efSChandler Carruth APInt this_max = getUnsignedMax().zext(getBitWidth() * 2);
11048cd041efSChandler Carruth APInt Other_min = Other.getUnsignedMin().zext(getBitWidth() * 2);
11058cd041efSChandler Carruth APInt Other_max = Other.getUnsignedMax().zext(getBitWidth() * 2);
11068cd041efSChandler Carruth
11078cd041efSChandler Carruth ConstantRange Result_zext = ConstantRange(this_min * Other_min,
11088cd041efSChandler Carruth this_max * Other_max + 1);
1109dcc78ec3SJames Molloy ConstantRange UR = Result_zext.truncate(getBitWidth());
1110dcc78ec3SJames Molloy
111134a7a945SPete Cooper // If the unsigned range doesn't wrap, and isn't negative then it's a range
111234a7a945SPete Cooper // from one positive number to another which is as good as we can generate.
111334a7a945SPete Cooper // In this case, skip the extra work of generating signed ranges which aren't
111434a7a945SPete Cooper // going to be better than this range.
11156d855ea0SNikita Popov if (!UR.isUpperWrapped() &&
1116c51d0536SCraig Topper (UR.getUpper().isNonNegative() || UR.getUpper().isMinSignedValue()))
111734a7a945SPete Cooper return UR;
111834a7a945SPete Cooper
1119dcc78ec3SJames Molloy // Now the signed range. Because we could be dealing with negative numbers
1120dcc78ec3SJames Molloy // here, the lower bound is the smallest of the cartesian product of the
1121dcc78ec3SJames Molloy // lower and upper ranges; for example:
1122dcc78ec3SJames Molloy // [-1,4) * [-2,3) = min(-1*-2, -1*2, 3*-2, 3*2) = -6.
1123dcc78ec3SJames Molloy // Similarly for the upper bound, swapping min for max.
1124dcc78ec3SJames Molloy
1125dcc78ec3SJames Molloy this_min = getSignedMin().sext(getBitWidth() * 2);
1126dcc78ec3SJames Molloy this_max = getSignedMax().sext(getBitWidth() * 2);
1127dcc78ec3SJames Molloy Other_min = Other.getSignedMin().sext(getBitWidth() * 2);
1128dcc78ec3SJames Molloy Other_max = Other.getSignedMax().sext(getBitWidth() * 2);
1129dcc78ec3SJames Molloy
1130dcc78ec3SJames Molloy auto L = {this_min * Other_min, this_min * Other_max,
1131dcc78ec3SJames Molloy this_max * Other_min, this_max * Other_max};
1132dcc78ec3SJames Molloy auto Compare = [](const APInt &A, const APInt &B) { return A.slt(B); };
1133dcc78ec3SJames Molloy ConstantRange Result_sext(std::min(L, Compare), std::max(L, Compare) + 1);
1134dcc78ec3SJames Molloy ConstantRange SR = Result_sext.truncate(getBitWidth());
1135dcc78ec3SJames Molloy
1136d29549e9SCraig Topper return UR.isSizeStrictlySmallerThan(SR) ? UR : SR;
11378cd041efSChandler Carruth }
11388cd041efSChandler Carruth
smul_fast(const ConstantRange & Other) const1139274b2439SNikita Popov ConstantRange ConstantRange::smul_fast(const ConstantRange &Other) const {
1140274b2439SNikita Popov if (isEmptySet() || Other.isEmptySet())
1141274b2439SNikita Popov return getEmpty();
1142274b2439SNikita Popov
1143274b2439SNikita Popov APInt Min = getSignedMin();
1144274b2439SNikita Popov APInt Max = getSignedMax();
1145274b2439SNikita Popov APInt OtherMin = Other.getSignedMin();
1146274b2439SNikita Popov APInt OtherMax = Other.getSignedMax();
1147274b2439SNikita Popov
1148274b2439SNikita Popov bool O1, O2, O3, O4;
1149274b2439SNikita Popov auto Muls = {Min.smul_ov(OtherMin, O1), Min.smul_ov(OtherMax, O2),
1150274b2439SNikita Popov Max.smul_ov(OtherMin, O3), Max.smul_ov(OtherMax, O4)};
1151274b2439SNikita Popov if (O1 || O2 || O3 || O4)
1152274b2439SNikita Popov return getFull();
1153274b2439SNikita Popov
1154274b2439SNikita Popov auto Compare = [](const APInt &A, const APInt &B) { return A.slt(B); };
1155274b2439SNikita Popov return getNonEmpty(std::min(Muls, Compare), std::max(Muls, Compare) + 1);
1156274b2439SNikita Popov }
1157274b2439SNikita Popov
11588cd041efSChandler Carruth ConstantRange
smax(const ConstantRange & Other) const11598cd041efSChandler Carruth ConstantRange::smax(const ConstantRange &Other) const {
11608cd041efSChandler Carruth // X smax Y is: range(smax(X_smin, Y_smin),
11618cd041efSChandler Carruth // smax(X_smax, Y_smax))
11628cd041efSChandler Carruth if (isEmptySet() || Other.isEmptySet())
1163977934f0SNikita Popov return getEmpty();
11648cd041efSChandler Carruth APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin());
11658cd041efSChandler Carruth APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1;
1166a852234fSNikita Popov ConstantRange Res = getNonEmpty(std::move(NewL), std::move(NewU));
1167a852234fSNikita Popov if (isSignWrappedSet() || Other.isSignWrappedSet())
1168a852234fSNikita Popov return Res.intersectWith(unionWith(Other, Signed), Signed);
1169a852234fSNikita Popov return Res;
11708cd041efSChandler Carruth }
11718cd041efSChandler Carruth
11728cd041efSChandler Carruth ConstantRange
umax(const ConstantRange & Other) const11738cd041efSChandler Carruth ConstantRange::umax(const ConstantRange &Other) const {
11748cd041efSChandler Carruth // X umax Y is: range(umax(X_umin, Y_umin),
11758cd041efSChandler Carruth // umax(X_umax, Y_umax))
11768cd041efSChandler Carruth if (isEmptySet() || Other.isEmptySet())
1177977934f0SNikita Popov return getEmpty();
11788cd041efSChandler Carruth APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
11798cd041efSChandler Carruth APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1;
1180a852234fSNikita Popov ConstantRange Res = getNonEmpty(std::move(NewL), std::move(NewU));
1181a852234fSNikita Popov if (isWrappedSet() || Other.isWrappedSet())
1182a852234fSNikita Popov return Res.intersectWith(unionWith(Other, Unsigned), Unsigned);
1183a852234fSNikita Popov return Res;
11848cd041efSChandler Carruth }
11858cd041efSChandler Carruth
11868cd041efSChandler Carruth ConstantRange
smin(const ConstantRange & Other) const1187ba31312fSPhilip Reames ConstantRange::smin(const ConstantRange &Other) const {
1188ba31312fSPhilip Reames // X smin Y is: range(smin(X_smin, Y_smin),
1189ba31312fSPhilip Reames // smin(X_smax, Y_smax))
1190ba31312fSPhilip Reames if (isEmptySet() || Other.isEmptySet())
1191977934f0SNikita Popov return getEmpty();
1192ba31312fSPhilip Reames APInt NewL = APIntOps::smin(getSignedMin(), Other.getSignedMin());
1193ba31312fSPhilip Reames APInt NewU = APIntOps::smin(getSignedMax(), Other.getSignedMax()) + 1;
1194a852234fSNikita Popov ConstantRange Res = getNonEmpty(std::move(NewL), std::move(NewU));
1195a852234fSNikita Popov if (isSignWrappedSet() || Other.isSignWrappedSet())
1196a852234fSNikita Popov return Res.intersectWith(unionWith(Other, Signed), Signed);
1197a852234fSNikita Popov return Res;
1198ba31312fSPhilip Reames }
1199ba31312fSPhilip Reames
1200ba31312fSPhilip Reames ConstantRange
umin(const ConstantRange & Other) const1201ba31312fSPhilip Reames ConstantRange::umin(const ConstantRange &Other) const {
1202ba31312fSPhilip Reames // X umin Y is: range(umin(X_umin, Y_umin),
1203ba31312fSPhilip Reames // umin(X_umax, Y_umax))
1204ba31312fSPhilip Reames if (isEmptySet() || Other.isEmptySet())
1205977934f0SNikita Popov return getEmpty();
1206ba31312fSPhilip Reames APInt NewL = APIntOps::umin(getUnsignedMin(), Other.getUnsignedMin());
1207ba31312fSPhilip Reames APInt NewU = APIntOps::umin(getUnsignedMax(), Other.getUnsignedMax()) + 1;
1208a852234fSNikita Popov ConstantRange Res = getNonEmpty(std::move(NewL), std::move(NewU));
1209a852234fSNikita Popov if (isWrappedSet() || Other.isWrappedSet())
1210a852234fSNikita Popov return Res.intersectWith(unionWith(Other, Unsigned), Unsigned);
1211a852234fSNikita Popov return Res;
1212ba31312fSPhilip Reames }
1213ba31312fSPhilip Reames
1214ba31312fSPhilip Reames ConstantRange
udiv(const ConstantRange & RHS) const12158cd041efSChandler Carruth ConstantRange::udiv(const ConstantRange &RHS) const {
1216735f4671SChris Lattner if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isZero())
1217977934f0SNikita Popov return getEmpty();
12188cd041efSChandler Carruth
12198cd041efSChandler Carruth APInt Lower = getUnsignedMin().udiv(RHS.getUnsignedMax());
12208cd041efSChandler Carruth
12218cd041efSChandler Carruth APInt RHS_umin = RHS.getUnsignedMin();
1222735f4671SChris Lattner if (RHS_umin.isZero()) {
12238cd041efSChandler Carruth // We want the lowest value in RHS excluding zero. Usually that would be 1
12248cd041efSChandler Carruth // except for a range in the form of [X, 1) in which case it would be X.
12258cd041efSChandler Carruth if (RHS.getUpper() == 1)
12268cd041efSChandler Carruth RHS_umin = RHS.getLower();
12278cd041efSChandler Carruth else
122886616530SCraig Topper RHS_umin = 1;
12298cd041efSChandler Carruth }
12308cd041efSChandler Carruth
12318cd041efSChandler Carruth APInt Upper = getUnsignedMax().udiv(RHS_umin) + 1;
1232dbc3fbafSNikita Popov return getNonEmpty(std::move(Lower), std::move(Upper));
12338cd041efSChandler Carruth }
12348cd041efSChandler Carruth
sdiv(const ConstantRange & RHS) const1235c061b99cSNikita Popov ConstantRange ConstantRange::sdiv(const ConstantRange &RHS) const {
1236c061b99cSNikita Popov // We split up the LHS and RHS into positive and negative components
1237c061b99cSNikita Popov // and then also compute the positive and negative components of the result
1238c061b99cSNikita Popov // separately by combining division results with the appropriate signs.
1239735f4671SChris Lattner APInt Zero = APInt::getZero(getBitWidth());
1240c061b99cSNikita Popov APInt SignedMin = APInt::getSignedMinValue(getBitWidth());
1241*ba1e04b9SNikita Popov // There are no positive 1-bit values. The 1 would get interpreted as -1.
1242*ba1e04b9SNikita Popov ConstantRange PosFilter =
1243*ba1e04b9SNikita Popov getBitWidth() == 1 ? getEmpty()
1244*ba1e04b9SNikita Popov : ConstantRange(APInt(getBitWidth(), 1), SignedMin);
1245c061b99cSNikita Popov ConstantRange NegFilter(SignedMin, Zero);
1246c061b99cSNikita Popov ConstantRange PosL = intersectWith(PosFilter);
1247c061b99cSNikita Popov ConstantRange NegL = intersectWith(NegFilter);
1248c061b99cSNikita Popov ConstantRange PosR = RHS.intersectWith(PosFilter);
1249c061b99cSNikita Popov ConstantRange NegR = RHS.intersectWith(NegFilter);
1250c061b99cSNikita Popov
1251c061b99cSNikita Popov ConstantRange PosRes = getEmpty();
1252c061b99cSNikita Popov if (!PosL.isEmptySet() && !PosR.isEmptySet())
1253c061b99cSNikita Popov // pos / pos = pos.
1254c061b99cSNikita Popov PosRes = ConstantRange(PosL.Lower.sdiv(PosR.Upper - 1),
1255c061b99cSNikita Popov (PosL.Upper - 1).sdiv(PosR.Lower) + 1);
1256c061b99cSNikita Popov
1257c061b99cSNikita Popov if (!NegL.isEmptySet() && !NegR.isEmptySet()) {
1258c061b99cSNikita Popov // neg / neg = pos.
1259c061b99cSNikita Popov //
1260c061b99cSNikita Popov // We need to deal with one tricky case here: SignedMin / -1 is UB on the
1261c061b99cSNikita Popov // IR level, so we'll want to exclude this case when calculating bounds.
1262c061b99cSNikita Popov // (For APInts the operation is well-defined and yields SignedMin.) We
1263c061b99cSNikita Popov // handle this by dropping either SignedMin from the LHS or -1 from the RHS.
1264c061b99cSNikita Popov APInt Lo = (NegL.Upper - 1).sdiv(NegR.Lower);
1265735f4671SChris Lattner if (NegL.Lower.isMinSignedValue() && NegR.Upper.isZero()) {
1266c061b99cSNikita Popov // Remove -1 from the LHS. Skip if it's the only element, as this would
1267c061b99cSNikita Popov // leave us with an empty set.
1268a9bceb2bSJay Foad if (!NegR.Lower.isAllOnes()) {
1269c061b99cSNikita Popov APInt AdjNegRUpper;
1270a9bceb2bSJay Foad if (RHS.Lower.isAllOnes())
1271c061b99cSNikita Popov // Negative part of [-1, X] without -1 is [SignedMin, X].
1272c061b99cSNikita Popov AdjNegRUpper = RHS.Upper;
1273c061b99cSNikita Popov else
1274c061b99cSNikita Popov // [X, -1] without -1 is [X, -2].
1275c061b99cSNikita Popov AdjNegRUpper = NegR.Upper - 1;
1276c061b99cSNikita Popov
1277c061b99cSNikita Popov PosRes = PosRes.unionWith(
1278c061b99cSNikita Popov ConstantRange(Lo, NegL.Lower.sdiv(AdjNegRUpper - 1) + 1));
1279c061b99cSNikita Popov }
1280c061b99cSNikita Popov
1281c061b99cSNikita Popov // Remove SignedMin from the RHS. Skip if it's the only element, as this
1282c061b99cSNikita Popov // would leave us with an empty set.
1283c061b99cSNikita Popov if (NegL.Upper != SignedMin + 1) {
1284c061b99cSNikita Popov APInt AdjNegLLower;
1285c061b99cSNikita Popov if (Upper == SignedMin + 1)
1286c061b99cSNikita Popov // Negative part of [X, SignedMin] without SignedMin is [X, -1].
1287c061b99cSNikita Popov AdjNegLLower = Lower;
1288c061b99cSNikita Popov else
1289c061b99cSNikita Popov // [SignedMin, X] without SignedMin is [SignedMin + 1, X].
1290c061b99cSNikita Popov AdjNegLLower = NegL.Lower + 1;
1291c061b99cSNikita Popov
1292c061b99cSNikita Popov PosRes = PosRes.unionWith(
1293c061b99cSNikita Popov ConstantRange(std::move(Lo),
1294c061b99cSNikita Popov AdjNegLLower.sdiv(NegR.Upper - 1) + 1));
1295c061b99cSNikita Popov }
1296c061b99cSNikita Popov } else {
1297c061b99cSNikita Popov PosRes = PosRes.unionWith(
1298c061b99cSNikita Popov ConstantRange(std::move(Lo), NegL.Lower.sdiv(NegR.Upper - 1) + 1));
1299c061b99cSNikita Popov }
1300c061b99cSNikita Popov }
1301c061b99cSNikita Popov
1302c061b99cSNikita Popov ConstantRange NegRes = getEmpty();
1303c061b99cSNikita Popov if (!PosL.isEmptySet() && !NegR.isEmptySet())
1304c061b99cSNikita Popov // pos / neg = neg.
1305c061b99cSNikita Popov NegRes = ConstantRange((PosL.Upper - 1).sdiv(NegR.Upper - 1),
1306c061b99cSNikita Popov PosL.Lower.sdiv(NegR.Lower) + 1);
1307c061b99cSNikita Popov
1308c061b99cSNikita Popov if (!NegL.isEmptySet() && !PosR.isEmptySet())
1309c061b99cSNikita Popov // neg / pos = neg.
1310c061b99cSNikita Popov NegRes = NegRes.unionWith(
1311c061b99cSNikita Popov ConstantRange(NegL.Lower.sdiv(PosR.Lower),
1312c061b99cSNikita Popov (NegL.Upper - 1).sdiv(PosR.Upper - 1) + 1));
1313c061b99cSNikita Popov
1314c061b99cSNikita Popov // Prefer a non-wrapping signed range here.
1315c061b99cSNikita Popov ConstantRange Res = NegRes.unionWith(PosRes, PreferredRangeType::Signed);
1316c061b99cSNikita Popov
1317c061b99cSNikita Popov // Preserve the zero that we dropped when splitting the LHS by sign.
1318c061b99cSNikita Popov if (contains(Zero) && (!PosR.isEmptySet() || !NegR.isEmptySet()))
1319c061b99cSNikita Popov Res = Res.unionWith(ConstantRange(Zero));
1320c061b99cSNikita Popov return Res;
1321c061b99cSNikita Popov }
1322c061b99cSNikita Popov
urem(const ConstantRange & RHS) const1323f945429fSNikita Popov ConstantRange ConstantRange::urem(const ConstantRange &RHS) const {
1324735f4671SChris Lattner if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isZero())
1325f945429fSNikita Popov return getEmpty();
1326f945429fSNikita Popov
1327611a02ccSFlorian Hahn if (const APInt *RHSInt = RHS.getSingleElement()) {
1328611a02ccSFlorian Hahn // UREM by null is UB.
1329735f4671SChris Lattner if (RHSInt->isZero())
1330611a02ccSFlorian Hahn return getEmpty();
1331611a02ccSFlorian Hahn // Use APInt's implementation of UREM for single element ranges.
1332611a02ccSFlorian Hahn if (const APInt *LHSInt = getSingleElement())
1333611a02ccSFlorian Hahn return {LHSInt->urem(*RHSInt)};
1334611a02ccSFlorian Hahn }
1335611a02ccSFlorian Hahn
1336f945429fSNikita Popov // L % R for L < R is L.
1337f945429fSNikita Popov if (getUnsignedMax().ult(RHS.getUnsignedMin()))
1338f945429fSNikita Popov return *this;
1339f945429fSNikita Popov
1340f945429fSNikita Popov // L % R is <= L and < R.
1341f945429fSNikita Popov APInt Upper = APIntOps::umin(getUnsignedMax(), RHS.getUnsignedMax() - 1) + 1;
1342735f4671SChris Lattner return getNonEmpty(APInt::getZero(getBitWidth()), std::move(Upper));
1343f945429fSNikita Popov }
1344f945429fSNikita Popov
srem(const ConstantRange & RHS) const1345d5a403fbSNikita Popov ConstantRange ConstantRange::srem(const ConstantRange &RHS) const {
1346d5a403fbSNikita Popov if (isEmptySet() || RHS.isEmptySet())
1347d5a403fbSNikita Popov return getEmpty();
1348d5a403fbSNikita Popov
1349611a02ccSFlorian Hahn if (const APInt *RHSInt = RHS.getSingleElement()) {
1350611a02ccSFlorian Hahn // SREM by null is UB.
1351735f4671SChris Lattner if (RHSInt->isZero())
1352611a02ccSFlorian Hahn return getEmpty();
1353611a02ccSFlorian Hahn // Use APInt's implementation of SREM for single element ranges.
1354611a02ccSFlorian Hahn if (const APInt *LHSInt = getSingleElement())
1355611a02ccSFlorian Hahn return {LHSInt->srem(*RHSInt)};
1356611a02ccSFlorian Hahn }
1357611a02ccSFlorian Hahn
1358d5a403fbSNikita Popov ConstantRange AbsRHS = RHS.abs();
1359d5a403fbSNikita Popov APInt MinAbsRHS = AbsRHS.getUnsignedMin();
1360d5a403fbSNikita Popov APInt MaxAbsRHS = AbsRHS.getUnsignedMax();
1361d5a403fbSNikita Popov
1362d5a403fbSNikita Popov // Modulus by zero is UB.
1363735f4671SChris Lattner if (MaxAbsRHS.isZero())
1364d5a403fbSNikita Popov return getEmpty();
1365d5a403fbSNikita Popov
1366735f4671SChris Lattner if (MinAbsRHS.isZero())
1367d5a403fbSNikita Popov ++MinAbsRHS;
1368d5a403fbSNikita Popov
1369d5a403fbSNikita Popov APInt MinLHS = getSignedMin(), MaxLHS = getSignedMax();
1370d5a403fbSNikita Popov
1371d5a403fbSNikita Popov if (MinLHS.isNonNegative()) {
1372d5a403fbSNikita Popov // L % R for L < R is L.
1373d5a403fbSNikita Popov if (MaxLHS.ult(MinAbsRHS))
1374d5a403fbSNikita Popov return *this;
1375d5a403fbSNikita Popov
1376d5a403fbSNikita Popov // L % R is <= L and < R.
1377d5a403fbSNikita Popov APInt Upper = APIntOps::umin(MaxLHS, MaxAbsRHS - 1) + 1;
1378735f4671SChris Lattner return ConstantRange(APInt::getZero(getBitWidth()), std::move(Upper));
1379d5a403fbSNikita Popov }
1380d5a403fbSNikita Popov
1381d5a403fbSNikita Popov // Same basic logic as above, but the result is negative.
1382d5a403fbSNikita Popov if (MaxLHS.isNegative()) {
1383d5a403fbSNikita Popov if (MinLHS.ugt(-MinAbsRHS))
1384d5a403fbSNikita Popov return *this;
1385d5a403fbSNikita Popov
1386d5a403fbSNikita Popov APInt Lower = APIntOps::umax(MinLHS, -MaxAbsRHS + 1);
1387d5a403fbSNikita Popov return ConstantRange(std::move(Lower), APInt(getBitWidth(), 1));
1388d5a403fbSNikita Popov }
1389d5a403fbSNikita Popov
1390d5a403fbSNikita Popov // LHS range crosses zero.
1391d5a403fbSNikita Popov APInt Lower = APIntOps::umax(MinLHS, -MaxAbsRHS + 1);
1392d5a403fbSNikita Popov APInt Upper = APIntOps::umin(MaxLHS, MaxAbsRHS - 1) + 1;
1393d5a403fbSNikita Popov return ConstantRange(std::move(Lower), std::move(Upper));
1394d5a403fbSNikita Popov }
1395d5a403fbSNikita Popov
binaryNot() const1396b38d897eSRoman Lebedev ConstantRange ConstantRange::binaryNot() const {
1397735f4671SChris Lattner return ConstantRange(APInt::getAllOnes(getBitWidth())).sub(*this);
1398b38d897eSRoman Lebedev }
1399b38d897eSRoman Lebedev
binaryAnd(const ConstantRange & Other) const14000f4d9f9bSAlexander Shaposhnikov ConstantRange ConstantRange::binaryAnd(const ConstantRange &Other) const {
14018cd041efSChandler Carruth if (isEmptySet() || Other.isEmptySet())
1402977934f0SNikita Popov return getEmpty();
14038cd041efSChandler Carruth
14040f4d9f9bSAlexander Shaposhnikov ConstantRange KnownBitsRange =
14050f4d9f9bSAlexander Shaposhnikov fromKnownBits(toKnownBits() & Other.toKnownBits(), false);
14060f4d9f9bSAlexander Shaposhnikov ConstantRange UMinUMaxRange =
14070f4d9f9bSAlexander Shaposhnikov getNonEmpty(APInt::getZero(getBitWidth()),
14080f4d9f9bSAlexander Shaposhnikov APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax()) + 1);
14090f4d9f9bSAlexander Shaposhnikov return KnownBitsRange.intersectWith(UMinUMaxRange);
14108cd041efSChandler Carruth }
14118cd041efSChandler Carruth
binaryOr(const ConstantRange & Other) const14120f4d9f9bSAlexander Shaposhnikov ConstantRange ConstantRange::binaryOr(const ConstantRange &Other) const {
14138cd041efSChandler Carruth if (isEmptySet() || Other.isEmptySet())
1414977934f0SNikita Popov return getEmpty();
14158cd041efSChandler Carruth
14169398caf3SAlexander Shaposhnikov ConstantRange KnownBitsRange =
14179398caf3SAlexander Shaposhnikov fromKnownBits(toKnownBits() | Other.toKnownBits(), false);
14189398caf3SAlexander Shaposhnikov // Upper wrapped range.
14199398caf3SAlexander Shaposhnikov ConstantRange UMaxUMinRange =
14209398caf3SAlexander Shaposhnikov getNonEmpty(APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()),
14219398caf3SAlexander Shaposhnikov APInt::getZero(getBitWidth()));
14229398caf3SAlexander Shaposhnikov return KnownBitsRange.intersectWith(UMaxUMinRange);
14238cd041efSChandler Carruth }
14248cd041efSChandler Carruth
binaryXor(const ConstantRange & Other) const14257caba339SFlorian Hahn ConstantRange ConstantRange::binaryXor(const ConstantRange &Other) const {
14267caba339SFlorian Hahn if (isEmptySet() || Other.isEmptySet())
14277caba339SFlorian Hahn return getEmpty();
14287caba339SFlorian Hahn
14297caba339SFlorian Hahn // Use APInt's implementation of XOR for single element ranges.
14307caba339SFlorian Hahn if (isSingleElement() && Other.isSingleElement())
14317caba339SFlorian Hahn return {*getSingleElement() ^ *Other.getSingleElement()};
14327caba339SFlorian Hahn
1433b38d897eSRoman Lebedev // Special-case binary complement, since we can give a precise answer.
1434a9bceb2bSJay Foad if (Other.isSingleElement() && Other.getSingleElement()->isAllOnes())
1435b38d897eSRoman Lebedev return binaryNot();
1436a9bceb2bSJay Foad if (isSingleElement() && getSingleElement()->isAllOnes())
1437b38d897eSRoman Lebedev return Other.binaryNot();
1438b38d897eSRoman Lebedev
14392db4dc7eSNikita Popov return fromKnownBits(toKnownBits() ^ Other.toKnownBits(), /*IsSigned*/false);
14407caba339SFlorian Hahn }
14417caba339SFlorian Hahn
14428cd041efSChandler Carruth ConstantRange
shl(const ConstantRange & Other) const14438cd041efSChandler Carruth ConstantRange::shl(const ConstantRange &Other) const {
14448cd041efSChandler Carruth if (isEmptySet() || Other.isEmptySet())
1445977934f0SNikita Popov return getEmpty();
14468cd041efSChandler Carruth
1447587493b4SNikita Popov APInt Min = getUnsignedMin();
1448587493b4SNikita Popov APInt Max = getUnsignedMax();
1449587493b4SNikita Popov if (const APInt *RHS = Other.getSingleElement()) {
1450587493b4SNikita Popov unsigned BW = getBitWidth();
1451587493b4SNikita Popov if (RHS->uge(BW))
1452587493b4SNikita Popov return getEmpty();
14538cd041efSChandler Carruth
1454587493b4SNikita Popov unsigned EqualLeadingBits = (Min ^ Max).countLeadingZeros();
1455587493b4SNikita Popov if (RHS->ule(EqualLeadingBits))
1456587493b4SNikita Popov return getNonEmpty(Min << *RHS, (Max << *RHS) + 1);
1457587493b4SNikita Popov
1458587493b4SNikita Popov return getNonEmpty(APInt::getZero(BW),
1459587493b4SNikita Popov APInt::getBitsSetFrom(BW, RHS->getZExtValue()) + 1);
1460587493b4SNikita Popov }
1461587493b4SNikita Popov
1462587493b4SNikita Popov APInt OtherMax = Other.getUnsignedMax();
1463587493b4SNikita Popov
1464587493b4SNikita Popov // There's overflow!
1465587493b4SNikita Popov if (OtherMax.ugt(Max.countLeadingZeros()))
1466977934f0SNikita Popov return getFull();
14678cd041efSChandler Carruth
14688cd041efSChandler Carruth // FIXME: implement the other tricky cases
1469ef02803bSCraig Topper
1470587493b4SNikita Popov Min <<= Other.getUnsignedMin();
1471587493b4SNikita Popov Max <<= OtherMax;
1472ef02803bSCraig Topper
1473587493b4SNikita Popov return ConstantRange::getNonEmpty(std::move(Min), std::move(Max) + 1);
14748cd041efSChandler Carruth }
14758cd041efSChandler Carruth
14768cd041efSChandler Carruth ConstantRange
lshr(const ConstantRange & Other) const14778cd041efSChandler Carruth ConstantRange::lshr(const ConstantRange &Other) const {
14788cd041efSChandler Carruth if (isEmptySet() || Other.isEmptySet())
1479977934f0SNikita Popov return getEmpty();
14808cd041efSChandler Carruth
148179b7666fSCraig Topper APInt max = getUnsignedMax().lshr(Other.getUnsignedMin()) + 1;
14828cd041efSChandler Carruth APInt min = getUnsignedMin().lshr(Other.getUnsignedMax());
1483dbc3fbafSNikita Popov return getNonEmpty(std::move(min), std::move(max));
14848cd041efSChandler Carruth }
14858cd041efSChandler Carruth
1486d792171eSMax Kazantsev ConstantRange
ashr(const ConstantRange & Other) const1487d792171eSMax Kazantsev ConstantRange::ashr(const ConstantRange &Other) const {
1488d792171eSMax Kazantsev if (isEmptySet() || Other.isEmptySet())
1489977934f0SNikita Popov return getEmpty();
1490d792171eSMax Kazantsev
1491d792171eSMax Kazantsev // May straddle zero, so handle both positive and negative cases.
1492d792171eSMax Kazantsev // 'PosMax' is the upper bound of the result of the ashr
1493d792171eSMax Kazantsev // operation, when Upper of the LHS of ashr is a non-negative.
1494d792171eSMax Kazantsev // number. Since ashr of a non-negative number will result in a
1495d792171eSMax Kazantsev // smaller number, the Upper value of LHS is shifted right with
1496d792171eSMax Kazantsev // the minimum value of 'Other' instead of the maximum value.
1497d792171eSMax Kazantsev APInt PosMax = getSignedMax().ashr(Other.getUnsignedMin()) + 1;
1498d792171eSMax Kazantsev
1499d792171eSMax Kazantsev // 'PosMin' is the lower bound of the result of the ashr
1500d792171eSMax Kazantsev // operation, when Lower of the LHS is a non-negative number.
1501d792171eSMax Kazantsev // Since ashr of a non-negative number will result in a smaller
1502d792171eSMax Kazantsev // number, the Lower value of LHS is shifted right with the
1503d792171eSMax Kazantsev // maximum value of 'Other'.
1504d792171eSMax Kazantsev APInt PosMin = getSignedMin().ashr(Other.getUnsignedMax());
1505d792171eSMax Kazantsev
1506d792171eSMax Kazantsev // 'NegMax' is the upper bound of the result of the ashr
1507d792171eSMax Kazantsev // operation, when Upper of the LHS of ashr is a negative number.
1508d792171eSMax Kazantsev // Since 'ashr' of a negative number will result in a bigger
1509d792171eSMax Kazantsev // number, the Upper value of LHS is shifted right with the
1510d792171eSMax Kazantsev // maximum value of 'Other'.
1511d792171eSMax Kazantsev APInt NegMax = getSignedMax().ashr(Other.getUnsignedMax()) + 1;
1512d792171eSMax Kazantsev
1513d792171eSMax Kazantsev // 'NegMin' is the lower bound of the result of the ashr
1514d792171eSMax Kazantsev // operation, when Lower of the LHS of ashr is a negative number.
1515d792171eSMax Kazantsev // Since 'ashr' of a negative number will result in a bigger
1516d792171eSMax Kazantsev // number, the Lower value of LHS is shifted right with the
1517d792171eSMax Kazantsev // minimum value of 'Other'.
1518d792171eSMax Kazantsev APInt NegMin = getSignedMin().ashr(Other.getUnsignedMin());
1519d792171eSMax Kazantsev
1520d792171eSMax Kazantsev APInt max, min;
1521d792171eSMax Kazantsev if (getSignedMin().isNonNegative()) {
1522d792171eSMax Kazantsev // Upper and Lower of LHS are non-negative.
1523d792171eSMax Kazantsev min = PosMin;
1524d792171eSMax Kazantsev max = PosMax;
1525d792171eSMax Kazantsev } else if (getSignedMax().isNegative()) {
1526d792171eSMax Kazantsev // Upper and Lower of LHS are negative.
1527d792171eSMax Kazantsev min = NegMin;
1528d792171eSMax Kazantsev max = NegMax;
1529d792171eSMax Kazantsev } else {
1530d792171eSMax Kazantsev // Upper is non-negative and Lower is negative.
1531d792171eSMax Kazantsev min = NegMin;
1532d792171eSMax Kazantsev max = PosMax;
1533d792171eSMax Kazantsev }
1534dbc3fbafSNikita Popov return getNonEmpty(std::move(min), std::move(max));
1535d792171eSMax Kazantsev }
1536d792171eSMax Kazantsev
uadd_sat(const ConstantRange & Other) const1537198ab601SNikita Popov ConstantRange ConstantRange::uadd_sat(const ConstantRange &Other) const {
1538198ab601SNikita Popov if (isEmptySet() || Other.isEmptySet())
1539198ab601SNikita Popov return getEmpty();
1540198ab601SNikita Popov
1541198ab601SNikita Popov APInt NewL = getUnsignedMin().uadd_sat(Other.getUnsignedMin());
1542198ab601SNikita Popov APInt NewU = getUnsignedMax().uadd_sat(Other.getUnsignedMax()) + 1;
1543198ab601SNikita Popov return getNonEmpty(std::move(NewL), std::move(NewU));
1544198ab601SNikita Popov }
1545198ab601SNikita Popov
sadd_sat(const ConstantRange & Other) const1546198ab601SNikita Popov ConstantRange ConstantRange::sadd_sat(const ConstantRange &Other) const {
1547198ab601SNikita Popov if (isEmptySet() || Other.isEmptySet())
1548198ab601SNikita Popov return getEmpty();
1549198ab601SNikita Popov
1550198ab601SNikita Popov APInt NewL = getSignedMin().sadd_sat(Other.getSignedMin());
1551198ab601SNikita Popov APInt NewU = getSignedMax().sadd_sat(Other.getSignedMax()) + 1;
1552198ab601SNikita Popov return getNonEmpty(std::move(NewL), std::move(NewU));
1553198ab601SNikita Popov }
1554198ab601SNikita Popov
usub_sat(const ConstantRange & Other) const1555198ab601SNikita Popov ConstantRange ConstantRange::usub_sat(const ConstantRange &Other) const {
1556198ab601SNikita Popov if (isEmptySet() || Other.isEmptySet())
1557198ab601SNikita Popov return getEmpty();
1558198ab601SNikita Popov
1559198ab601SNikita Popov APInt NewL = getUnsignedMin().usub_sat(Other.getUnsignedMax());
1560198ab601SNikita Popov APInt NewU = getUnsignedMax().usub_sat(Other.getUnsignedMin()) + 1;
1561198ab601SNikita Popov return getNonEmpty(std::move(NewL), std::move(NewU));
1562198ab601SNikita Popov }
1563198ab601SNikita Popov
ssub_sat(const ConstantRange & Other) const1564198ab601SNikita Popov ConstantRange ConstantRange::ssub_sat(const ConstantRange &Other) const {
1565198ab601SNikita Popov if (isEmptySet() || Other.isEmptySet())
1566198ab601SNikita Popov return getEmpty();
1567198ab601SNikita Popov
1568198ab601SNikita Popov APInt NewL = getSignedMin().ssub_sat(Other.getSignedMax());
1569198ab601SNikita Popov APInt NewU = getSignedMax().ssub_sat(Other.getSignedMin()) + 1;
1570198ab601SNikita Popov return getNonEmpty(std::move(NewL), std::move(NewU));
1571198ab601SNikita Popov }
1572198ab601SNikita Popov
umul_sat(const ConstantRange & Other) const15735a9fd76dSRoman Lebedev ConstantRange ConstantRange::umul_sat(const ConstantRange &Other) const {
15745a9fd76dSRoman Lebedev if (isEmptySet() || Other.isEmptySet())
15755a9fd76dSRoman Lebedev return getEmpty();
15765a9fd76dSRoman Lebedev
15775a9fd76dSRoman Lebedev APInt NewL = getUnsignedMin().umul_sat(Other.getUnsignedMin());
15785a9fd76dSRoman Lebedev APInt NewU = getUnsignedMax().umul_sat(Other.getUnsignedMax()) + 1;
15795a9fd76dSRoman Lebedev return getNonEmpty(std::move(NewL), std::move(NewU));
15805a9fd76dSRoman Lebedev }
15815a9fd76dSRoman Lebedev
smul_sat(const ConstantRange & Other) const15825a9fd76dSRoman Lebedev ConstantRange ConstantRange::smul_sat(const ConstantRange &Other) const {
15835a9fd76dSRoman Lebedev if (isEmptySet() || Other.isEmptySet())
15845a9fd76dSRoman Lebedev return getEmpty();
15855a9fd76dSRoman Lebedev
15865a9fd76dSRoman Lebedev // Because we could be dealing with negative numbers here, the lower bound is
15875a9fd76dSRoman Lebedev // the smallest of the cartesian product of the lower and upper ranges;
15885a9fd76dSRoman Lebedev // for example:
15895a9fd76dSRoman Lebedev // [-1,4) * [-2,3) = min(-1*-2, -1*2, 3*-2, 3*2) = -6.
15905a9fd76dSRoman Lebedev // Similarly for the upper bound, swapping min for max.
15915a9fd76dSRoman Lebedev
1592ea7be260SNikita Popov APInt Min = getSignedMin();
1593ea7be260SNikita Popov APInt Max = getSignedMax();
1594ea7be260SNikita Popov APInt OtherMin = Other.getSignedMin();
1595ea7be260SNikita Popov APInt OtherMax = Other.getSignedMax();
15965a9fd76dSRoman Lebedev
1597ea7be260SNikita Popov auto L = {Min.smul_sat(OtherMin), Min.smul_sat(OtherMax),
1598ea7be260SNikita Popov Max.smul_sat(OtherMin), Max.smul_sat(OtherMax)};
15995a9fd76dSRoman Lebedev auto Compare = [](const APInt &A, const APInt &B) { return A.slt(B); };
1600ea7be260SNikita Popov return getNonEmpty(std::min(L, Compare), std::max(L, Compare) + 1);
16015a9fd76dSRoman Lebedev }
16025a9fd76dSRoman Lebedev
ushl_sat(const ConstantRange & Other) const1603e0ea842bSRoman Lebedev ConstantRange ConstantRange::ushl_sat(const ConstantRange &Other) const {
1604e0ea842bSRoman Lebedev if (isEmptySet() || Other.isEmptySet())
1605e0ea842bSRoman Lebedev return getEmpty();
1606e0ea842bSRoman Lebedev
1607e0ea842bSRoman Lebedev APInt NewL = getUnsignedMin().ushl_sat(Other.getUnsignedMin());
1608e0ea842bSRoman Lebedev APInt NewU = getUnsignedMax().ushl_sat(Other.getUnsignedMax()) + 1;
1609e0ea842bSRoman Lebedev return getNonEmpty(std::move(NewL), std::move(NewU));
1610e0ea842bSRoman Lebedev }
1611e0ea842bSRoman Lebedev
sshl_sat(const ConstantRange & Other) const1612e0ea842bSRoman Lebedev ConstantRange ConstantRange::sshl_sat(const ConstantRange &Other) const {
1613e0ea842bSRoman Lebedev if (isEmptySet() || Other.isEmptySet())
1614e0ea842bSRoman Lebedev return getEmpty();
1615e0ea842bSRoman Lebedev
1616e0ea842bSRoman Lebedev APInt Min = getSignedMin(), Max = getSignedMax();
1617e0ea842bSRoman Lebedev APInt ShAmtMin = Other.getUnsignedMin(), ShAmtMax = Other.getUnsignedMax();
161872a21ad6SRoman Lebedev APInt NewL = Min.sshl_sat(Min.isNonNegative() ? ShAmtMin : ShAmtMax);
161972a21ad6SRoman Lebedev APInt NewU = Max.sshl_sat(Max.isNegative() ? ShAmtMin : ShAmtMax) + 1;
1620e0ea842bSRoman Lebedev return getNonEmpty(std::move(NewL), std::move(NewU));
1621e0ea842bSRoman Lebedev }
1622e0ea842bSRoman Lebedev
inverse() const16238cd041efSChandler Carruth ConstantRange ConstantRange::inverse() const {
16248cd041efSChandler Carruth if (isFullSet())
1625977934f0SNikita Popov return getEmpty();
16268cd041efSChandler Carruth if (isEmptySet())
1627977934f0SNikita Popov return getFull();
16288cd041efSChandler Carruth return ConstantRange(Upper, Lower);
16298cd041efSChandler Carruth }
16308cd041efSChandler Carruth
abs(bool IntMinIsPoison) const163194f8120cSNikita Popov ConstantRange ConstantRange::abs(bool IntMinIsPoison) const {
1632c0fa4ec0SNikita Popov if (isEmptySet())
1633c0fa4ec0SNikita Popov return getEmpty();
1634c0fa4ec0SNikita Popov
1635c0fa4ec0SNikita Popov if (isSignWrappedSet()) {
1636c0fa4ec0SNikita Popov APInt Lo;
1637c0fa4ec0SNikita Popov // Check whether the range crosses zero.
1638c0fa4ec0SNikita Popov if (Upper.isStrictlyPositive() || !Lower.isStrictlyPositive())
1639735f4671SChris Lattner Lo = APInt::getZero(getBitWidth());
1640c0fa4ec0SNikita Popov else
1641c0fa4ec0SNikita Popov Lo = APIntOps::umin(Lower, -Upper + 1);
1642c0fa4ec0SNikita Popov
164394f8120cSNikita Popov // If SignedMin is not poison, then it is included in the result range.
164494f8120cSNikita Popov if (IntMinIsPoison)
164594f8120cSNikita Popov return ConstantRange(Lo, APInt::getSignedMinValue(getBitWidth()));
164694f8120cSNikita Popov else
1647c0fa4ec0SNikita Popov return ConstantRange(Lo, APInt::getSignedMinValue(getBitWidth()) + 1);
1648c0fa4ec0SNikita Popov }
1649c0fa4ec0SNikita Popov
1650c0fa4ec0SNikita Popov APInt SMin = getSignedMin(), SMax = getSignedMax();
1651c0fa4ec0SNikita Popov
165294f8120cSNikita Popov // Skip SignedMin if it is poison.
165394f8120cSNikita Popov if (IntMinIsPoison && SMin.isMinSignedValue()) {
165494f8120cSNikita Popov // The range may become empty if it *only* contains SignedMin.
165594f8120cSNikita Popov if (SMax.isMinSignedValue())
165694f8120cSNikita Popov return getEmpty();
165794f8120cSNikita Popov ++SMin;
165894f8120cSNikita Popov }
165994f8120cSNikita Popov
1660c0fa4ec0SNikita Popov // All non-negative.
1661c0fa4ec0SNikita Popov if (SMin.isNonNegative())
1662c0fa4ec0SNikita Popov return *this;
1663c0fa4ec0SNikita Popov
1664c0fa4ec0SNikita Popov // All negative.
1665c0fa4ec0SNikita Popov if (SMax.isNegative())
1666c0fa4ec0SNikita Popov return ConstantRange(-SMax, -SMin + 1);
1667c0fa4ec0SNikita Popov
1668c0fa4ec0SNikita Popov // Range crosses zero.
1669735f4671SChris Lattner return ConstantRange(APInt::getZero(getBitWidth()),
1670c0fa4ec0SNikita Popov APIntOps::umax(-SMin, SMax) + 1);
1671c0fa4ec0SNikita Popov }
1672c0fa4ec0SNikita Popov
unsignedAddMayOverflow(const ConstantRange & Other) const1673e3d3e862SNikita Popov ConstantRange::OverflowResult ConstantRange::unsignedAddMayOverflow(
1674e3d3e862SNikita Popov const ConstantRange &Other) const {
1675e3d3e862SNikita Popov if (isEmptySet() || Other.isEmptySet())
1676e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1677e3d3e862SNikita Popov
1678e3d3e862SNikita Popov APInt Min = getUnsignedMin(), Max = getUnsignedMax();
1679e3d3e862SNikita Popov APInt OtherMin = Other.getUnsignedMin(), OtherMax = Other.getUnsignedMax();
1680e3d3e862SNikita Popov
1681332c1005SNikita Popov // a u+ b overflows high iff a u> ~b.
1682e3d3e862SNikita Popov if (Min.ugt(~OtherMin))
1683332c1005SNikita Popov return OverflowResult::AlwaysOverflowsHigh;
1684e3d3e862SNikita Popov if (Max.ugt(~OtherMax))
1685e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1686e3d3e862SNikita Popov return OverflowResult::NeverOverflows;
1687e3d3e862SNikita Popov }
1688e3d3e862SNikita Popov
signedAddMayOverflow(const ConstantRange & Other) const1689e3d3e862SNikita Popov ConstantRange::OverflowResult ConstantRange::signedAddMayOverflow(
1690e3d3e862SNikita Popov const ConstantRange &Other) const {
1691e3d3e862SNikita Popov if (isEmptySet() || Other.isEmptySet())
1692e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1693e3d3e862SNikita Popov
1694e3d3e862SNikita Popov APInt Min = getSignedMin(), Max = getSignedMax();
1695e3d3e862SNikita Popov APInt OtherMin = Other.getSignedMin(), OtherMax = Other.getSignedMax();
1696e3d3e862SNikita Popov
1697e3d3e862SNikita Popov APInt SignedMin = APInt::getSignedMinValue(getBitWidth());
1698e3d3e862SNikita Popov APInt SignedMax = APInt::getSignedMaxValue(getBitWidth());
1699e3d3e862SNikita Popov
1700e3d3e862SNikita Popov // a s+ b overflows high iff a s>=0 && b s>= 0 && a s> smax - b.
1701e3d3e862SNikita Popov // a s+ b overflows low iff a s< 0 && b s< 0 && a s< smin - b.
1702e3d3e862SNikita Popov if (Min.isNonNegative() && OtherMin.isNonNegative() &&
1703e3d3e862SNikita Popov Min.sgt(SignedMax - OtherMin))
1704332c1005SNikita Popov return OverflowResult::AlwaysOverflowsHigh;
1705e3d3e862SNikita Popov if (Max.isNegative() && OtherMax.isNegative() &&
1706e3d3e862SNikita Popov Max.slt(SignedMin - OtherMax))
1707332c1005SNikita Popov return OverflowResult::AlwaysOverflowsLow;
1708e3d3e862SNikita Popov
1709e3d3e862SNikita Popov if (Max.isNonNegative() && OtherMax.isNonNegative() &&
1710e3d3e862SNikita Popov Max.sgt(SignedMax - OtherMax))
1711e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1712e3d3e862SNikita Popov if (Min.isNegative() && OtherMin.isNegative() &&
1713e3d3e862SNikita Popov Min.slt(SignedMin - OtherMin))
1714e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1715e3d3e862SNikita Popov
1716e3d3e862SNikita Popov return OverflowResult::NeverOverflows;
1717e3d3e862SNikita Popov }
1718e3d3e862SNikita Popov
unsignedSubMayOverflow(const ConstantRange & Other) const1719e3d3e862SNikita Popov ConstantRange::OverflowResult ConstantRange::unsignedSubMayOverflow(
1720e3d3e862SNikita Popov const ConstantRange &Other) const {
1721e3d3e862SNikita Popov if (isEmptySet() || Other.isEmptySet())
1722e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1723e3d3e862SNikita Popov
1724e3d3e862SNikita Popov APInt Min = getUnsignedMin(), Max = getUnsignedMax();
1725e3d3e862SNikita Popov APInt OtherMin = Other.getUnsignedMin(), OtherMax = Other.getUnsignedMax();
1726e3d3e862SNikita Popov
1727332c1005SNikita Popov // a u- b overflows low iff a u< b.
1728e3d3e862SNikita Popov if (Max.ult(OtherMin))
1729332c1005SNikita Popov return OverflowResult::AlwaysOverflowsLow;
1730e3d3e862SNikita Popov if (Min.ult(OtherMax))
1731e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1732e3d3e862SNikita Popov return OverflowResult::NeverOverflows;
1733e3d3e862SNikita Popov }
1734e3d3e862SNikita Popov
signedSubMayOverflow(const ConstantRange & Other) const1735e3d3e862SNikita Popov ConstantRange::OverflowResult ConstantRange::signedSubMayOverflow(
1736e3d3e862SNikita Popov const ConstantRange &Other) const {
1737e3d3e862SNikita Popov if (isEmptySet() || Other.isEmptySet())
1738e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1739e3d3e862SNikita Popov
1740e3d3e862SNikita Popov APInt Min = getSignedMin(), Max = getSignedMax();
1741e3d3e862SNikita Popov APInt OtherMin = Other.getSignedMin(), OtherMax = Other.getSignedMax();
1742e3d3e862SNikita Popov
1743e3d3e862SNikita Popov APInt SignedMin = APInt::getSignedMinValue(getBitWidth());
1744e3d3e862SNikita Popov APInt SignedMax = APInt::getSignedMaxValue(getBitWidth());
1745e3d3e862SNikita Popov
1746e3d3e862SNikita Popov // a s- b overflows high iff a s>=0 && b s< 0 && a s> smax + b.
1747e3d3e862SNikita Popov // a s- b overflows low iff a s< 0 && b s>= 0 && a s< smin + b.
1748e3d3e862SNikita Popov if (Min.isNonNegative() && OtherMax.isNegative() &&
1749e3d3e862SNikita Popov Min.sgt(SignedMax + OtherMax))
1750332c1005SNikita Popov return OverflowResult::AlwaysOverflowsHigh;
1751e3d3e862SNikita Popov if (Max.isNegative() && OtherMin.isNonNegative() &&
1752e3d3e862SNikita Popov Max.slt(SignedMin + OtherMin))
1753332c1005SNikita Popov return OverflowResult::AlwaysOverflowsLow;
1754e3d3e862SNikita Popov
1755e3d3e862SNikita Popov if (Max.isNonNegative() && OtherMin.isNegative() &&
1756e3d3e862SNikita Popov Max.sgt(SignedMax + OtherMin))
1757e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1758e3d3e862SNikita Popov if (Min.isNegative() && OtherMax.isNonNegative() &&
1759e3d3e862SNikita Popov Min.slt(SignedMin + OtherMax))
1760e3d3e862SNikita Popov return OverflowResult::MayOverflow;
1761e3d3e862SNikita Popov
1762e3d3e862SNikita Popov return OverflowResult::NeverOverflows;
1763e3d3e862SNikita Popov }
1764e3d3e862SNikita Popov
unsignedMulMayOverflow(const ConstantRange & Other) const1765e319eafbSNikita Popov ConstantRange::OverflowResult ConstantRange::unsignedMulMayOverflow(
1766e319eafbSNikita Popov const ConstantRange &Other) const {
1767e319eafbSNikita Popov if (isEmptySet() || Other.isEmptySet())
1768e319eafbSNikita Popov return OverflowResult::MayOverflow;
1769e319eafbSNikita Popov
1770e319eafbSNikita Popov APInt Min = getUnsignedMin(), Max = getUnsignedMax();
1771e319eafbSNikita Popov APInt OtherMin = Other.getUnsignedMin(), OtherMax = Other.getUnsignedMax();
1772e319eafbSNikita Popov bool Overflow;
1773e319eafbSNikita Popov
1774e319eafbSNikita Popov (void) Min.umul_ov(OtherMin, Overflow);
1775e319eafbSNikita Popov if (Overflow)
1776332c1005SNikita Popov return OverflowResult::AlwaysOverflowsHigh;
1777e319eafbSNikita Popov
1778e319eafbSNikita Popov (void) Max.umul_ov(OtherMax, Overflow);
1779e319eafbSNikita Popov if (Overflow)
1780e319eafbSNikita Popov return OverflowResult::MayOverflow;
1781e319eafbSNikita Popov
1782e319eafbSNikita Popov return OverflowResult::NeverOverflows;
1783e319eafbSNikita Popov }
1784e319eafbSNikita Popov
print(raw_ostream & OS) const17858cd041efSChandler Carruth void ConstantRange::print(raw_ostream &OS) const {
17868cd041efSChandler Carruth if (isFullSet())
17878cd041efSChandler Carruth OS << "full-set";
17888cd041efSChandler Carruth else if (isEmptySet())
17898cd041efSChandler Carruth OS << "empty-set";
17908cd041efSChandler Carruth else
17918cd041efSChandler Carruth OS << "[" << Lower << "," << Upper << ")";
17928cd041efSChandler Carruth }
17938cd041efSChandler Carruth
1794615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const1795eb2a2546SYaron Keren LLVM_DUMP_METHOD void ConstantRange::dump() const {
17968cd041efSChandler Carruth print(dbgs());
17978cd041efSChandler Carruth }
17988c209aa8SMatthias Braun #endif
1799ecdd58f1SPeter Collingbourne
getConstantRangeFromMetadata(const MDNode & Ranges)1800ecdd58f1SPeter Collingbourne ConstantRange llvm::getConstantRangeFromMetadata(const MDNode &Ranges) {
1801ecdd58f1SPeter Collingbourne const unsigned NumRanges = Ranges.getNumOperands() / 2;
1802ecdd58f1SPeter Collingbourne assert(NumRanges >= 1 && "Must have at least one range!");
1803ecdd58f1SPeter Collingbourne assert(Ranges.getNumOperands() % 2 == 0 && "Must be a sequence of pairs");
1804ecdd58f1SPeter Collingbourne
1805ecdd58f1SPeter Collingbourne auto *FirstLow = mdconst::extract<ConstantInt>(Ranges.getOperand(0));
1806ecdd58f1SPeter Collingbourne auto *FirstHigh = mdconst::extract<ConstantInt>(Ranges.getOperand(1));
1807ecdd58f1SPeter Collingbourne
1808ecdd58f1SPeter Collingbourne ConstantRange CR(FirstLow->getValue(), FirstHigh->getValue());
1809ecdd58f1SPeter Collingbourne
1810ecdd58f1SPeter Collingbourne for (unsigned i = 1; i < NumRanges; ++i) {
1811ecdd58f1SPeter Collingbourne auto *Low = mdconst::extract<ConstantInt>(Ranges.getOperand(2 * i + 0));
1812ecdd58f1SPeter Collingbourne auto *High = mdconst::extract<ConstantInt>(Ranges.getOperand(2 * i + 1));
1813ecdd58f1SPeter Collingbourne
1814ecdd58f1SPeter Collingbourne // Note: unionWith will potentially create a range that contains values not
1815ecdd58f1SPeter Collingbourne // contained in any of the original N ranges.
1816ecdd58f1SPeter Collingbourne CR = CR.unionWith(ConstantRange(Low->getValue(), High->getValue()));
1817ecdd58f1SPeter Collingbourne }
1818ecdd58f1SPeter Collingbourne
1819ecdd58f1SPeter Collingbourne return CR;
1820ecdd58f1SPeter Collingbourne }
1821