From: Craig Topper Date: Tue, 7 Mar 2017 02:19:45 +0000 (+0000) Subject: [APInt] Implement getLowBitsSet/getHighBitsSet/getBitsSet using setLowBits/setHighBit... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1f41782fb2b2948bfa9dd0a17b4cab5c812299a7;p=llvm [APInt] Implement getLowBitsSet/getHighBitsSet/getBitsSet using setLowBits/setHighBits/setBits This patch implements getLowBitsSet/getHighBitsSet/getBitsSet in terms of the new setLowBits/setHighBits/setBits methods by making an all 0s APInt and then calling the appropriate set method. This also adds support to setBits to allow loBits/hiBits to be in the other order to match with getBitsSet behavior. Differential Revision: https://reviews.llvm.org/D30563 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297112 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index cd9b420becc..af81d0bf418 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -505,12 +505,9 @@ public: /// /// \returns An APInt value with the requested bits set. static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) { - assert(hiBit <= numBits && "hiBit out of range"); - assert(loBit < numBits && "loBit out of range"); - if (hiBit < loBit) - return getLowBitsSet(numBits, hiBit) | - getHighBitsSet(numBits, numBits - loBit); - return getLowBitsSet(numBits, hiBit - loBit).shl(loBit); + APInt Res(numBits, 0); + Res.setBits(loBit, hiBit); + return Res; } /// \brief Get a value with high bits set @@ -520,15 +517,9 @@ public: /// \param numBits the bitwidth of the result /// \param hiBitsSet the number of high-order bits set in the result. static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) { - assert(hiBitsSet <= numBits && "Too many bits to set!"); - // Handle a degenerate case, to avoid shifting by word size - if (hiBitsSet == 0) - return APInt(numBits, 0); - unsigned shiftAmt = numBits - hiBitsSet; - // For small values, return quickly - if (numBits <= APINT_BITS_PER_WORD) - return APInt(numBits, UINT64_MAX << shiftAmt); - return getAllOnesValue(numBits).shl(shiftAmt); + APInt Res(numBits, 0); + Res.setHighBits(hiBitsSet); + return Res; } /// \brief Get a value with low bits set @@ -538,14 +529,9 @@ public: /// \param numBits the bitwidth of the result /// \param loBitsSet the number of low-order bits set in the result. static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) { - assert(loBitsSet <= numBits && "Too many bits to set!"); - // Handle a degenerate case, to avoid shifting by word size - if (loBitsSet == 0) - return APInt(numBits, 0); - // For small values, return quickly. - if (loBitsSet <= APINT_BITS_PER_WORD) - return APInt(numBits, UINT64_MAX >> (APINT_BITS_PER_WORD - loBitsSet)); - return getAllOnesValue(numBits).lshr(numBits - loBitsSet); + APInt Res(numBits, 0); + Res.setLowBits(loBitsSet); + return Res; } /// \brief Return a value containing V broadcasted over NewLen bits. @@ -1216,9 +1202,14 @@ public: /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1. void setBits(unsigned loBit, unsigned hiBit) { assert(hiBit <= BitWidth && "hiBit out of range"); - assert(loBit <= hiBit && "loBit out of range"); + assert(loBit <= BitWidth && "loBit out of range"); if (loBit == hiBit) return; + if (loBit > hiBit) { + setLowBits(hiBit); + setHighBits(BitWidth - loBit); + return; + } if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) { uint64_t mask = UINT64_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit)); mask <<= loBit; diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 8a9c4ebc9c7..ad0cf42fb31 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -1557,6 +1557,24 @@ TEST(APIntTest, getLowBitsSet) { } TEST(APIntTest, getHighBitsSet) { + APInt i64hi1lo1 = APInt::getBitsSet(64, 63, 1); + EXPECT_EQ(1u, i64hi1lo1.countLeadingOnes()); + EXPECT_EQ(0u, i64hi1lo1.countLeadingZeros()); + EXPECT_EQ(64u, i64hi1lo1.getActiveBits()); + EXPECT_EQ(0u, i64hi1lo1.countTrailingZeros()); + EXPECT_EQ(1u, i64hi1lo1.countTrailingOnes()); + EXPECT_EQ(2u, i64hi1lo1.countPopulation()); + + APInt i127hi1lo1 = APInt::getBitsSet(127, 126, 1); + EXPECT_EQ(1u, i127hi1lo1.countLeadingOnes()); + EXPECT_EQ(0u, i127hi1lo1.countLeadingZeros()); + EXPECT_EQ(127u, i127hi1lo1.getActiveBits()); + EXPECT_EQ(0u, i127hi1lo1.countTrailingZeros()); + EXPECT_EQ(1u, i127hi1lo1.countTrailingOnes()); + EXPECT_EQ(2u, i127hi1lo1.countPopulation()); +} + +TEST(APIntTest, getBitsSet) { APInt i64hi32 = APInt::getHighBitsSet(64, 32); EXPECT_EQ(32u, i64hi32.countLeadingOnes()); EXPECT_EQ(0u, i64hi32.countLeadingZeros());