[llvm] fd03be3 - [APInt] add wrap support for `setBits` and `getBitsSet`
via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 19 00:58:08 PST 2019
Author: czhengsz
Date: 2019-11-19T03:57:48-05:00
New Revision: fd03be363421fa65cbe5447eef489a67517e9083
URL: https://github.com/llvm/llvm-project/commit/fd03be363421fa65cbe5447eef489a67517e9083
DIFF: https://github.com/llvm/llvm-project/commit/fd03be363421fa65cbe5447eef489a67517e9083.diff
LOG: [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
Added:
Modified:
llvm/include/llvm/ADT/APInt.h
llvm/unittests/ADT/APIntTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index 60a0db7e9898..796110f753bc 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -595,8 +595,8 @@ class LLVM_NODISCARD APInt {
/// 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 @@ class LLVM_NODISCARD APInt {
///
/// \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 @@ class LLVM_NODISCARD APInt {
}
/// 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
index 030b000c2588..2a3abbfaf164 100644
--- a/llvm/unittests/ADT/APIntTest.cpp
+++ b/llvm/unittests/ADT/APIntTest.cpp
@@ -2046,6 +2046,40 @@ TEST(APIntTest, getBitsSet) {
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());
More information about the llvm-commits
mailing list