diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index fb596a3bf16..f2a77765dcf 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -82,16 +82,25 @@ public: static ConstantRange makeSatisfyingICmpRegion(CmpInst::Predicate Pred, const ConstantRange &Other); - /// Return the largest range containing all X such that "X BinOpC C" does not - /// wrap (overflow). + /// Return the largest range containing all X such that "X BinOpC C" is + /// guaranteed not to wrap (overflow). + /// + /// NB! The returned set does *not* contain **all** possible values of X for + /// which "X BinOpC C" does not wrap -- some viable values of X may be + /// missing, so you cannot use this to contrain X's range. E.g. in the last + /// example, "(-2) + 1" is both nsw and nuw (so the "X" could be -2), but (-2) + /// is not in the set returned. /// /// Example: /// typedef OverflowingBinaryOperator OBO; /// makeNoWrapRegion(Add, i8 1, OBO::NoSignedWrap) == [-128, 127) /// makeNoWrapRegion(Add, i8 1, OBO::NoUnsignedWrap) == [0, -1) /// makeNoWrapRegion(Add, i8 0, OBO::NoUnsignedWrap) == Full Set - static ConstantRange makeNoWrapRegion(Instruction::BinaryOps BinOp, - const APInt &C, unsigned NoWrapKind); + /// makeNoWrapRegion(Add, i8 1, OBO::NoUnsignedWrap | OBO::NoSignedWrap) == + /// [0,INT_MAX) + static ConstantRange makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, + const APInt &C, + unsigned NoWrapKind); /// Return the lower value for this range. /// diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 07d72f5ee20..f1f57c6fbd6 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -1969,15 +1969,14 @@ StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type, const APInt &C = cast(Ops[0])->getAPInt(); if (!(SignOrUnsignWrap & SCEV::FlagNSW)) { - auto NSWRegion = - ConstantRange::makeNoWrapRegion(Instruction::Add, C, OBO::NoSignedWrap); + auto NSWRegion = ConstantRange::makeGuaranteedNoWrapRegion( + Instruction::Add, C, OBO::NoSignedWrap); if (NSWRegion.contains(SE->getSignedRange(Ops[1]))) Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNSW); } if (!(SignOrUnsignWrap & SCEV::FlagNUW)) { - auto NUWRegion = - ConstantRange::makeNoWrapRegion(Instruction::Add, C, - OBO::NoUnsignedWrap); + auto NUWRegion = ConstantRange::makeGuaranteedNoWrapRegion( + Instruction::Add, C, OBO::NoUnsignedWrap); if (NUWRegion.contains(SE->getUnsignedRange(Ops[1]))) Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW); } diff --git a/lib/IR/ConstantRange.cpp b/lib/IR/ConstantRange.cpp index 460b778bcc5..9bea98c7f3c 100644 --- a/lib/IR/ConstantRange.cpp +++ b/lib/IR/ConstantRange.cpp @@ -127,9 +127,9 @@ ConstantRange ConstantRange::makeSatisfyingICmpRegion(CmpInst::Predicate Pred, .inverse(); } -ConstantRange ConstantRange::makeNoWrapRegion(Instruction::BinaryOps BinOp, - const APInt &C, - unsigned NoWrapKind) { +ConstantRange +ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, + const APInt &C, unsigned NoWrapKind) { typedef OverflowingBinaryOperator OBO; // Computes the intersection of CR0 and CR1. It is different from diff --git a/unittests/IR/ConstantRangeTest.cpp b/unittests/IR/ConstantRangeTest.cpp index 1f32eea3e43..af2f133d38f 100644 --- a/unittests/IR/ConstantRangeTest.cpp +++ b/unittests/IR/ConstantRangeTest.cpp @@ -577,17 +577,17 @@ TEST(ConstantRange, MakeOverflowingRegion) { for (int Const : {0, -1, -2, 1, 2, IntMin4Bits, IntMax4Bits}) { APInt C(4, Const, true /* = isSigned */); - auto NUWRegion = - ConstantRange::makeNoWrapRegion(Instruction::Add, C, OBO::NoUnsignedWrap); + auto NUWRegion = ConstantRange::makeGuaranteedNoWrapRegion( + Instruction::Add, C, OBO::NoUnsignedWrap); EXPECT_FALSE(NUWRegion.isEmptySet()); - auto NSWRegion = - ConstantRange::makeNoWrapRegion(Instruction::Add, C, OBO::NoSignedWrap); + auto NSWRegion = ConstantRange::makeGuaranteedNoWrapRegion( + Instruction::Add, C, OBO::NoSignedWrap); EXPECT_FALSE(NSWRegion.isEmptySet()); - auto NoWrapRegion = ConstantRange::makeNoWrapRegion( + auto NoWrapRegion = ConstantRange::makeGuaranteedNoWrapRegion( Instruction::Add, C, OBO::NoSignedWrap | OBO::NoUnsignedWrap); EXPECT_FALSE(NoWrapRegion.isEmptySet());