Hi,

Now that we have stdbit.h I think that it would be nice to reduce the
duplication in all the bit operation modules.

Is there any reason not to use stdbit.h for ffs, ffsl, ffsll,
count-leading-zeros, count-one-bits, count-trailing-zeros?

I've attached an unpushed patch for count-one-bits and can do the rest
if there isn't any disagreement.

Collin

>From abacaf822fe21d1acfc766b33fa1ba06867c39c6 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Tue, 17 Dec 2024 12:34:40 -0800
Subject: [PATCH] count-one-bits: Implement using stdbit.h.

* lib/count-one-bits.h: Include stdbit.h.
(COUNT_ONE_BITS): Remove definition.
(COUNT_ONE_BITS_GENERIC): Likewise.
(count_one_bits_32): Remove function.
(__cpuid, __popcnt, __popcnt64, popcount_support, popcount_supported)
[_MSC_VER]: Remove declarations.
(__popcnt64) [_MSC_VER && !_M_X64]: Remove function.
(count_one_bits): Use stdc_count_ones_ui.
(count_one_bits_l): Use stdc_count_ones_ul.
(count_one_bits_ll): stdc_count_ones_ull.
* lib/count-one-bits.c (popcount_support) [_MSC_VER]: Remove variable.
* modules/count-one-bits (Depends-on): Add stdc_count_ones.
---
 ChangeLog              |  16 ++++++
 lib/count-one-bits.c   |   3 --
 lib/count-one-bits.h   | 112 ++---------------------------------------
 modules/count-one-bits |   1 +
 4 files changed, 21 insertions(+), 111 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 74d1ded7d5..742a38044f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2024-12-17  Collin Funk  <collin.fu...@gmail.com>
+
+	count-one-bits: Implement using stdbit.h.
+	* lib/count-one-bits.h: Include stdbit.h.
+	(COUNT_ONE_BITS): Remove definition.
+	(COUNT_ONE_BITS_GENERIC): Likewise.
+	(count_one_bits_32): Remove function.
+	(__cpuid, __popcnt, __popcnt64, popcount_support, popcount_supported)
+	[_MSC_VER]: Remove declarations.
+	(__popcnt64) [_MSC_VER && !_M_X64]: Remove function.
+	(count_one_bits): Use stdc_count_ones_ui.
+	(count_one_bits_l): Use stdc_count_ones_ul.
+	(count_one_bits_ll): stdc_count_ones_ull.
+	* lib/count-one-bits.c (popcount_support) [_MSC_VER]: Remove variable.
+	* modules/count-one-bits (Depends-on): Add stdc_count_ones.
+
 2024-12-17  Bruno Haible  <br...@clisp.org>
 
 	crc-x86_64: Tweaks.
diff --git a/lib/count-one-bits.c b/lib/count-one-bits.c
index 54b8708802..e6e415bf8c 100644
--- a/lib/count-one-bits.c
+++ b/lib/count-one-bits.c
@@ -20,6 +20,3 @@
 #define COUNT_ONE_BITS_INLINE _GL_EXTERN_INLINE
 #include "count-one-bits.h"
 
-#if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
-int popcount_support = -1;
-#endif
diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h
index 24bf8cc232..eddcf42f77 100644
--- a/lib/count-one-bits.h
+++ b/lib/count-one-bits.h
@@ -24,8 +24,7 @@
  #error "Please include config.h first."
 #endif
 
-#include <limits.h>
-#include <stdlib.h>
+#include <stdbit.h>
 
 _GL_INLINE_HEADER_BEGIN
 #ifndef COUNT_ONE_BITS_INLINE
