Skip to content

[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

Merged
merged 3 commits into from
Mar 27, 2024

Conversation

nickdesaulniers
Copy link
Member

@nickdesaulniers nickdesaulniers commented Mar 25, 2024

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.

We could have used this in the implementation of UInt::has_single_bit, but
has_single_bit has a perhaps useful early return.
@llvmbot
Copy link
Member

llvmbot commented Mar 25, 2024

@llvm/pr-subscribers-libc

Author: Nick Desaulniers (nickdesaulniers)

Changes

We could have used this in the implementation of UInt::has_single_bit, but
has_single_bit has a perhaps useful early return.


Full diff: https://github.com/llvm/llvm-project/pull/86531.diff

2 Files Affected:

  • (modified) libc/src/__support/UInt.h (+11)
  • (modified) libc/test/src/__support/CPP/bit_test.cpp (+1-8)
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),

Copy link

✅ With the latest revision this PR passed the Python code formatter.

Copy link

✅ With the latest revision this PR passed the C/C++ code formatter.

@nickdesaulniers
Copy link
Member Author

Ah, I should fix up the math_extras, too.

@nickdesaulniers nickdesaulniers marked this pull request as draft March 25, 2024 17:00
@nickdesaulniers nickdesaulniers marked this pull request as ready for review March 25, 2024 17:09
@nickdesaulniers
Copy link
Member Author

Ah, I should fix up the math_extras, too.

fixed in 457a41d, PTAL

@nickdesaulniers nickdesaulniers changed the title [libc][support][UInt] implement 128b popcount [libc][support][UInt] implement 128b math helpers Mar 25, 2024
@nickdesaulniers
Copy link
Member Author

hmm...I'm on the fence about removing this TODO.

// TODO: 128b specializations?

On one hand, we now have __builtin_popcountg in nascent versions of clang and GCC. We'd need a __has_builtin guard for these.

Actually, I'll add it to this PR.

@nickdesaulniers nickdesaulniers marked this pull request as draft March 25, 2024 17:15
@nickdesaulniers
Copy link
Member Author

hmm...I'm on the fence about removing this TODO.

// TODO: 128b specializations?

On one hand, we now have __builtin_popcountg in nascent versions of clang and GCC. We'd need a __has_builtin guard for these.

Actually, I'll add it to this PR.

Done in b1e40ed PTAL

@nickdesaulniers nickdesaulniers marked this pull request as ready for review March 25, 2024 17:34
@nickdesaulniers
Copy link
Member Author

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)
Copy link
Member Author

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?

Copy link
Member Author

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed #86546

@nickdesaulniers nickdesaulniers merged commit 51f7b26 into llvm:main Mar 27, 2024
@nickdesaulniers nickdesaulniers deleted the int128 branch March 27, 2024 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants