Index: llvm/trunk/include/llvm/IR/ConstantRange.h =================================================================== --- llvm/trunk/include/llvm/IR/ConstantRange.h +++ llvm/trunk/include/llvm/IR/ConstantRange.h @@ -124,8 +124,10 @@ static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred, const APInt &Other); - /// Return the exact range containing all X such that "X BinOpC Y" is - /// guaranteed not to wrap (overflow) for all Y in Other. + /// Produce the largest range containing all X such that "X BinOp Y" is + /// guaranteed not to wrap (overflow) for *all* Y in Other. However, there may + /// be *some* Y in Other for which additional X not contained in the result + /// also do not overflow. /// /// NoWrapKind must be one of OBO::NoUnsignedWrap or OBO::NoSignedWrap. /// @@ -142,6 +144,12 @@ const ConstantRange &Other, unsigned NoWrapKind); + /// Produce the range that contains X if and only if "X BinOp Other" does + /// not wrap. + static ConstantRange makeExactNoWrapRegion(Instruction::BinaryOps BinOp, + const APInt &Other, + unsigned NoWrapKind); + /// Set up \p Pred and \p RHS such that /// ConstantRange::makeExactICmpRegion(Pred, RHS) == *this. Return true if /// successful. Index: llvm/trunk/lib/Analysis/LazyValueInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/LazyValueInfo.cpp +++ llvm/trunk/lib/Analysis/LazyValueInfo.cpp @@ -1146,8 +1146,8 @@ return ValueLatticeElement::getOverdefined(); // Calculate the possible values of %x for which no overflow occurs. - ConstantRange NWR = ConstantRange::makeGuaranteedNoWrapRegion( - WO->getBinaryOp(), ConstantRange(*C), WO->getNoWrapKind()); + ConstantRange NWR = ConstantRange::makeExactNoWrapRegion( + WO->getBinaryOp(), *C, WO->getNoWrapKind()); // If overflow is false, %x is constrained to NWR. If overflow is true, %x is // constrained to it's inverse (all values that might cause overflow). Index: llvm/trunk/lib/IR/ConstantRange.cpp =================================================================== --- llvm/trunk/lib/IR/ConstantRange.cpp +++ llvm/trunk/lib/IR/ConstantRange.cpp @@ -309,6 +309,14 @@ } } +ConstantRange ConstantRange::makeExactNoWrapRegion(Instruction::BinaryOps BinOp, + const APInt &Other, + unsigned NoWrapKind) { + // makeGuaranteedNoWrapRegion() is exact for single-element ranges, as + // "for all" and "for any" coincide in this case. + return makeGuaranteedNoWrapRegion(BinOp, ConstantRange(Other), NoWrapKind); +} + bool ConstantRange::isFullSet() const { return Lower == Upper && Lower.isMaxValue(); } @@ -843,10 +851,8 @@ ConstantRange ConstantRange::addWithNoSignedWrap(const APInt &Other) const { // Calculate the subset of this range such that "X + Other" is // guaranteed not to wrap (overflow) for all X in this subset. - // makeGuaranteedNoWrapRegion will produce an exact NSW range. - auto NSWRange = ConstantRange::makeGuaranteedNoWrapRegion(BinaryOperator::Add, - ConstantRange(Other), - OverflowingBinaryOperator::NoSignedWrap); + auto NSWRange = ConstantRange::makeExactNoWrapRegion( + BinaryOperator::Add, Other, OverflowingBinaryOperator::NoSignedWrap); auto NSWConstrainedRange = intersectWith(NSWRange); return NSWConstrainedRange.add(ConstantRange(Other)); Index: llvm/trunk/unittests/IR/ConstantRangeTest.cpp =================================================================== --- llvm/trunk/unittests/IR/ConstantRangeTest.cpp +++ llvm/trunk/unittests/IR/ConstantRangeTest.cpp @@ -1176,17 +1176,25 @@ ConstantRange::makeGuaranteedNoWrapRegion(BinOp, CR2, NoWrapKind); ForeachNumInConstantRange(CR1, [&](const APInt &N1) { bool NoOverflow = true; + bool Overflow = true; ForeachNumInConstantRange(CR2, [&](const APInt &N2) { if (OverflowFn(N1, N2)) NoOverflow = false; + else + Overflow = false; }); EXPECT_EQ(NoOverflow, NoWrap.contains(N1)); + + // The no-wrap range is exact for single-element ranges. + if (CR2.isSingleElement()) { + EXPECT_EQ(Overflow, !NoWrap.contains(N1)); + } }); }); } -// Show that makeGuaranteedNoWrapRegion is precise if only one of -// NoUnsignedWrap or NoSignedWrap is used. +// Show that makeGuaranteedNoWrapRegion() is maximal, and for single-element +// ranges also exact. TEST(ConstantRange, NoWrapRegionExhaustive) { TestNoWrapRegionExhaustive( Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap,