Index: include/llvm/IR/ConstantRange.h =================================================================== --- include/llvm/IR/ConstantRange.h +++ include/llvm/IR/ConstantRange.h @@ -310,6 +310,9 @@ /// Return a new range that is the logical not of the current set. ConstantRange inverse() const; + /// Convert this ConstantRange to its inverse. + void inverseInPlace(); + /// Print out the bounds to a stream. void print(raw_ostream &OS) const; Index: lib/IR/ConstantRange.cpp =================================================================== --- lib/IR/ConstantRange.cpp +++ lib/IR/ConstantRange.cpp @@ -172,15 +172,6 @@ unsigned NoWrapKind) { typedef OverflowingBinaryOperator OBO; - // Computes the intersection of CR0 and CR1. It is different from - // intersectWith in that the ConstantRange returned will only contain elements - // in both CR0 and CR1 (i.e. SubsetIntersect(X, Y) is a *subset*, proper or - // not, of both X and Y). - auto SubsetIntersect = - [](const ConstantRange &CR0, const ConstantRange &CR1) { - return CR0.inverse().unionWith(CR1.inverse()).inverse(); - }; - assert(BinOp >= Instruction::BinaryOpsBegin && BinOp < Instruction::BinaryOpsEnd && "Binary operators only!"); @@ -199,29 +190,44 @@ // Full set: nothing signed / unsigned wraps when added to 0. return ConstantRange(BitWidth); - ConstantRange Result(BitWidth); + // Start with the Result inverted from FullSet to avoid repeated + // inversions when we calculate the intersection. We'll do a final invert at + // the end. + ConstantRange Result(BitWidth, false); + + // Computes the inverse intersection of inverse(Result) and Other. It + // is different from intersectWith in that the ConstantRange returned will + // only contain elements in both inverse(Result) and Other + // (i.e. inverse(SubsetIntersectWith(Y)) is a *subset*, proper or + // not, of both inverse(Result) and Y). + // NOTE: We return in inverted form so that the multiple calls to this don't + // have to invert again. There is one final invert at the end. + auto SubsetIntersectWithResult = [&](ConstantRange Other) { + Other.inverseInPlace(); + Result = Result.unionWith(Other); + }; if (NoWrapKind & OBO::NoUnsignedWrap) - Result = - SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth), - -Other.getUnsignedMax())); + SubsetIntersectWithResult( + ConstantRange(APInt::getNullValue(BitWidth), -Other.getUnsignedMax())); if (NoWrapKind & OBO::NoSignedWrap) { const APInt &SignedMin = Other.getSignedMin(); const APInt &SignedMax = Other.getSignedMax(); if (SignedMax.isStrictlyPositive()) - Result = SubsetIntersect( - Result, + SubsetIntersectWithResult( ConstantRange(APInt::getSignedMinValue(BitWidth), APInt::getSignedMinValue(BitWidth) - SignedMax)); if (SignedMin.isNegative()) - Result = SubsetIntersect( - Result, ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin, - APInt::getSignedMinValue(BitWidth))); + SubsetIntersectWithResult( + ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin, + APInt::getSignedMinValue(BitWidth))); } + // Invert Result to get the final subset since we computed it inverted. + Result.inverseInPlace(); return Result; } @@ -906,6 +912,18 @@ return ConstantRange(std::move(min), std::move(max) + 1); } +void ConstantRange::inverseInPlace() { + if (isFullSet()) { + Lower.clearAllBits(); + Upper.clearAllBits(); + } else if (isEmptySet()) { + Lower.setAllBits(); + Upper.setAllBits(); + } else { + std::swap(Lower, Upper); + } +} + ConstantRange ConstantRange::inverse() const { if (isFullSet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false);