Skip to content

Commit fd03be3

Browse files
author
czhengsz
committed
[APInt] add wrap support for setBits and getBitsSet
Add two new interfaces getBitsSet and getBitsSetWithWrap Reviewed by: lebedev.ri, craig.topper Differential Revision: https://reviews.llvm.org/D69032
1 parent d43913a commit fd03be3

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

llvm/include/llvm/ADT/APInt.h

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,20 +595,32 @@ class LLVM_NODISCARD APInt {
595595
/// Constructs an APInt value that has a contiguous range of bits set. The
596596
/// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other
597597
/// bits will be zero. For example, with parameters(32, 0, 16) you would get
598-
/// 0x0000FFFF. If hiBit is less than loBit then the set bits "wrap". For
599-
/// example, with parameters (32, 28, 4), you would get 0xF000000F.
598+
/// 0x0000FFFF. Please call getBitsSetWithWrap if \p loBit may be greater than
599+
/// \p hiBit.
600600
///
601601
/// \param numBits the intended bit width of the result
602602
/// \param loBit the index of the lowest bit set.
603603
/// \param hiBit the index of the highest bit set.
604604
///
605605
/// \returns An APInt value with the requested bits set.
606606
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) {
607+
assert(loBit <= hiBit && "loBit greater than hiBit");
607608
APInt Res(numBits, 0);
608609
Res.setBits(loBit, hiBit);
609610
return Res;
610611
}
611612

613+
/// Wrap version of getBitsSet.
614+
/// If \p hiBit is no less than \p loBit, this is same with getBitsSet.
615+
/// If \p hiBit is less than \p loBit, the set bits "wrap". For example, with
616+
/// parameters (32, 28, 4), you would get 0xF000000F.
617+
static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit,
618+
unsigned hiBit) {
619+
APInt Res(numBits, 0);
620+
Res.setBitsWithWrap(loBit, hiBit);
621+
return Res;
622+
}
623+
612624
/// Get a value with upper bits starting at loBit set.
613625
///
614626
/// Constructs an APInt value that has a contiguous range of bits set. The
@@ -1431,6 +1443,21 @@ class LLVM_NODISCARD APInt {
14311443
}
14321444

14331445
/// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1.
1446+
/// This function handles "wrap" case when \p loBit > \p hiBit, and calls
1447+
/// setBits when \p loBit <= \p hiBit.
1448+
void setBitsWithWrap(unsigned loBit, unsigned hiBit) {
1449+
assert(hiBit <= BitWidth && "hiBit out of range");
1450+
assert(loBit <= BitWidth && "loBit out of range");
1451+
if (loBit <= hiBit) {
1452+
setBits(loBit, hiBit);
1453+
return;
1454+
}
1455+
setLowBits(hiBit);
1456+
setHighBits(BitWidth - loBit);
1457+
}
1458+
1459+
/// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1.
1460+
/// This function handles case when \p loBit <= \p hiBit.
14341461
void setBits(unsigned loBit, unsigned hiBit) {
14351462
assert(hiBit <= BitWidth && "hiBit out of range");
14361463
assert(loBit <= BitWidth && "loBit out of range");

llvm/unittests/ADT/APIntTest.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,6 +2046,40 @@ TEST(APIntTest, getBitsSet) {
20462046
EXPECT_EQ(125u, i127hi1lo1.countPopulation());
20472047
}
20482048

2049+
TEST(APIntTest, getBitsSetWithWrap) {
2050+
APInt i64hi1lo1 = APInt::getBitsSetWithWrap(64, 1, 63);
2051+
EXPECT_EQ(0u, i64hi1lo1.countLeadingOnes());
2052+
EXPECT_EQ(1u, i64hi1lo1.countLeadingZeros());
2053+
EXPECT_EQ(63u, i64hi1lo1.getActiveBits());
2054+
EXPECT_EQ(1u, i64hi1lo1.countTrailingZeros());
2055+
EXPECT_EQ(0u, i64hi1lo1.countTrailingOnes());
2056+
EXPECT_EQ(62u, i64hi1lo1.countPopulation());
2057+
2058+
APInt i127hi1lo1 = APInt::getBitsSetWithWrap(127, 1, 126);
2059+
EXPECT_EQ(0u, i127hi1lo1.countLeadingOnes());
2060+
EXPECT_EQ(1u, i127hi1lo1.countLeadingZeros());
2061+
EXPECT_EQ(126u, i127hi1lo1.getActiveBits());
2062+
EXPECT_EQ(1u, i127hi1lo1.countTrailingZeros());
2063+
EXPECT_EQ(0u, i127hi1lo1.countTrailingOnes());
2064+
EXPECT_EQ(125u, i127hi1lo1.countPopulation());
2065+
2066+
APInt i64hi1lo1wrap = APInt::getBitsSetWithWrap(64, 63, 1);
2067+
EXPECT_EQ(1u, i64hi1lo1wrap.countLeadingOnes());
2068+
EXPECT_EQ(0u, i64hi1lo1wrap.countLeadingZeros());
2069+
EXPECT_EQ(64u, i64hi1lo1wrap.getActiveBits());
2070+
EXPECT_EQ(0u, i64hi1lo1wrap.countTrailingZeros());
2071+
EXPECT_EQ(1u, i64hi1lo1wrap.countTrailingOnes());
2072+
EXPECT_EQ(2u, i64hi1lo1wrap.countPopulation());
2073+
2074+
APInt i127hi1lo1wrap = APInt::getBitsSetWithWrap(127, 126, 1);
2075+
EXPECT_EQ(1u, i127hi1lo1wrap.countLeadingOnes());
2076+
EXPECT_EQ(0u, i127hi1lo1wrap.countLeadingZeros());
2077+
EXPECT_EQ(127u, i127hi1lo1wrap.getActiveBits());
2078+
EXPECT_EQ(0u, i127hi1lo1wrap.countTrailingZeros());
2079+
EXPECT_EQ(1u, i127hi1lo1wrap.countTrailingOnes());
2080+
EXPECT_EQ(2u, i127hi1lo1wrap.countPopulation());
2081+
}
2082+
20492083
TEST(APIntTest, getHighBitsSet) {
20502084
APInt i64hi32 = APInt::getHighBitsSet(64, 32);
20512085
EXPECT_EQ(32u, i64hi32.countLeadingOnes());

0 commit comments

Comments
 (0)