diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h index 2acaecfc3440..ec88b9807174 100644 --- a/llvm/include/llvm/Support/KnownBits.h +++ b/llvm/include/llvm/Support/KnownBits.h @@ -119,12 +119,32 @@ public: return One; } + /// Return the minimal signed value possible given these KnownBits. + APInt getSignedMinValue() const { + // Assume that all bits that aren't known-ones are zeros. + APInt Min = One; + // Sign bit is unknown. + if (Zero.isSignBitClear() && One.isSignBitClear()) + Min.setSignBit(); + return Min; + } + /// Return the maximal unsigned value possible given these KnownBits. APInt getMaxValue() const { // Assume that all bits that aren't known-zeros are ones. return ~Zero; } + /// Return the maximal signed value possible given these KnownBits. + APInt getSignedMaxValue() const { + // Assume that all bits that aren't known-zeros are ones. + APInt Max = ~Zero; + // Sign bit is unknown. + if (Zero.isSignBitClear() && One.isSignBitClear()) + Max.clearSignBit(); + return Max; + } + /// Return known bits for a truncation of the value we're tracking. KnownBits trunc(unsigned BitWidth) const { return KnownBits(Zero.trunc(BitWidth), One.trunc(BitWidth)); diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index c5eb96efc85e..528a645ec51a 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -295,6 +295,20 @@ TEST(KnownBitsTest, GetMinMaxVal) { }); } +TEST(KnownBitsTest, GetSignedMinMaxVal) { + unsigned Bits = 4; + ForeachKnownBits(Bits, [&](const KnownBits &Known) { + APInt Min = APInt::getSignedMaxValue(Bits); + APInt Max = APInt::getSignedMinValue(Bits); + ForeachNumInKnownBits(Known, [&](const APInt &N) { + Min = APIntOps::smin(Min, N); + Max = APIntOps::smax(Max, N); + }); + EXPECT_EQ(Min, Known.getSignedMinValue()); + EXPECT_EQ(Max, Known.getSignedMaxValue()); + }); +} + TEST(KnownBitsTest, SExtOrTrunc) { const unsigned NarrowerSize = 4; const unsigned BaseSize = 6;