diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -595,8 +595,8 @@ /// Constructs an APInt value that has a contiguous range of bits set. The /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other /// bits will be zero. For example, with parameters(32, 0, 16) you would get - /// 0x0000FFFF. If hiBit is less than loBit then the set bits "wrap". For - /// example, with parameters (32, 28, 4), you would get 0xF000000F. + /// 0x0000FFFF. Please call getBitsSetWithWrap if \p loBit may be greater than + /// \p hiBit. /// /// \param numBits the intended bit width of the result /// \param loBit the index of the lowest bit set. @@ -604,11 +604,23 @@ /// /// \returns An APInt value with the requested bits set. static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) { + assert(loBit <= hiBit && "loBit greater than hiBit"); APInt Res(numBits, 0); Res.setBits(loBit, hiBit); return Res; } + /// Wrap version of getBitsSet. + /// If \p hiBit is no less than \p loBit, this is same with getBitsSet. + /// If \p hiBit is less than \p loBit, the set bits "wrap". For example, with + /// parameters (32, 28, 4), you would get 0xF000000F. + static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, + unsigned hiBit) { + APInt Res(numBits, 0); + Res.setBitsWithWrap(loBit, hiBit); + return Res; + } + /// Get a value with upper bits starting at loBit set. /// /// Constructs an APInt value that has a contiguous range of bits set. The @@ -1431,6 +1443,21 @@ } /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1. + /// This function handles "wrap" case when \p loBit > \p hiBit, and calls + /// setBits when \p loBit <= \p hiBit. + void setBitsWithWrap(unsigned loBit, unsigned hiBit) { + assert(hiBit <= BitWidth && "hiBit out of range"); + assert(loBit <= BitWidth && "loBit out of range"); + if (loBit <= hiBit) { + setBits(loBit, hiBit); + return; + } + setLowBits(hiBit); + setHighBits(BitWidth - loBit); + } + + /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1. + /// This function handles case when \p loBit <= \p hiBit. void setBits(unsigned loBit, unsigned hiBit) { assert(hiBit <= BitWidth && "hiBit out of range"); assert(loBit <= BitWidth && "loBit out of range"); diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -2046,6 +2046,40 @@ EXPECT_EQ(125u, i127hi1lo1.countPopulation()); } +TEST(APIntTest, getBitsSetWithWrap) { + APInt i64hi1lo1 = APInt::getBitsSetWithWrap(64, 1, 63); + EXPECT_EQ(0u, i64hi1lo1.countLeadingOnes()); + EXPECT_EQ(1u, i64hi1lo1.countLeadingZeros()); + EXPECT_EQ(63u, i64hi1lo1.getActiveBits()); + EXPECT_EQ(1u, i64hi1lo1.countTrailingZeros()); + EXPECT_EQ(0u, i64hi1lo1.countTrailingOnes()); + EXPECT_EQ(62u, i64hi1lo1.countPopulation()); + + APInt i127hi1lo1 = APInt::getBitsSetWithWrap(127, 1, 126); + EXPECT_EQ(0u, i127hi1lo1.countLeadingOnes()); + EXPECT_EQ(1u, i127hi1lo1.countLeadingZeros()); + EXPECT_EQ(126u, i127hi1lo1.getActiveBits()); + EXPECT_EQ(1u, i127hi1lo1.countTrailingZeros()); + EXPECT_EQ(0u, i127hi1lo1.countTrailingOnes()); + EXPECT_EQ(125u, i127hi1lo1.countPopulation()); + + APInt i64hi1lo1wrap = APInt::getBitsSetWithWrap(64, 63, 1); + EXPECT_EQ(1u, i64hi1lo1wrap.countLeadingOnes()); + EXPECT_EQ(0u, i64hi1lo1wrap.countLeadingZeros()); + EXPECT_EQ(64u, i64hi1lo1wrap.getActiveBits()); + EXPECT_EQ(0u, i64hi1lo1wrap.countTrailingZeros()); + EXPECT_EQ(1u, i64hi1lo1wrap.countTrailingOnes()); + EXPECT_EQ(2u, i64hi1lo1wrap.countPopulation()); + + APInt i127hi1lo1wrap = APInt::getBitsSetWithWrap(127, 126, 1); + EXPECT_EQ(1u, i127hi1lo1wrap.countLeadingOnes()); + EXPECT_EQ(0u, i127hi1lo1wrap.countLeadingZeros()); + EXPECT_EQ(127u, i127hi1lo1wrap.getActiveBits()); + EXPECT_EQ(0u, i127hi1lo1wrap.countTrailingZeros()); + EXPECT_EQ(1u, i127hi1lo1wrap.countTrailingOnes()); + EXPECT_EQ(2u, i127hi1lo1wrap.countPopulation()); +} + TEST(APIntTest, getHighBitsSet) { APInt i64hi32 = APInt::getHighBitsSet(64, 32); EXPECT_EQ(32u, i64hi32.countLeadingOnes());