Skip to content

Commit bafdd03

Browse files
committedMar 7, 2017
[APInt] Add setLowBits/setHighBits methods to APInt.
Summary: There are quite a few places in the code base that do something like the following to set the high or low bits in an APInt. KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - 1); For BitWidths larger than 64 this creates a short lived APInt with malloced storage. I think it might even call malloc twice. Its better to just provide methods that can set the necessary bits without the temporary APInt. I'll update usages that benefit in a separate patch. Reviewers: majnemer, MatzeB, davide, RKSimon, hans Reviewed By: hans Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D30525 llvm-svn: 297111
1 parent 00c7592 commit bafdd03

File tree

3 files changed

+173
-30
lines changed

3 files changed

+173
-30
lines changed
 

‎llvm/include/llvm/ADT/APInt.h

+29-1
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ class LLVM_NODISCARD APInt {
223223
/// out-of-line slow case for countPopulation
224224
unsigned countPopulationSlowCase() const;
225225

226+
/// out-of-line slow case for setBits.
227+
void setBitsSlowCase(unsigned loBit, unsigned hiBit);
228+
226229
public:
227230
/// \name Constructors
228231
/// @{
@@ -1211,7 +1214,32 @@ class LLVM_NODISCARD APInt {
12111214
void setBit(unsigned bitPosition);
12121215

12131216
/// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1.
1214-
void setBits(unsigned loBit, unsigned hiBit);
1217+
void setBits(unsigned loBit, unsigned hiBit) {
1218+
assert(hiBit <= BitWidth && "hiBit out of range");
1219+
assert(loBit <= hiBit && "loBit out of range");
1220+
if (loBit == hiBit)
1221+
return;
1222+
if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) {
1223+
uint64_t mask = UINT64_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit));
1224+
mask <<= loBit;
1225+
if (isSingleWord())
1226+
VAL |= mask;
1227+
else
1228+
pVal[0] |= mask;
1229+
} else {
1230+
setBitsSlowCase(loBit, hiBit);
1231+
}
1232+
}
1233+
1234+
/// Set the bottom loBits bits.
1235+
void setLowBits(unsigned loBits) {
1236+
return setBits(0, loBits);
1237+
}
1238+
1239+
/// Set the top hiBits bits.
1240+
void setHighBits(unsigned hiBits) {
1241+
return setBits(BitWidth - hiBits, BitWidth);
1242+
}
12151243

