bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2] stdbit: tweak for non-GCC non-Clang


From: Paul Eggert
Subject: [PATCH 1/2] stdbit: tweak for non-GCC non-Clang
Date: Wed, 15 May 2024 15:14:57 -0700

* lib/stdbit.in.h (__gl_stdbit_clz, __gl_stdbit_clzl)
(__gl_stdbit_clzll, __gl_stdbit_ctz, __gl_stdbit_ctzl)
(__gl_stdbit_ctzll): Work even if the argument is zero.
All callers changed.  This should help avoid branches
on non-GCC-like platforms.
---
 ChangeLog       |  9 ++++++
 lib/stdbit.in.h | 73 +++++++++++++++++++++++++++++++------------------
 2 files changed, 56 insertions(+), 26 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index af8fb1e409..f37d9f2796 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2024-05-15  Paul Eggert  <eggert@cs.ucla.edu>
+
+       stdbit: tweak for non-GCC non-Clang
+       * lib/stdbit.in.h (__gl_stdbit_clz, __gl_stdbit_clzl)
+       (__gl_stdbit_clzll, __gl_stdbit_ctz, __gl_stdbit_ctzl)
+       (__gl_stdbit_ctzll): Work even if the argument is zero.
+       All callers changed.  This should help avoid branches
+       on non-GCC-like platforms.
+
 2024-05-15  Bruno Haible  <bruno@clisp.org>
 
        vasnprintf: Avoid a dummy memory allocation.
