[PATCH] D32212: Create some helpers for generating bit masks

Zachary Turner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 18 20:49:16 PDT 2017


zturner created this revision.

Often you want a bit-mask with the first N bits or the last N bits set to 1.  This is surprisingly confusing to get right, in part because X << (8*sizeof(X)) is undefined, so trying to produce a mask of all 1s won't work, and also in part because the branch-free implementation is not obvious.


https://reviews.llvm.org/D32212

Files:
  llvm/include/llvm/Support/MathExtras.h
  llvm/unittests/Support/MathExtrasTest.cpp


Index: llvm/unittests/Support/MathExtrasTest.cpp
===================================================================
--- llvm/unittests/Support/MathExtrasTest.cpp
+++ llvm/unittests/Support/MathExtrasTest.cpp
@@ -66,6 +66,26 @@
   }
 }
 
+TEST(MathExtras, onesMask) {
+  EXPECT_EQ(0U, maskLeadingOnes<uint8_t>(0));
+  EXPECT_EQ(0U, maskTrailingOnes<uint8_t>(0));
+  EXPECT_EQ(0U, maskLeadingOnes<uint16_t>(0));
+  EXPECT_EQ(0U, maskTrailingOnes<uint16_t>(0));
+  EXPECT_EQ(0U, maskLeadingOnes<uint32_t>(0));
+  EXPECT_EQ(0U, maskTrailingOnes<uint32_t>(0));
+  EXPECT_EQ(0U, maskLeadingOnes<uint64_t>(0));
+  EXPECT_EQ(0U, maskTrailingOnes<uint64_t>(0));
+
+  EXPECT_EQ(0x00000003, maskTrailingOnes<uint32_t>(2U));
+  EXPECT_EQ(0xC0000000, maskLeadingOnes<uint32_t>(2U));
+
+  EXPECT_EQ(0x000007FF, maskTrailingOnes<uint32_t>(11U));
+  EXPECT_EQ(0xFFE00000, maskLeadingOnes<uint32_t>(11U));
+
+  EXPECT_EQ(0xFFFFFFFF, maskTrailingOnes<uint32_t>(32U));
+  EXPECT_EQ(0xFFFFFFFF, maskLeadingOnes<uint32_t>(32U));
+}
+
 TEST(MathExtras, findFirstSet) {
   uint8_t Z8 = 0;
   uint16_t Z16 = 0;
Index: llvm/include/llvm/Support/MathExtras.h
===================================================================
--- llvm/include/llvm/Support/MathExtras.h
+++ llvm/include/llvm/Support/MathExtras.h
@@ -198,6 +198,21 @@
   return countTrailingZeros(Val, ZB_Undefined);
 }
 
+/// \brief Create a bitmask with the N right-most bits set to 1, and all other
+/// bits set to 0.  Only unsigned types are allowed.
+template <typename T> T maskTrailingOnes(unsigned N) {
+  static_assert(std::is_unsigned<T>::value, "Invalid type!");
+  const unsigned Bits = CHAR_BIT * sizeof(T);
+  assert(N <= Bits && "Invalid bit index");
+  return -T(N != 0) & (T(-1) >> (Bits - N));
+}
+
+/// \brief Create a bitmask with the N left-most bits set to 1, and all other
+/// bits set to 0.  Only unsigned types are allowed.
+template <typename T> T maskLeadingOnes(unsigned N) {
+  return ~maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N);
+}
+
 /// \brief Get the index of the last set bit starting from the least
 ///   significant bit.
 ///


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D32212.95683.patch
Type: text/x-patch
Size: 2109 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170419/d93f34e3/attachment.bin>


More information about the llvm-commits mailing list