263 lines
12 KiB
Diff
263 lines
12 KiB
Diff
|
From 1b9c1a0047fb26a65a9b2a7b8cd977243f7d353c Mon Sep 17 00:00:00 2001
|
||
|
From: Jakub Jelinek <jakub@redhat.com>
|
||
|
Date: Wed, 31 Jan 2024 19:17:27 +0100
|
||
|
Subject: [PATCH] Use gcc __builtin_stdc_* builtins in stdbit.h if possible
|
||
|
|
||
|
The following patch uses the GCC 14 __builtin_stdc_* builtins in stdbit.h
|
||
|
for the type-generic macros, so that when compiled with GCC 14 or later,
|
||
|
it supports not just 8/16/32/64-bit unsigned integers, but also 128-bit
|
||
|
(if target supports them) and unsigned _BitInt (any supported precision).
|
||
|
And so that the macros don't expand arguments multiple times and can be
|
||
|
evaluated in constant expressions.
|
||
|
|
||
|
The new testcase is gcc's gcc/testsuite/gcc.dg/builtin-stdc-bit-1.c
|
||
|
adjusted to test stdbit.h and the type-generic macros in there instead
|
||
|
of the builtins and adjusted to use glibc test framework rather than
|
||
|
gcc style tests with __builtin_abort ().
|
||
|
|
||
|
Signed-off-by: Jakub Jelinek <jakub@redhat.com>
|
||
|
Reviewed-by: Joseph Myers <josmyers@redhat.com>
|
||
|
(cherry picked from commit da89496337b97e6a2aaf1e81d55cf998f6db1070)
|
||
|
---
|
||
|
manual/stdbit.texi | 8 +-
|
||
|
stdlib/Makefile | 1 +
|
||
|
stdlib/stdbit.h | 84 +++-
|
||
|
stdlib/tst-stdbit-builtins.c | 778 +++++++++++++++++++++++++++++++++++
|
||
|
4 files changed, 856 insertions(+), 15 deletions(-)
|
||
|
create mode 100644 stdlib/tst-stdbit-builtins.c
|
||
|
|
||
|
diff --git a/manual/stdbit.texi b/manual/stdbit.texi
|
||
|
index fe41c671d8..6c75ed9a20 100644
|
||
|
--- a/manual/stdbit.texi
|
||
|
+++ b/manual/stdbit.texi
|
||
|
@@ -32,7 +32,13 @@ and @code{unsigned long long int}. In addition, there is a
|
||
|
corresponding type-generic macro (not listed below), named the same as
|
||
|
the functions but without any suffix such as @samp{_uc}. The
|
||
|
type-generic macro can only be used with an argument of an unsigned
|
||
|
-integer type with a width of 8, 16, 32 or 64 bits.
|
||
|
+integer type with a width of 8, 16, 32 or 64 bits, or when using
|
||
|
+a compiler with support for
|
||
|
+@uref{https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html,@code{__builtin_stdc_bit_ceil}},
|
||
|
+etc.@:, built-in functions such as GCC 14.1 or later
|
||
|
+any unsigned integer type those built-in functions support.
|
||
|
+In GCC 14.1 that includes support for @code{unsigned __int128} and
|
||
|
+@code{unsigned _BitInt(@var{n})} if supported by the target.
|
||
|
|
||
|
@deftypefun {unsigned int} stdc_leading_zeros_uc (unsigned char @var{x})
|
||
|
@deftypefunx {unsigned int} stdc_leading_zeros_us (unsigned short @var{x})
|
||
|
diff --git a/stdlib/stdbit.h b/stdlib/stdbit.h
|
||
|
index f334eb174d..2801590c63 100644
|
||
|
--- a/stdlib/stdbit.h
|
||
|
+++ b/stdlib/stdbit.h
|
||
|
@@ -64,9 +64,13 @@ extern unsigned int stdc_leading_zeros_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_leading_zeros_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_leading_zeros(x) \
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_leading_zeros)
|
||
|
+# define stdc_leading_zeros(x) (__builtin_stdc_leading_zeros (x))
|
||
|
+#else
|
||
|
+# define stdc_leading_zeros(x) \
|
||
|
(stdc_leading_zeros_ull (x) \
|
||
|
- (unsigned int) (8 * (sizeof (0ULL) - sizeof (x))))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -116,9 +120,13 @@ extern unsigned int stdc_leading_ones_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_leading_ones_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_leading_ones(x) \
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_leading_ones)
|
||
|
+# define stdc_leading_ones(x) (__builtin_stdc_leading_ones (x))
|
||
|
+#else
|
||
|
+# define stdc_leading_ones(x) \
|
||
|
(stdc_leading_ones_ull ((unsigned long long int) (x) \
|
||
|
<< 8 * (sizeof (0ULL) - sizeof (x))))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -168,11 +176,15 @@ extern unsigned int stdc_trailing_zeros_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_trailing_zeros_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_trailing_zeros(x) \
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_trailing_zeros)
|
||
|
+# define stdc_trailing_zeros(x) (__builtin_stdc_trailing_zeros (x))
|
||
|
+#else
|
||
|
+# define stdc_trailing_zeros(x) \
|
||
|
(sizeof (x) == 8 ? stdc_trailing_zeros_ull (x) \
|
||
|
: sizeof (x) == 4 ? stdc_trailing_zeros_ui (x) \
|
||
|
: sizeof (x) == 2 ? stdc_trailing_zeros_us (__pacify_uint16 (x)) \
|
||
|
: stdc_trailing_zeros_uc (__pacify_uint8 (x)))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -222,7 +234,11 @@ extern unsigned int stdc_trailing_ones_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_trailing_ones_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_trailing_ones(x) (stdc_trailing_ones_ull (x))
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_trailing_ones)
|
||
|
+# define stdc_trailing_ones(x) (__builtin_stdc_trailing_ones (x))
|
||
|
+#else
|
||
|
+# define stdc_trailing_ones(x) (stdc_trailing_ones_ull (x))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -272,11 +288,15 @@ extern unsigned int stdc_first_leading_zero_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_first_leading_zero_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_first_leading_zero(x) \
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_first_leading_zero)
|
||
|
+# define stdc_first_leading_zero(x) (__builtin_stdc_first_leading_zero (x))
|
||
|
+#else
|
||
|
+# define stdc_first_leading_zero(x) \
|
||
|
(sizeof (x) == 8 ? stdc_first_leading_zero_ull (x) \
|
||
|
: sizeof (x) == 4 ? stdc_first_leading_zero_ui (x) \
|
||
|
: sizeof (x) == 2 ? stdc_first_leading_zero_us (__pacify_uint16 (x)) \
|
||
|
: stdc_first_leading_zero_uc (__pacify_uint8 (x)))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -326,11 +346,15 @@ extern unsigned int stdc_first_leading_one_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_first_leading_one_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_first_leading_one(x) \
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_first_leading_one)
|
||
|
+# define stdc_first_leading_one(x) (__builtin_stdc_first_leading_one (x))
|
||
|
+#else
|
||
|
+# define stdc_first_leading_one(x) \
|
||
|
(sizeof (x) == 8 ? stdc_first_leading_one_ull (x) \
|
||
|
: sizeof (x) == 4 ? stdc_first_leading_one_ui (x) \
|
||
|
: sizeof (x) == 2 ? stdc_first_leading_one_us (__pacify_uint16 (x)) \
|
||
|
: stdc_first_leading_one_uc (__pacify_uint8 (x)))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -380,11 +404,15 @@ extern unsigned int stdc_first_trailing_zero_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_first_trailing_zero_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_first_trailing_zero(x) \
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_first_trailing_zero)
|
||
|
+# define stdc_first_trailing_zero(x) (__builtin_stdc_first_trailing_zero (x))
|
||
|
+#else
|
||
|
+# define stdc_first_trailing_zero(x) \
|
||
|
(sizeof (x) == 8 ? stdc_first_trailing_zero_ull (x) \
|
||
|
: sizeof (x) == 4 ? stdc_first_trailing_zero_ui (x) \
|
||
|
: sizeof (x) == 2 ? stdc_first_trailing_zero_us (__pacify_uint16 (x)) \
|
||
|
: stdc_first_trailing_zero_uc (__pacify_uint8 (x)))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -434,11 +462,15 @@ extern unsigned int stdc_first_trailing_one_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_first_trailing_one_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_first_trailing_one(x) \
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_first_trailing_one)
|
||
|
+# define stdc_first_trailing_one(x) (__builtin_stdc_first_trailing_one (x))
|
||
|
+#else
|
||
|
+# define stdc_first_trailing_one(x) \
|
||
|
(sizeof (x) == 8 ? stdc_first_trailing_one_ull (x) \
|
||
|
: sizeof (x) == 4 ? stdc_first_trailing_one_ui (x) \
|
||
|
: sizeof (x) == 2 ? stdc_first_trailing_one_us (__pacify_uint16 (x)) \
|
||
|
: stdc_first_trailing_one_uc (__pacify_uint8 (x)))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -488,9 +520,13 @@ extern unsigned int stdc_count_zeros_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_count_zeros_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_count_zeros(x) \
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_count_zeros)
|
||
|
+# define stdc_count_zeros(x) (__builtin_stdc_count_zeros (x))
|
||
|
+#else
|
||
|
+# define stdc_count_zeros(x) \
|
||
|
(stdc_count_zeros_ull (x) \
|
||
|
- (unsigned int) (8 * (sizeof (0ULL) - sizeof (x))))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_popcountll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -540,7 +576,11 @@ extern unsigned int stdc_count_ones_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_count_ones_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_count_ones(x) (stdc_count_ones_ull (x))
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_count_ones)
|
||
|
+# define stdc_count_ones(x) (__builtin_stdc_count_ones (x))
|
||
|
+#else
|
||
|
+# define stdc_count_ones(x) (stdc_count_ones_ull (x))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_popcountll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -590,10 +630,14 @@ extern bool stdc_has_single_bit_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern bool stdc_has_single_bit_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_has_single_bit(x) \
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_has_single_bit)
|
||
|
+# define stdc_has_single_bit(x) (__builtin_stdc_has_single_bit (x))
|
||
|
+#else
|
||
|
+# define stdc_has_single_bit(x) \
|
||
|
((bool) (sizeof (x) <= sizeof (unsigned int) \
|
||
|
? stdc_has_single_bit_ui (x) \
|
||
|
: stdc_has_single_bit_ull (x)))
|
||
|
+#endif
|
||
|
|
||
|
static __always_inline bool
|
||
|
__hsb64_inline (uint64_t __x)
|
||
|
@@ -641,7 +685,11 @@ extern unsigned int stdc_bit_width_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned int stdc_bit_width_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_bit_width(x) (stdc_bit_width_ull (x))
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_bit_width)
|
||
|
+# define stdc_bit_width(x) (__builtin_stdc_bit_width (x))
|
||
|
+#else
|
||
|
+# define stdc_bit_width(x) (stdc_bit_width_ull (x))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
|
||
|
static __always_inline unsigned int
|
||
|
@@ -691,7 +739,11 @@ extern unsigned long int stdc_bit_floor_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned long long int stdc_bit_floor_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_bit_floor(x) ((__typeof (x)) stdc_bit_floor_ull (x))
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_bit_floor)
|
||
|
+# define stdc_bit_floor(x) (__builtin_stdc_bit_floor (x))
|
||
|
+#else
|
||
|
+# define stdc_bit_floor(x) ((__typeof (x)) stdc_bit_floor_ull (x))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
|
||
|
static __always_inline uint64_t
|
||
|
@@ -743,7 +795,11 @@ extern unsigned long int stdc_bit_ceil_ul (unsigned long int __x)
|
||
|
__extension__
|
||
|
extern unsigned long long int stdc_bit_ceil_ull (unsigned long long int __x)
|
||
|
__THROW __attribute_const__;
|
||
|
-#define stdc_bit_ceil(x) ((__typeof (x)) stdc_bit_ceil_ull (x))
|
||
|
+#if __glibc_has_builtin (__builtin_stdc_bit_ceil)
|
||
|
+# define stdc_bit_ceil(x) (__builtin_stdc_bit_ceil (x))
|
||
|
+#else
|
||
|
+# define stdc_bit_ceil(x) ((__typeof (x)) stdc_bit_ceil_ull (x))
|
||
|
+#endif
|
||
|
|
||
|
#if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll)
|
||
|
static __always_inline uint64_t
|