Index: llvm/include/llvm/IR/ConstantRange.h =================================================================== --- llvm/include/llvm/IR/ConstantRange.h +++ llvm/include/llvm/IR/ConstantRange.h @@ -143,14 +143,32 @@ /// Return true if this set contains no members. bool isEmptySet() const; - /// Return true if this set wraps around the top of the range. - /// For example: [100, 8). + /// Return true if this set wraps around the unsigned domain. Special cases: + /// * Empty set: Not wrapped. + /// * Full set: Not wrapped. + /// * [X, 0) == [X, Max]: Not wrapped. bool isWrappedSet() const; - /// Return true if this set wraps around the INT_MIN of - /// its bitwidth. For example: i8 [120, 140). + /// Return true if this set wraps around the signed domain. Special cases: + /// * Empty set: Not wrapped. + /// * Full set: Not wrapped. + /// * [X, SignedMin) == [X, SignedMax]: Not wrapped. bool isSignWrappedSet() const; + /// Return true if the exclusive upper bound wraps around the unsigned + /// domain. Special cases: + /// * Empty set: Not wrapped. + /// * Full set: Not wrapped. + /// * [X, 0): Wrapped. + bool isUpperWrapped() const; + + /// Return true if the (exclusive) upper bound wraps around the signed + /// domain. Special cases: + /// * Empty set: Not wrapped. + /// * Full set: Not wrapped. + /// * [X, SignedMin): Wrapped. + bool isUpperSignWrapped() const; + /// Return true if the specified value is in the set. bool contains(const APInt &Val) const; Index: llvm/lib/IR/ConstantRange.cpp =================================================================== --- llvm/lib/IR/ConstantRange.cpp +++ llvm/lib/IR/ConstantRange.cpp @@ -345,12 +345,19 @@ } bool ConstantRange::isWrappedSet() const { - return Lower.ugt(Upper); + return Lower.ugt(Upper) && !Upper.isNullValue(); } bool ConstantRange::isSignWrappedSet() const { - return contains(APInt::getSignedMaxValue(getBitWidth())) && - contains(APInt::getSignedMinValue(getBitWidth())); + return Lower.sgt(Upper) && !Upper.isMinSignedValue(); +} + +bool ConstantRange::isUpperWrapped() const { + return Lower.ugt(Upper); +} + +bool ConstantRange::isUpperSignWrapped() const { + return Lower.sgt(Upper); } APInt ConstantRange::getSetSize() const { @@ -383,25 +390,25 @@ } APInt ConstantRange::getUnsignedMax() const { - if (isFullSet() || isWrappedSet()) + if (isFullSet() || isUpperWrapped()) return APInt::getMaxValue(getBitWidth()); return getUpper() - 1; } APInt ConstantRange::getUnsignedMin() const { - if (isFullSet() || (isWrappedSet() && !getUpper().isNullValue())) + if (isFullSet() || isWrappedSet()) return APInt::getMinValue(getBitWidth()); return getLower(); } APInt ConstantRange::getSignedMax() const { - if (isFullSet() || Lower.sgt(Upper)) + if (isFullSet() || isUpperSignWrapped()) return APInt::getSignedMaxValue(getBitWidth()); return getUpper() - 1; } APInt ConstantRange::getSignedMin() const { - if (isFullSet() || (Lower.sgt(Upper) && !getUpper().isMinSignedValue())) + if (isFullSet() || isSignWrappedSet()) return APInt::getSignedMinValue(getBitWidth()); return getLower(); } @@ -410,7 +417,7 @@ if (Lower == Upper) return isFullSet(); - if (!isWrappedSet()) + if (!isUpperWrapped()) return Lower.ule(V) && V.ult(Upper); return Lower.ule(V) || V.ult(Upper); } @@ -419,14 +426,14 @@ if (isFullSet() || Other.isEmptySet()) return true; if (isEmptySet() || Other.isFullSet()) return false; - if (!isWrappedSet()) { - if (Other.isWrappedSet()) + if (!isUpperWrapped()) { + if (Other.isUpperWrapped()) return false; return Lower.ule(Other.getLower()) && Other.getUpper().ule(Upper); } - if (!Other.isWrappedSet()) + if (!Other.isUpperWrapped()) return Other.getUpper().ule(Upper) || Lower.ule(Other.getLower()); @@ -453,10 +460,10 @@ if ( isEmptySet() || CR.isFullSet()) return *this; if (CR.isEmptySet() || isFullSet()) return CR; - if (!isWrappedSet() && CR.isWrappedSet()) + if (!isUpperWrapped() && CR.isUpperWrapped()) return CR.intersectWith(*this); - if (!isWrappedSet() && !CR.isWrappedSet()) { + if (!isUpperWrapped() && !CR.isUpperWrapped()) { if (Lower.ult(CR.Lower)) { if (Upper.ule(CR.Lower)) return ConstantRange(getBitWidth(), false); @@ -475,7 +482,7 @@ return ConstantRange(getBitWidth(), false); } - if (isWrappedSet() && !CR.isWrappedSet()) { + if (isUpperWrapped() && !CR.isUpperWrapped()) { if (CR.Lower.ult(Upper)) { if (CR.Upper.ult(Upper)) return CR; @@ -526,9 +533,9 @@ if ( isFullSet() || CR.isEmptySet()) return *this; if (CR.isFullSet() || isEmptySet()) return CR; - if (!isWrappedSet() && CR.isWrappedSet()) return CR.unionWith(*this); + if (!isUpperWrapped() && CR.isUpperWrapped()) return CR.unionWith(*this); - if (!isWrappedSet() && !CR.isWrappedSet()) { + if (!isUpperWrapped() && !CR.isUpperWrapped()) { if (CR.Upper.ult(Lower) || Upper.ult(CR.Lower)) { // If the two ranges are disjoint, find the smaller gap and bridge it. APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; @@ -546,7 +553,7 @@ return ConstantRange(std::move(L), std::move(U)); } - if (!CR.isWrappedSet()) { + if (!CR.isUpperWrapped()) { // ------U L----- and ------U L----- : this // L--U L--U : CR if (CR.Upper.ule(Upper) || CR.Lower.uge(Lower)) @@ -638,7 +645,7 @@ unsigned SrcTySize = getBitWidth(); assert(SrcTySize < DstTySize && "Not a value extension"); - if (isFullSet() || isWrappedSet()) { + if (isFullSet() || isUpperWrapped()) { // Change into [0, 1 << src bit width) APInt LowerExt(DstTySize, 0); if (!Upper) // special case: [X, 0) -- not really wrapping around @@ -660,7 +667,7 @@ if (Upper.isMinSignedValue()) return ConstantRange(Lower.sext(DstTySize), Upper.zext(DstTySize)); - if (isFullSet() || isSignWrappedSet()) { + if (isFullSet() || isUpperSignWrapped()) { return ConstantRange(APInt::getHighBitsSet(DstTySize,DstTySize-SrcTySize+1), APInt::getLowBitsSet(DstTySize, SrcTySize-1) + 1); } @@ -681,7 +688,7 @@ // Analyze wrapped sets in their two parts: [0, Upper) \/ [Lower, MaxValue] // We use the non-wrapped set code to analyze the [Lower, MaxValue) part, and // then we do the union with [MaxValue, Upper) - if (isWrappedSet()) { + if (isUpperWrapped()) { // If Upper is greater than or equal to MaxValue(DstTy), it covers the whole // truncated range. if (Upper.getActiveBits() > DstTySize || @@ -860,7 +867,7 @@ // from one positive number to another which is as good as we can generate. // In this case, skip the extra work of generating signed ranges which aren't // going to be better than this range. - if (!UR.isWrappedSet() && + if (!UR.isUpperWrapped() && (UR.getUpper().isNonNegative() || UR.getUpper().isMinSignedValue())) return UR; Index: llvm/unittests/IR/ConstantRangeTest.cpp =================================================================== --- llvm/unittests/IR/ConstantRangeTest.cpp +++ llvm/unittests/IR/ConstantRangeTest.cpp @@ -161,7 +161,7 @@ } TEST_F(ConstantRangeTest, SignWrapped) { - EXPECT_TRUE(Full.isSignWrappedSet()); + EXPECT_FALSE(Full.isSignWrappedSet()); EXPECT_FALSE(Empty.isSignWrappedSet()); EXPECT_FALSE(One.isSignWrappedSet()); EXPECT_FALSE(Some.isSignWrappedSet()); @@ -176,6 +176,29 @@ EXPECT_FALSE(ConstantRange(APInt(8, 250), APInt(8, 251)).isSignWrappedSet()); } +TEST_F(ConstantRangeTest, UpperWrapped) { + // The behavior here is the same as for isWrappedSet() / isSignWrappedSet(). + EXPECT_FALSE(Full.isUpperWrapped()); + EXPECT_FALSE(Empty.isUpperWrapped()); + EXPECT_FALSE(One.isUpperWrapped()); + EXPECT_FALSE(Some.isUpperWrapped()); + EXPECT_TRUE(Wrap.isUpperWrapped()); + EXPECT_FALSE(Full.isUpperSignWrapped()); + EXPECT_FALSE(Empty.isUpperSignWrapped()); + EXPECT_FALSE(One.isUpperSignWrapped()); + EXPECT_FALSE(Some.isUpperSignWrapped()); + EXPECT_TRUE(Wrap.isUpperSignWrapped()); + + // The behavior differs if Upper is the Min/SignedMin value. + ConstantRange CR1(APInt(8, 42), APInt::getMinValue(8)); + EXPECT_FALSE(CR1.isWrappedSet()); + EXPECT_TRUE(CR1.isUpperWrapped()); + + ConstantRange CR2(APInt(8, 42), APInt::getSignedMinValue(8)); + EXPECT_FALSE(CR2.isSignWrappedSet()); + EXPECT_TRUE(CR2.isUpperSignWrapped()); +} + TEST_F(ConstantRangeTest, Trunc) { ConstantRange TFull = Full.truncate(10); ConstantRange TEmpty = Empty.truncate(10);