-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc][support][UInt] implement 128b math helpers #86531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
We could have used this in the implementation of UInt::has_single_bit, but has_single_bit has a perhaps useful early return.
@llvm/pr-subscribers-libc Author: Nick Desaulniers (nickdesaulniers) ChangesWe could have used this in the implementation of UInt::has_single_bit, but Full diff: https://github.com/llvm/llvm-project/pull/86531.diff 2 Files Affected:
diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h
index df01e081e3c19e..b04e8d02ad4c16 100644
--- a/libc/src/__support/UInt.h
+++ b/libc/src/__support/UInt.h
@@ -1082,6 +1082,17 @@ bit_cast(const UInt<Bits> &from) {
return cpp::bit_cast<To>(from.val);
}
+// Specialization of cpp::popcount ('bit.h') for BigInt.
+template <typename T>
+[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
+popcount(T value) {
+ int bits = 0;
+ for (auto word : value.val)
+ if (word)
+ bits += popcount(word);
+ return bits;
+}
+
// Specialization of cpp::has_single_bit ('bit.h') for BigInt.
template <typename T>
[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, bool>
diff --git a/libc/test/src/__support/CPP/bit_test.cpp b/libc/test/src/__support/CPP/bit_test.cpp
index cee5b90c8f4bdb..875b47e6a1980e 100644
--- a/libc/test/src/__support/CPP/bit_test.cpp
+++ b/libc/test/src/__support/CPP/bit_test.cpp
@@ -15,13 +15,6 @@
namespace LIBC_NAMESPACE::cpp {
-using UnsignedTypesNoBigInt = testing::TypeList<
-#if defined(LIBC_TYPES_HAS_INT128)
- __uint128_t,
-#endif // LIBC_TYPES_HAS_INT128
- unsigned char, unsigned short, unsigned int, unsigned long,
- unsigned long long>;
-
using UnsignedTypes = testing::TypeList<
#if defined(LIBC_TYPES_HAS_INT128)
__uint128_t,
@@ -228,7 +221,7 @@ TEST(LlvmLibcBitTest, Rotr) {
rotr<uint64_t>(0x12345678deadbeefULL, -19));
}
-TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypesNoBigInt) {
+TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypes) {
EXPECT_EQ(popcount(T(0)), 0);
for (int i = 0; i != cpp::numeric_limits<T>::digits; ++i)
EXPECT_EQ(popcount<T>(cpp::numeric_limits<T>::max() >> i),
|
✅ With the latest revision this PR passed the Python code formatter. |
✅ With the latest revision this PR passed the C/C++ code formatter. |
Ah, I should fix up the math_extras, too. |
fixed in 457a41d, PTAL |
hmm...I'm on the fence about removing this TODO. llvm-project/libc/src/__support/CPP/bit.h Line 264 in 5ef0954
On one hand, we now have Actually, I'll add it to this PR. |
Done in b1e40ed PTAL |
cc @overmighty |
@@ -242,6 +242,14 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) { | |||
/// Count number of 1's aka population count or Hamming weight. | |||
/// | |||
/// Only unsigned integral types are allowed. | |||
// clang-19+, gcc-14+ | |||
#if __has_builtin(__builtin_popcountg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, should this be using LIBC_HAS_BUILTIN
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gcc-10+ supports __has_builtin
. While wrapping the use of __has_builtin
used to be necessary to support older compilers, this is no longer necessary since we only support gcc-12+ . https://libc.llvm.org/compiler_support.html I'll leave this out, and file a bug about removing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed #86546
Flush out the remaining UInt<128> support and add test coverage.
We could have used cpp::popcount in the implementation of UInt::has_single_bit, but
has_single_bit has a perhaps useful early return.