12161244
/// \brief Set every bit to 0.
12171245
void clearAllBits() {

‎llvm/lib/Support/APInt.cpp

+23-29
Original file line numberDiff line numberDiff line change
@@ -566,37 +566,31 @@ void APInt::setBit(unsigned bitPosition) {
566566
pVal[whichWord(bitPosition)] |= maskBit(bitPosition);
567567
}
568568

569-
void APInt::setBits(unsigned loBit, unsigned hiBit) {
570-
assert(hiBit <= BitWidth && "hiBit out of range");
571-
assert(loBit <= hiBit && loBit <= BitWidth && "loBit out of range");
572-
573-
if (loBit == hiBit)
574-
return;
575-
576-
if (isSingleWord())
577-
*this |= APInt::getBitsSet(BitWidth, loBit, hiBit);
578-
else {
579-
unsigned hiBit1 = hiBit - 1;
580-
unsigned loWord = whichWord(loBit);
581-
unsigned hiWord = whichWord(hiBit1);
582-
if (loWord == hiWord) {
583-
// Set bits are all within the same word, create a [loBit,hiBit) mask.
584-
uint64_t mask = UINT64_MAX;
585-
mask >>= (APINT_BITS_PER_WORD - (hiBit - loBit));
586-
mask <<= whichBit(loBit);
587-
pVal[loWord] |= mask;
588-
} else {
589-
// Set bits span multiple words, create a lo mask with set bits starting
590-
// at loBit, a hi mask with set bits below hiBit and set all bits of the
591-
// words in between.
592-
uint64_t loMask = UINT64_MAX << whichBit(loBit);
593-
uint64_t hiMask = UINT64_MAX >> (64 - whichBit(hiBit1) - 1);
594-
pVal[loWord] |= loMask;
569+
void APInt::setBitsSlowCase(unsigned loBit, unsigned hiBit) {
570+
unsigned loWord = whichWord(loBit);
571+
unsigned hiWord = whichWord(hiBit);
572+
573+
// Create an initial mask for the low word with zeroes below loBit.
574+
uint64_t loMask = UINT64_MAX << whichBit(loBit);
575+
576+
// If hiBit is not aligned, we need a high mask.
577+
unsigned hiShiftAmt = whichBit(hiBit);
578+
if (hiShiftAmt != 0) {
579+
// Create a high mask with zeros above hiBit.
580+
uint64_t hiMask = UINT64_MAX >> (APINT_BITS_PER_WORD - hiShiftAmt);
581+
// If loWord and hiWord are equal, then we combine the masks. Otherwise,
582+
// set the bits in hiWord.
583+
if (hiWord == loWord)
584+
loMask &= hiMask;
585+
else
595586
pVal[hiWord] |= hiMask;
596-
for (unsigned word = loWord + 1; word < hiWord; ++word)
597-
pVal[word] = UINT64_MAX;
598-
}
599587
}
588+
// Apply the mask to the low word.
589+
pVal[loWord] |= loMask;
590+
591+
// Fill any words between loWord and hiWord with all ones.
592+
for (unsigned word = loWord + 1; word < hiWord; ++word)
593+
pVal[word] = UINT64_MAX;
600594
}
601595

602596
/// Set the given bit to 0 whose position is given as "bitPosition".

‎llvm/unittests/ADT/APIntTest.cpp

+121
Original file line numberDiff line numberDiff line change
@@ -1565,3 +1565,124 @@ TEST(APIntTest, getHighBitsSet) {
15651565
EXPECT_EQ(0u, i64hi32.countTrailingOnes());
15661566
EXPECT_EQ(32u, i64hi32.countPopulation());
15671567
}
1568+
1569+
TEST(APIntTest, setLowBits) {
1570+
APInt i64lo32(64, 0);
1571+
i64lo32.setLowBits(32);
1572+
EXPECT_EQ(0u, i64lo32.countLeadingOnes());
1573+
EXPECT_EQ(32u, i64lo32.countLeadingZeros());
1574+
EXPECT_EQ(32u, i64lo32.getActiveBits());
1575+
EXPECT_EQ(0u, i64lo32.countTrailingZeros());
1576+
EXPECT_EQ(32u, i64lo32.countTrailingOnes());
1577+
EXPECT_EQ(32u, i64lo32.countPopulation());
1578+
1579+
APInt i128lo64(128, 0);
1580+
i128lo64.setLowBits(64);
1581+
EXPECT_EQ(0u, i128lo64.countLeadingOnes());
1582+
EXPECT_EQ(64u, i128lo64.countLeadingZeros());
1583+
EXPECT_EQ(64u, i128lo64.getActiveBits());
1584+
EXPECT_EQ(0u, i128lo64.countTrailingZeros());
1585+
EXPECT_EQ(64u, i128lo64.countTrailingOnes());
1586+
EXPECT_EQ(64u, i128lo64.countPopulation());
1587+
1588+
APInt i128lo24(128, 0);
1589+
i128lo24.setLowBits(24);
1590+
EXPECT_EQ(0u, i128lo24.countLeadingOnes());
1591+
EXPECT_EQ(104u, i128lo24.countLeadingZeros());
1592+
EXPECT_EQ(24u, i128lo24.getActiveBits());
1593+
EXPECT_EQ(0u, i128lo24.countTrailingZeros());
1594+
EXPECT_EQ(24u, i128lo24.countTrailingOnes());
1595+
EXPECT_EQ(24u, i128lo24.countPopulation());
1596+
1597+
APInt i128lo104(128, 0);
1598+
i128lo104.setLowBits(104);
1599+
EXPECT_EQ(0u, i128lo104.countLeadingOnes());
1600+
EXPECT_EQ(24u, i128lo104.countLeadingZeros());
1601+
EXPECT_EQ(104u, i128lo104.getActiveBits());
1602+
EXPECT_EQ(0u, i128lo104.countTrailingZeros());
1603+
EXPECT_EQ(104u, i128lo104.countTrailingOnes());
1604+
EXPECT_EQ(104u, i128lo104.countPopulation());
1605+
1606+
APInt i128lo0(128, 0);
1607+
i128lo0.setLowBits(0);
1608+
EXPECT_EQ(0u, i128lo0.countLeadingOnes());
1609+
EXPECT_EQ(128u, i128lo0.countLeadingZeros());
1610+
EXPECT_EQ(0u, i128lo0.getActiveBits());
1611+
EXPECT_EQ(128u, i128lo0.countTrailingZeros());
1612+
EXPECT_EQ(0u, i128lo0.countTrailingOnes());
1613+
EXPECT_EQ(0u, i128lo0.countPopulation());
1614+
1615+
APInt i80lo79(80, 0);
1616+
i80lo79.setLowBits(79);
1617+
EXPECT_EQ(0u, i80lo79.countLeadingOnes());
1618+
EXPECT_EQ(1u, i80lo79.countLeadingZeros());
1619+
EXPECT_EQ(79u, i80lo79.getActiveBits());
1620+
EXPECT_EQ(0u, i80lo79.countTrailingZeros());
1621+
EXPECT_EQ(79u, i80lo79.countTrailingOnes());
1622+
EXPECT_EQ(79u, i80lo79.countPopulation());
1623+
}
1624+
1625+
TEST(APIntTest, setHighBits) {
1626+
APInt i64hi32(64, 0);
1627+
i64hi32.setHighBits(32);
1628+
EXPECT_EQ(32u, i64hi32.countLeadingOnes());
1629+
EXPECT_EQ(0u, i64hi32.countLeadingZeros());
1630+
EXPECT_EQ(64u, i64hi32.getActiveBits());
1631+
EXPECT_EQ(32u, i64hi32.countTrailingZeros());
1632+
EXPECT_EQ(0u, i64hi32.countTrailingOnes());
1633+
EXPECT_EQ(32u, i64hi32.countPopulation());
1634+
1635+
APInt i128hi64(128, 0);
1636+
i128hi64.setHighBits(64);
1637+
EXPECT_EQ(64u, i128hi64.countLeadingOnes());
1638+
EXPECT_EQ(0u, i128hi64.countLeadingZeros());
1639+
EXPECT_EQ(128u, i128hi64.getActiveBits());
1640+
EXPECT_EQ(64u, i128hi64.countTrailingZeros());
1641+
EXPECT_EQ(0u, i128hi64.countTrailingOnes());
1642+
EXPECT_EQ(64u, i128hi64.countPopulation());
1643+
1644+
APInt i128hi24(128, 0);
1645+
i128hi24.setHighBits(24);
1646+
EXPECT_EQ(24u, i128hi24.countLeadingOnes());
1647+
EXPECT_EQ(0u, i128hi24.countLeadingZeros());
1648+
EXPECT_EQ(128u, i128hi24.getActiveBits());
1649+
EXPECT_EQ(104u, i128hi24.countTrailingZeros());
1650+
EXPECT_EQ(0u, i128hi24.countTrailingOnes());
1651+
EXPECT_EQ(24u, i128hi24.countPopulation());
1652+
1653+
APInt i128hi104(128, 0);
1654+
i128hi104.setHighBits(104);
1655+
EXPECT_EQ(104u, i128hi104.countLeadingOnes());
1656+
EXPECT_EQ(0u, i128hi104.countLeadingZeros());
1657+
EXPECT_EQ(128u, i128hi104.getActiveBits());
1658+
EXPECT_EQ(24u, i128hi104.countTrailingZeros());
1659+
EXPECT_EQ(0u, i128hi104.countTrailingOnes());
1660+
EXPECT_EQ(104u, i128hi104.countPopulation());
1661+
1662+
APInt i128hi0(128, 0);
1663+
i128hi0.setHighBits(0);
1664+
EXPECT_EQ(0u, i128hi0.countLeadingOnes());
1665+
EXPECT_EQ(128u, i128hi0.countLeadingZeros());
1666+
EXPECT_EQ(0u, i128hi0.getActiveBits());
1667+
EXPECT_EQ(128u, i128hi0.countTrailingZeros());
1668+
EXPECT_EQ(0u, i128hi0.countTrailingOnes());
1669+
EXPECT_EQ(0u, i128hi0.countPopulation());
1670+
1671+
APInt i80hi1(80, 0);
1672+
i80hi1.setHighBits(1);
1673+
EXPECT_EQ(1u, i80hi1.countLeadingOnes());
1674+
EXPECT_EQ(0u, i80hi1.countLeadingZeros());
1675+
EXPECT_EQ(80u, i80hi1.getActiveBits());
1676+
EXPECT_EQ(79u, i80hi1.countTrailingZeros());
1677+
EXPECT_EQ(0u, i80hi1.countTrailingOnes());
1678+
EXPECT_EQ(1u, i80hi1.countPopulation());
1679+
1680+
APInt i32hi16(32, 0);
1681+
i32hi16.setHighBits(16);
1682+
EXPECT_EQ(16u, i32hi16.countLeadingOnes());
1683+
EXPECT_EQ(0u, i32hi16.countLeadingZeros());
1684+
EXPECT_EQ(32u, i32hi16.getActiveBits());
1685+
EXPECT_EQ(16u, i32hi16.countTrailingZeros());
1686+
EXPECT_EQ(0u, i32hi16.countTrailingOnes());
1687+
EXPECT_EQ(16u, i32hi16.countPopulation());
1688+
}

0 commit comments

Comments
 (0)
Please sign in to comment.