Index: include/llvm/IR/ConstantRange.h =================================================================== --- include/llvm/IR/ConstantRange.h +++ include/llvm/IR/ConstantRange.h @@ -69,6 +69,14 @@ static ConstantRange makeICmpRegion(unsigned Pred, const ConstantRange &Other); + /// Produce the range that contains exactly all the values that might satisfy + /// the comparison specified by Pred when compared to Other. This is similar + /// to makeICmpRegion except for the additional exactness constraint -- the + /// resultant range does not contain any value that for which the predicate is + /// false. + /// + static ConstantRange makeExactICmpRegion(unsigned Pred, const APInt &Other); + /// Return the lower value for this range. /// const APInt &getLower() const { return Lower; } Index: lib/IR/ConstantRange.cpp =================================================================== --- lib/IR/ConstantRange.cpp +++ lib/IR/ConstantRange.cpp @@ -114,6 +114,59 @@ } } +ConstantRange ConstantRange::makeExactICmpRegion(unsigned Pred, + const APInt &AI) { + uint32_t W = AI.getBitWidth(); + switch (Pred) { + default: + llvm_unreachable("Invalid ICmp predicate to makeICmpRegion()"); + case CmpInst::ICMP_EQ: + return ConstantRange(AI); + case CmpInst::ICMP_NE: + return ConstantRange(AI + 1, AI); + case CmpInst::ICMP_ULT: { + if (AI.isMinValue()) + return ConstantRange(W, /* isFullSet = */ false); + return ConstantRange(APInt::getMinValue(W), AI); + } + case CmpInst::ICMP_SLT: { + if (AI.isMinSignedValue()) + return ConstantRange(W, /* isFullSet = */ false); + return ConstantRange(APInt::getSignedMinValue(W), AI); + } + case CmpInst::ICMP_ULE: { + if (AI.isMaxValue()) + return ConstantRange(W); + return ConstantRange(APInt::getMinValue(W), AI + 1); + } + case CmpInst::ICMP_SLE: { + if (AI.isMaxSignedValue()) + return ConstantRange(W); + return ConstantRange(APInt::getSignedMinValue(W), AI + 1); + } + case CmpInst::ICMP_UGT: { + if (AI.isMaxValue()) + return ConstantRange(W, /* isFullSet = */ false); + return ConstantRange(AI + 1, APInt::getNullValue(W)); + } + case CmpInst::ICMP_SGT: { + if (AI.isMaxSignedValue()) + return ConstantRange(W, /* isFullSet = */ false); + return ConstantRange(AI + 1, APInt::getSignedMinValue(W)); + } + case CmpInst::ICMP_UGE: { + if (AI.isMinValue()) + return ConstantRange(W); + return ConstantRange(AI, APInt::getNullValue(W)); + } + case CmpInst::ICMP_SGE: { + if (AI.isMinSignedValue()) + return ConstantRange(W); + return ConstantRange(AI, APInt::getSignedMinValue(W)); + } + } +} + /// isFullSet - Return true if this set contains all of the elements possible /// for this data-type bool ConstantRange::isFullSet() const { Index: unittests/IR/ConstantRangeTest.cpp =================================================================== --- unittests/IR/ConstantRangeTest.cpp +++ unittests/IR/ConstantRangeTest.cpp @@ -516,4 +516,24 @@ SMax).isEmptySet()); } +TEST(ConstantRange, MakeICmpRegionExact) { + EXPECT_TRUE(ConstantRange::makeExactICmpRegion(ICmpInst::ICMP_SGT, + APInt::getSignedMaxValue(2)) + .isEmptySet()); + EXPECT_TRUE(ConstantRange::makeExactICmpRegion( + ICmpInst::ICMP_SGE, APInt::getSignedMinValue(2)).isFullSet()); + EXPECT_EQ(ConstantRange::makeExactICmpRegion( + ICmpInst::ICMP_ULT, APInt::getSignedMinValue(2)).getSetSize(), + 2); + EXPECT_EQ(ConstantRange::makeExactICmpRegion( + ICmpInst::ICMP_UGT, APInt::getSignedMinValue(2)).getSetSize(), + 1); + EXPECT_EQ(ConstantRange::makeExactICmpRegion( + ICmpInst::ICMP_NE, APInt::getMinValue(2)).getSetSize(), + 3); + EXPECT_EQ(ConstantRange::makeExactICmpRegion( + ICmpInst::ICMP_EQ, APInt::getMinValue(2)).getSetSize(), + 1); +} + } // anonymous namespace