[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