diff --git a/lib/stdbit.in.h b/lib/stdbit.in.h
index 18efaf2d7c..984ef44ef9 100644
--- a/lib/stdbit.in.h
+++ b/lib/stdbit.in.h
@@ -85,11 +85,23 @@ extern "C" {
 # endif
 #endif
 
-/* Count leading zeros of nonzero N.  */
+/* Count leading 0 bits of N, even if N is 0.  */
 #ifdef _GL_STDBIT_HAS_BUILTIN_CLZ
-# define __gl_stdbit_clz __builtin_clz
-# define __gl_stdbit_clzl __builtin_clzl
-# define __gl_stdbit_clzll __builtin_clzll
+_GL_STDBIT_INLINE int
+__gl_stdbit_clz (unsigned int n)
+{
+  return n ? __builtin_clz (n) : 8 * sizeof n;
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_clzl (unsigned long int n)
+{
+  return n ? __builtin_clzl (n) : 8 * sizeof n;
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_clzll (unsigned long long int n)
+{
+  return n ? __builtin_clzll (n) : 8 * sizeof n;
+}
 #elif defined _MSC_VER
 # pragma intrinsic (_BitScanReverse)
 # ifdef _M_X64
@@ -99,8 +111,7 @@ _GL_STDBIT_INLINE int
 __gl_stdbit_clzl (unsigned long int n)
 {
   unsigned long int r;
-  _BitScanReverse (&r, n);
-  return 8 * sizeof n - 1 - r;
+  return 8 * sizeof n - (_BitScanReverse (&r, n) ? r + 1 : 0);
 }
 _GL_STDBIT_INLINE int
 __gl_stdbit_clz (unsigned int n)
@@ -112,8 +123,7 @@ __gl_stdbit_clzll (unsigned long long int n)
 {
 # ifdef _M_X64
   unsigned long int r;
-  _BitScanReverse64 (&r, n);
-  return 64 - 1 - r;
+  return 8 * sizeof n - (_BitScanReverse (&r, n) ? r + 1 : 0);
 # else
   unsigned long int hi = n >> 32;
   return __gl_stdbit_clzl (hi ? hi : n) + (hi ? 0 : 32);
@@ -148,10 +158,23 @@ __gl_stdbit_clzl (unsigned long int n)
 }
 #endif
 
+/* Count trailing 0 bits of N, even if N is 0.  */
 #ifdef _GL_STDBIT_HAS_BUILTIN_CTZ
-# define __gl_stdbit_ctz __builtin_ctz
-# define __gl_stdbit_ctzl __builtin_ctzl
-# define __gl_stdbit_ctzll __builtin_ctzll
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctz (unsigned int n)
+{
+  return n ? __builtin_ctz (n) : 8 * sizeof n;
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzl (unsigned long int n)
+{
+  return n ? __builtin_ctzl (n) : 8 * sizeof n;
+}
+_GL_STDBIT_INLINE int
+__gl_stdbit_ctzll (unsigned long long int n)
+{
+  return n ? __builtin_ctzll (n) : 8 * sizeof n;
+}
 #elif defined _MSC_VER
 # pragma intrinsic (_BitScanForward)
 # ifdef _M_X64
@@ -161,21 +184,19 @@ _GL_STDBIT_INLINE int
 __gl_stdbit_ctzl (unsigned long int n)
 {
   unsigned long int r;
-  _BitScanForward (&r, n);
-  return r;
+  return _BitScanForward (&r, n) ? r : 8 * sizeof n;
 }
 _GL_STDBIT_INLINE int
 __gl_stdbit_ctz (unsigned int n)
 {
-  return __gl_stdbit_ctzl (n);
+  return __gl_stdbit_ctzl (n | (1ul << (8 * sizeof n - 1) << 1));
 }
 _GL_STDBIT_INLINE int
 __gl_stdbit_ctzll (unsigned long long int n)
 {
 # ifdef _M_X64
   unsigned long int r;
-  _BitScanForward64 (&r, n);
-  return r;
+  return _BitScanForward64 (&r, n) ? r : 8 * sizeof n;
 # else
   unsigned int lo = n;
   return __gl_stdbit_ctzl (lo ? lo : n >> 32) + (lo ? 0 : 32);
@@ -188,26 +209,26 @@ _GL_STDBIT_INLINE int
 _GL_STDBIT_INLINE int
 __gl_stdbit_ctz (unsigned int n)
 {
-  return 8 * sizeof n - 1 - __gl_stdbit_clz (n & -n);
+  return 8 * sizeof n - (n ? __gl_stdbit_clz (n & -n) + 1 : 0);
 }
 _GL_STDBIT_INLINE int
 __gl_stdbit_ctzl (unsigned long int n)
 {
-  return 8 * sizeof n - 1 - __gl_stdbit_clzl (n & -n);
+  return 8 * sizeof n - (n ? __gl_stdbit_clzl (n & -n) + 1 : 0);
 }
 _GL_STDBIT_INLINE int
 __gl_stdbit_ctzll (unsigned long long int n)
 {
-  return 8 * sizeof n - 1 - __gl_stdbit_clzll (n & -n);
+  return 8 * sizeof n - (n ? __gl_stdbit_clzll (n & -n) + 1 : 0);
 }
 #endif
 
+/* Count 1 bits in N.  */
 #ifdef _GL_STDBIT_HAS_BUILTIN_POPCOUNT
 # define __gl_stdbit_popcount __builtin_popcount
 # define __gl_stdbit_popcountl __builtin_popcountl
 # define __gl_stdbit_popcountll __builtin_popcountll
 #else
-/* Count the number of 1 bits in N.  */
 _GL_STDBIT_INLINE int
 __gl_stdbit_popcount_wide (unsigned long long int n)
 {
@@ -320,7 +341,7 @@ __gl_stdbit_popcountll (unsigned long long int n)
 _GL_STDBIT_INLINE unsigned int
 stdc_leading_zeros_ui (unsigned int n)
 {
-  return n ? __gl_stdbit_clz (n) : 8 * sizeof n;
+  return __gl_stdbit_clz (n);
 }
 
 _GL_STDBIT_INLINE unsigned int
@@ -338,13 +359,13 @@ stdc_leading_zeros_us (unsigned short int n)
 _GL_STDBIT_INLINE unsigned int
 stdc_leading_zeros_ul (unsigned long int n)
 {
-  return n ? __gl_stdbit_clzl (n) : 8 * sizeof n;
+  return __gl_stdbit_clzl (n);
 }
 
 _GL_STDBIT_INLINE unsigned int
 stdc_leading_zeros_ull (unsigned long long int n)
 {
-  return n ? __gl_stdbit_clzll (n) : 8 * sizeof n;
+  return __gl_stdbit_clzll (n);
 }
 
 #define stdc_leading_zeros(n) \
@@ -396,7 +417,7 @@ stdc_leading_ones_ull (unsigned long long int n)
 _GL_STDBIT_INLINE unsigned int
 stdc_trailing_zeros_ui (unsigned int n)
 {
-  return n ? __gl_stdbit_ctz (n) : 8 * sizeof n;
+  return __gl_stdbit_ctz (n);
 }
 
 _GL_STDBIT_INLINE unsigned int
@@ -414,13 +435,13 @@ stdc_trailing_zeros_us (unsigned short int n)
 _GL_STDBIT_INLINE unsigned int
 stdc_trailing_zeros_ul (unsigned long int n)
 {
-  return n ? __gl_stdbit_ctzl (n) : 8 * sizeof n;
+  return __gl_stdbit_ctzl (n);
 }
 
 _GL_STDBIT_INLINE unsigned int
 stdc_trailing_zeros_ull (unsigned long long int n)
 {
-  return n ? __gl_stdbit_ctzll (n) : 8 * sizeof n;
+  return __gl_stdbit_ctzll (n);
 }
 
 #define stdc_trailing_zeros(n) \
-- 
2.45.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]