diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2016-05-19 03:53:06 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2016-05-19 03:53:06 +0000 |
commit | 590614c1e19199a0e109dcef5a61128e5a62fede (patch) | |
tree | 177b3711b5acea68a1cbafc663f86658bcef37fd | |
parent | 41133a3e961685ba0501631045fc6ef2d2a6a212 (diff) | |
download | bcm5719-llvm-590614c1e19199a0e109dcef5a61128e5a62fede.tar.gz bcm5719-llvm-590614c1e19199a0e109dcef5a61128e5a62fede.zip |
[ConstantRange] Add an getEquivalentICmp helper
Currently only its unit test uses it, but this will be used in a later
change to simplify some logic in the GuardWidening pass.
llvm-svn: 270018
-rw-r--r-- | llvm/include/llvm/IR/ConstantRange.h | 5 | ||||
-rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 26 | ||||
-rw-r--r-- | llvm/unittests/IR/ConstantRangeTest.cpp | 46 |
3 files changed, 77 insertions, 0 deletions
diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h index aacd0481c89..9458fa9f5c8 100644 --- a/llvm/include/llvm/IR/ConstantRange.h +++ b/llvm/include/llvm/IR/ConstantRange.h @@ -114,6 +114,11 @@ public: const ConstantRange &Other, unsigned NoWrapKind); + /// Set up \p Pred and \p RHS such that + /// ConstantRange::makeExactICmpRegion(Pred, RHS) == *this. Return true if + /// successful. + bool getEquivalentICmp(CmpInst::Predicate &Pred, APInt &RHS) const; + /// Return the lower value for this range. /// const APInt &getLower() const { return Lower; } diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index a2eb1517f57..309dfc33741 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -139,6 +139,32 @@ ConstantRange ConstantRange::makeExactICmpRegion(CmpInst::Predicate Pred, return makeAllowedICmpRegion(Pred, C); } +bool ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred, + APInt &RHS) const { + bool Success = false; + + if (isFullSet() || isEmptySet()) { + Pred = isEmptySet() ? CmpInst::ICMP_ULT : CmpInst::ICMP_UGE; + RHS = APInt(getBitWidth(), 0); + Success = true; + } else if (getLower().isMinSignedValue() || getLower().isMinValue()) { + Pred = + getLower().isMinSignedValue() ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT; + RHS = getUpper(); + Success = true; + } else if (getUpper().isMinSignedValue() || getUpper().isMinValue()) { + Pred = + getUpper().isMinSignedValue() ? CmpInst::ICMP_SGE : CmpInst::ICMP_UGE; + RHS = getLower(); + Success = true; + } + + assert((!Success || ConstantRange::makeExactICmpRegion(Pred, RHS) == *this) && + "Bad result!"); + + return Success; +} + ConstantRange ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, const ConstantRange &Other, diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp index 953e68e0594..f7a8a82043b 100644 --- a/llvm/unittests/IR/ConstantRangeTest.cpp +++ b/llvm/unittests/IR/ConstantRangeTest.cpp @@ -716,4 +716,50 @@ TEST(ConstantRange, MakeGuaranteedNoWrapRegion) { ConstantRange(APInt(32, 0), APInt(32, 1))); } +TEST(ConstantRange, GetEquivalentICmp) { + APInt RHS; + CmpInst::Predicate Pred; + + EXPECT_TRUE(ConstantRange(APInt::getMinValue(32), APInt(32, 100)) + .getEquivalentICmp(Pred, RHS)); + EXPECT_EQ(Pred, CmpInst::ICMP_ULT); + EXPECT_EQ(RHS, APInt(32, 100)); + + EXPECT_TRUE(ConstantRange(APInt::getSignedMinValue(32), APInt(32, 100)) + .getEquivalentICmp(Pred, RHS)); + EXPECT_EQ(Pred, CmpInst::ICMP_SLT); + EXPECT_EQ(RHS, APInt(32, 100)); + + EXPECT_TRUE(ConstantRange(APInt(32, 100), APInt::getMinValue(32)) + .getEquivalentICmp(Pred, RHS)); + EXPECT_EQ(Pred, CmpInst::ICMP_UGE); + EXPECT_EQ(RHS, APInt(32, 100)); + + EXPECT_TRUE(ConstantRange(APInt(32, 100), APInt::getSignedMinValue(32)) + .getEquivalentICmp(Pred, RHS)); + EXPECT_EQ(Pred, CmpInst::ICMP_SGE); + EXPECT_EQ(RHS, APInt(32, 100)); + + EXPECT_TRUE( + ConstantRange(32, /*isFullSet=*/true).getEquivalentICmp(Pred, RHS)); + EXPECT_EQ(Pred, CmpInst::ICMP_UGE); + EXPECT_EQ(RHS, APInt(32, 0)); + + EXPECT_TRUE( + ConstantRange(32, /*isFullSet=*/false).getEquivalentICmp(Pred, RHS)); + EXPECT_EQ(Pred, CmpInst::ICMP_ULT); + EXPECT_EQ(RHS, APInt(32, 0)); + + EXPECT_FALSE(ConstantRange(APInt(32, 100), APInt(32, 200)) + .getEquivalentICmp(Pred, RHS)); + + EXPECT_FALSE(ConstantRange(APInt::getSignedMinValue(32) - APInt(32, 100), + APInt::getSignedMinValue(32) + APInt(32, 100)) + .getEquivalentICmp(Pred, RHS)); + + EXPECT_FALSE(ConstantRange(APInt::getMinValue(32) - APInt(32, 100), + APInt::getMinValue(32) + APInt(32, 100)) + .getEquivalentICmp(Pred, RHS)); +} + } // anonymous namespace |