* lib/stdbit.in.h (stdc_first_leading_zero) (stdc_first_leading_one, stdc_first_trailing_zero_uc) (stdc_first_trailing_one_uc): Redo to avoid the need for a conditional branch, at least on x86-64 with GCC 14. --- ChangeLog | 7 +++++- lib/stdbit.in.h | 60 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 21 deletions(-)
diff --git a/ChangeLog b/ChangeLog index f37d9f2796..049f27b3b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ 2024-05-15 Paul Eggert <egg...@cs.ucla.edu> - stdbit: tweak for non-GCC non-Clang + stdbit: tweak first_leading for GCC + * lib/stdbit.in.h (stdc_first_leading_zero) + (stdc_first_leading_one, stdc_first_trailing_zero_uc) + (stdc_first_trailing_one_uc): Redo to avoid the need for a + conditional branch, at least on x86-64 with GCC 14. + * 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. diff --git a/lib/stdbit.in.h b/lib/stdbit.in.h index 984ef44ef9..ab328a7793 100644 --- a/lib/stdbit.in.h +++ b/lib/stdbit.in.h @@ -494,35 +494,40 @@ _GL_STDBIT_INLINE unsigned int stdc_first_leading_zero_uc (unsigned char n) { unsigned int count = stdc_leading_ones_uc (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_leading_zero_us (unsigned short int n) { unsigned int count = stdc_leading_ones_us (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_leading_zero_ui (unsigned int n) { unsigned int count = stdc_leading_ones_ui (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_leading_zero_ul (unsigned long int n) { unsigned int count = stdc_leading_ones_ul (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_leading_zero_ull (unsigned long long int n) { unsigned int count = stdc_leading_ones_ull (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } #define stdc_first_leading_zero(n) \ @@ -537,35 +542,40 @@ _GL_STDBIT_INLINE unsigned int stdc_first_leading_one_uc (unsigned char n) { unsigned int count = stdc_leading_zeros_uc (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_leading_one_us (unsigned short int n) { unsigned int count = stdc_leading_zeros_us (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_leading_one_ui (unsigned int n) { unsigned int count = stdc_leading_zeros_ui (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_leading_one_ul (unsigned long int n) { unsigned int count = stdc_leading_zeros_ul (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_leading_one_ull (unsigned long long int n) { unsigned int count = stdc_leading_zeros_ull (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } #define stdc_first_leading_one(n) \ @@ -580,35 +590,40 @@ _GL_STDBIT_INLINE unsigned int stdc_first_trailing_zero_uc (unsigned char n) { unsigned int count = stdc_trailing_ones_uc (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_trailing_zero_us (unsigned short int n) { unsigned int count = stdc_trailing_ones_us (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_trailing_zero_ui (unsigned int n) { unsigned int count = stdc_trailing_ones_ui (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_trailing_zero_ul (unsigned long int n) { unsigned int count = stdc_trailing_ones_ul (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_trailing_zero_ull (unsigned long long int n) { unsigned int count = stdc_trailing_ones_ull (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } #define stdc_first_trailing_zero(n) \ @@ -623,35 +638,40 @@ _GL_STDBIT_INLINE unsigned int stdc_first_trailing_one_uc (unsigned char n) { unsigned int count = stdc_trailing_zeros_uc (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_trailing_one_us (unsigned short int n) { unsigned int count = stdc_trailing_zeros_us (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_trailing_one_ui (unsigned int n) { unsigned int count = stdc_trailing_zeros_ui (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_trailing_one_ul (unsigned long int n) { unsigned int count = stdc_trailing_zeros_ul (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } _GL_STDBIT_INLINE unsigned int stdc_first_trailing_one_ull (unsigned long long int n) { unsigned int count = stdc_trailing_zeros_ull (n); - return count == 8 * sizeof n ? 0 : count + 1; + unsigned int bits = 8 * sizeof n; + return count % bits + (count < bits); } #define stdc_first_trailing_one(n) \ -- 2.45.0