[PATCH] D67043: [Support] Generic wrapper over __builtin_clz with cross-platform fallback

Nandor Licker via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 31 13:42:19 PDT 2019


nand created this revision.
nand added reviewers: Bigcheese, jfb, dexonsmith.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
nand edited the summary of this revision.

Added CountLeadingZeros<T> for signed and unsigned types to count the number
of leading zeros. On platforms with ``__builtin_clz``, the builtin is used, otherwise
a generic fallback is provided. Unlike ``__builtin_clz``, the method returns the
bit width of the type  for 0.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67043

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
@@ -595,4 +595,52 @@
   EXPECT_EQ(Result, TypeParam(0));
 }
 
+template <typename T>
+class CLZSignedTest : public ::testing::Test { };
+
+using CLZSignedTestTypes = ::testing::Types<int8_t, int16_t, int32_t, int64_t>;
+
+TYPED_TEST_CASE(CLZSignedTest, CLZSignedTestTypes);
+
+TYPED_TEST(CLZSignedTest, Zero)  {
+  EXPECT_EQ(sizeof(TypeParam) * CHAR_BIT, CountLeadingZeros<TypeParam>(0));
+}
+
+TYPED_TEST(CLZSignedTest, MinusOne)  {
+  EXPECT_EQ(0u, CountLeadingZeros(TypeParam(-1)));
+}
+
+TYPED_TEST(CLZSignedTest, Max) {
+  constexpr TypeParam MaxValue = std::numeric_limits<TypeParam>::max();
+  EXPECT_EQ(1u, CountLeadingZeros<TypeParam>(MaxValue));
+}
+
+template <typename T>
+class CLZUnsignedTest : public ::testing::Test { };
+
+using CLZUnsignedTestTypes = ::testing::Types<uint8_t, uint16_t, uint32_t,
+                                              uint64_t>;
+
+TYPED_TEST_CASE(CLZUnsignedTest, CLZUnsignedTestTypes);
+
+TYPED_TEST(CLZUnsignedTest, Zero)  {
+  EXPECT_EQ(sizeof(TypeParam) * CHAR_BIT, CountLeadingZeros<TypeParam>(0));
+}
+
+TYPED_TEST(CLZUnsignedTest, Max) {
+  constexpr TypeParam MaxValue = std::numeric_limits<TypeParam>::max();
+  EXPECT_EQ(0u, CountLeadingZeros<TypeParam>(MaxValue));
+}
+
+TEST(CLZSingleTest, CountLeadingZeros) {
+  EXPECT_EQ(1u, CountLeadingZeros<uint8_t>(127));
+  EXPECT_EQ(2u, CountLeadingZeros<uint8_t>(63));
+  EXPECT_EQ(9u, CountLeadingZeros<uint16_t>(127));
+  EXPECT_EQ(10u, CountLeadingZeros<uint16_t>(63));
+  EXPECT_EQ(25u, CountLeadingZeros<uint32_t>(127));
+  EXPECT_EQ(26u, CountLeadingZeros<uint32_t>(63));
+  EXPECT_EQ(57u, CountLeadingZeros<uint64_t>(127));
+  EXPECT_EQ(58u, CountLeadingZeros<uint64_t>(63));
+}
+
 } // namespace
Index: llvm/include/llvm/Support/MathExtras.h
===================================================================
--- llvm/include/llvm/Support/MathExtras.h
+++ llvm/include/llvm/Support/MathExtras.h
@@ -929,6 +929,34 @@
 #endif
 }
 
+/// Returns the number of leading zeros. The number of leading zeros of 0 is
+/// the number of bits in of the underlying type.
+template <typename T>
+typename std::enable_if<std::is_unsigned<T>::value, unsigned>::type
+CountLeadingZeros(T V) {
+  constexpr unsigned BitWidth = sizeof(T) * CHAR_BIT;
+#if __has_builtin(__builtin_clzll)
+  if (!V)
+    return BitWidth;
+  unsigned LeadingZeros = __builtin_clzll(V);
+  constexpr auto FullBits = std::numeric_limits<unsigned long long>::digits;
+  return LeadingZeros - (FullBits - BitWidth);
+#else
+  for (unsigned I = 0; I < BitWidth; ++I) {
+    if (V & (T(1) << T(BitWidth - I - 1)))
+      return I;
+  }
+  return BitWidth;
+#endif
+}
+
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, unsigned>::type
+CountLeadingZeros(T Value) {
+    using U = typename std::make_unsigned<T>::type;
+    return Value < 0  ? 0 : CountLeadingZeros(static_cast<U>(Value));
+}
+
 } // End llvm namespace
 
 #endif


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D67043.218235.patch
Type: text/x-patch
Size: 3126 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190831/d25c46c1/attachment.bin>


More information about the llvm-commits mailing list