diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h --- a/llvm/include/llvm/Support/MathExtras.h +++ b/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 std::enable_if::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::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 std::enable_if::value, unsigned>::type +CountLeadingZeros(T Value) { + using U = typename std::make_unsigned::type; + return Value < 0 ? 0 : CountLeadingZeros(static_cast(Value)); +} + } // End llvm namespace #endif diff --git a/llvm/unittests/Support/MathExtrasTest.cpp b/llvm/unittests/Support/MathExtrasTest.cpp --- a/llvm/unittests/Support/MathExtrasTest.cpp +++ b/llvm/unittests/Support/MathExtrasTest.cpp @@ -595,4 +595,52 @@ EXPECT_EQ(Result, TypeParam(0)); } +template +class CLZSignedTest : public ::testing::Test { }; + +using CLZSignedTestTypes = ::testing::Types; + +TYPED_TEST_CASE(CLZSignedTest, CLZSignedTestTypes); + +TYPED_TEST(CLZSignedTest, Zero) { + EXPECT_EQ(sizeof(TypeParam) * CHAR_BIT, CountLeadingZeros(0)); +} + +TYPED_TEST(CLZSignedTest, MinusOne) { + EXPECT_EQ(0u, CountLeadingZeros(TypeParam(-1))); +} + +TYPED_TEST(CLZSignedTest, Max) { + constexpr TypeParam MaxValue = std::numeric_limits::max(); + EXPECT_EQ(1u, CountLeadingZeros(MaxValue)); +} + +template +class CLZUnsignedTest : public ::testing::Test { }; + +using CLZUnsignedTestTypes = ::testing::Types; + +TYPED_TEST_CASE(CLZUnsignedTest, CLZUnsignedTestTypes); + +TYPED_TEST(CLZUnsignedTest, Zero) { + EXPECT_EQ(sizeof(TypeParam) * CHAR_BIT, CountLeadingZeros(0)); +} + +TYPED_TEST(CLZUnsignedTest, Max) { + constexpr TypeParam MaxValue = std::numeric_limits::max(); + EXPECT_EQ(0u, CountLeadingZeros(MaxValue)); +} + +TEST(CLZSingleTest, CountLeadingZeros) { + EXPECT_EQ(1u, CountLeadingZeros(127)); + EXPECT_EQ(2u, CountLeadingZeros(63)); + EXPECT_EQ(9u, CountLeadingZeros(127)); + EXPECT_EQ(10u, CountLeadingZeros(63)); + EXPECT_EQ(25u, CountLeadingZeros(127)); + EXPECT_EQ(26u, CountLeadingZeros(63)); + EXPECT_EQ(57u, CountLeadingZeros(127)); + EXPECT_EQ(58u, CountLeadingZeros(63)); +} + } // namespace