@@ -36,128 +35,25 @@ _GL_INLINE_HEADER_BEGIN
 extern "C" {
 #endif
 
-/* Assuming the GCC builtin is GCC_BUILTIN and the MSC builtin is MSC_BUILTIN,
-   expand to code that computes the number of 1-bits of the local
-   variable 'x' of type TYPE (an unsigned integer type) and return it
-   from the current function.  */
-#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
-    || (__clang_major__ >= 4)
-# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
-    return GCC_BUILTIN (x)
-#else
-
-/* Compute and return the number of 1-bits set in the least
-   significant 32 bits of X. */
-COUNT_ONE_BITS_INLINE int
-count_one_bits_32 (unsigned int x)
-{
-  x = ((x & 0xaaaaaaaaU) >> 1) + (x & 0x55555555U);
-  x = ((x & 0xccccccccU) >> 2) + (x & 0x33333333U);
-  x = (x >> 16) + (x & 0xffff);
-  x = ((x & 0xf0f0) >> 4) + (x & 0x0f0f);
-  return (x >> 8) + (x & 0x00ff);
-}
-
-/* Expand to code that computes the number of 1-bits of the local
-   variable 'x' of type TYPE (an unsigned integer type) and return it
-   from the current function.  */
-# define COUNT_ONE_BITS_GENERIC(TYPE)                                   \
-    do                                                                  \
-      {                                                                 \
-        int count = 0;                                                  \
-        int bits;                                                       \
-        for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32)     \
-          {                                                             \
-            count += count_one_bits_32 (x);                             \
-            x = x >> 31 >> 1;                                           \
-          }                                                             \
-        return count;                                                   \
-      }                                                                 \
-    while (0)
-
-# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
-
-/* While gcc falls back to its own generic code if the machine
-   on which it's running doesn't support popcount, with Microsoft's
-   compiler we need to detect and fallback ourselves.  */
-
-#  if 0
-#   include <intrin.h>
-#  else
-    /* Don't pollute the namespace with too many MSVC intrinsics.  */
-extern void __cpuid (int[4], int);
-#   pragma intrinsic (__cpuid)
-extern unsigned int __popcnt (unsigned int);
-#   pragma intrinsic (__popcnt)
-#   if defined _M_X64
-extern unsigned long long __popcnt64 (unsigned long long);
-#    pragma intrinsic (__popcnt64)
-#   endif
-#  endif
-
-#  if !defined _M_X64
-static inline __popcnt64 (unsigned long long x)
-{
-  return __popcnt ((unsigned int) (x >> 32)) + __popcnt ((unsigned int) x);
-}
-#  endif
-
-/* Return nonzero if popcount is supported.  */
-
-/* 1 if supported, 0 if not supported, -1 if unknown.  */
-extern int popcount_support;
-
-COUNT_ONE_BITS_INLINE int
-popcount_supported (void)
-{
-  if (popcount_support < 0)
-    {
-      /* Do as described in
-         <https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64> */
-      int cpu_info[4];
-      __cpuid (cpu_info, 1);
-      popcount_support = (cpu_info[2] >> 23) & 1;
-    }
-  return popcount_support;
-}
-
-#  define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
-     do                                                  \
-       {                                                 \
-         if (popcount_supported ())                      \
-           return MSC_BUILTIN (x);                       \
-         else                                            \
-           COUNT_ONE_BITS_GENERIC (TYPE);                \
-       }                                                 \
-     while (0)
-
-# else
-
-#  define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
-     COUNT_ONE_BITS_GENERIC (TYPE)
-
-# endif
-#endif
-
 /* Compute and return the number of 1-bits set in X. */
 COUNT_ONE_BITS_INLINE int
 count_one_bits (unsigned int x)
 {
-  COUNT_ONE_BITS (__builtin_popcount, __popcnt, unsigned int);
+  return stdc_count_ones_ui (x);
 }
 
 /* Compute and return the number of 1-bits set in X. */
 COUNT_ONE_BITS_INLINE int
 count_one_bits_l (unsigned long int x)
 {
-  COUNT_ONE_BITS (__builtin_popcountl, __popcnt, unsigned long int);
+  return stdc_count_ones_ul (x);
 }
 
 /* Compute and return the number of 1-bits set in X. */
 COUNT_ONE_BITS_INLINE int
 count_one_bits_ll (unsigned long long int x)
 {
-  COUNT_ONE_BITS (__builtin_popcountll, __popcnt64, unsigned long long int);
+  return stdc_count_ones_ull (x);
 }
 
 #ifdef __cplusplus
diff --git a/modules/count-one-bits b/modules/count-one-bits
index ddceacda4b..4354e07cd4 100644
--- a/modules/count-one-bits
+++ b/modules/count-one-bits
@@ -7,6 +7,7 @@ lib/count-one-bits.h
 
 Depends-on:
 extern-inline
+stdc_count_ones
 
 configure.ac:
 
-- 
2.47.1

Reply via email to