diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h index 1b7c1b92a573dd..20e8e67436a436 100644 --- a/llvm/include/llvm/IR/ConstantRange.h +++ b/llvm/include/llvm/IR/ConstantRange.h @@ -265,6 +265,10 @@ class LLVM_NODISCARD ConstantRange { /// in this range. unsigned getActiveBits() const; + /// Compute the maximal number of bits needed to represent every value + /// in this signed range. + unsigned getMinSignedBits() const; + /// Subtract the specified constant from the endpoints of this constant range. ConstantRange subtract(const APInt &CI) const; diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index d2132583e8f72c..4b0ad1bd25a046 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -420,6 +420,14 @@ unsigned ConstantRange::getActiveBits() const { return getUnsignedMax().getActiveBits(); } +unsigned ConstantRange::getMinSignedBits() const { + if (isEmptySet()) + return 0; + + return std::max(getSignedMin().getMinSignedBits(), + getSignedMax().getMinSignedBits()); +} + ConstantRange ConstantRange::subtract(const APInt &Val) const { assert(Val.getBitWidth() == getBitWidth() && "Wrong bit width"); // If the set is empty or full, don't modify the endpoints. diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp index 6962d349f5bc6c..19474eea01678e 100644 --- a/llvm/unittests/IR/ConstantRangeTest.cpp +++ b/llvm/unittests/IR/ConstantRangeTest.cpp @@ -668,6 +668,32 @@ TEST_F(ConstantRangeTest, losslessUnsignedTruncationZeroext) { }); } +TEST_F(ConstantRangeTest, getMinSignedBits) { + unsigned Bits = 4; + EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) { + unsigned Exact = 0; + ForeachNumInConstantRange(CR, [&](const APInt &N) { + Exact = std::max(Exact, N.getMinSignedBits()); + }); + + unsigned ResultCR = CR.getMinSignedBits(); + EXPECT_EQ(Exact, ResultCR); + }); +} +TEST_F(ConstantRangeTest, losslessSignedTruncationSignext) { + unsigned Bits = 4; + EnumerateConstantRanges(Bits, [&](const ConstantRange &CR) { + unsigned MinBitWidth = CR.getMinSignedBits(); + if (MinBitWidth == 0) { + EXPECT_TRUE(CR.isEmptySet()); + return; + } + if (MinBitWidth == Bits) + return; + EXPECT_EQ(CR, CR.truncate(MinBitWidth).signExtend(Bits)); + }); +} + TEST_F(ConstantRangeTest, SubtractAPInt) { EXPECT_EQ(Full.subtract(APInt(16, 4)), Full); EXPECT_EQ(Empty.subtract(APInt(16, 4)), Empty);