From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id BC6F83857B82 for ; Thu, 16 Nov 2023 15:59:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BC6F83857B82 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org BC6F83857B82 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700150379; cv=none; b=QfjdZ8zRiufo19zu94KHKUewj2MTYKc+VYGisp9dc1fB/ufgzlcWi9ngtEPca0qFN0zdMt8scvYFDCL0xZ4K7Ji3Kf0I0CH+DxVPDxhCfm12lYtq0SD683Wy5fFH4ooeQiT8sW1toq3xih/SMD8ZNbhHA8/GH3TBWEYhcqLKs4Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700150379; c=relaxed/simple; bh=QpJ9LqvpPPeRwOy30jDFDLswke2AnzhKrng/iR3gWJQ=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=LnD2voCKHo6geqh83Q5J37GF6wgm6qCTSGan6ANjV0I3/M6bHvN0Hl/KMd7tnWHyCM4/wBvbZ7Ou32e3UNisxlKiJL54rVGGFH6+HretTVloeMudRtTYl8Vfsk+b1m6Eo7MGenQxcoznpF0oTcMcCWZkVbipyv1JJzjLsrj62Ag= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1700150377; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references; bh=kBCl4T5to0EC7FjxIqMlFVa+GUyuzOY5Dtbpi5QcWGw=; b=RVVy9Vmoats1NwQx7YN3IMx9m1d9pqx4VgZsQqoJ+/MeFiYXZhnmPaprwtOg1RBxjccGCE u20XY+nIaPFnGT9d8PuE9fZ+GeCj8bKAfB0M4PFrcqGHxtPV0ujN+AVs4E81iu/+DhENFQ cX62RFL0d+KrWlSO6S6FI09xAFOnRTw= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-686-jZuFv6tvO5GiQhj1Ikrf4Q-1; Thu, 16 Nov 2023 10:59:34 -0500 X-MC-Unique: jZuFv6tvO5GiQhj1Ikrf4Q-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CA8551C0782E; Thu, 16 Nov 2023 15:59:33 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.194.53]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7087A7ACE; Thu, 16 Nov 2023 15:59:33 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 3AGFxUWs2095630 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 16 Nov 2023 16:59:31 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 3AGFxTuH2095629; Thu, 16 Nov 2023 16:59:29 +0100 Date: Thu, 16 Nov 2023 16:59:29 +0100 From: Jakub Jelinek To: Joseph Myers Cc: libc-alpha@sourceware.org Subject: Re: [RFC] stdbit.h implementation Message-ID: Reply-To: Jakub Jelinek References: <299d386f-ae57-b48c-cc9-82fb41f5ebd@codesourcery.com> MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Tue, Nov 14, 2023 at 09:52:03PM +0000, Joseph Myers wrote: > > But, I'm really out of ideas what to do about stdc_bit_floor and > > stdc_bit_ceil to > > New type-generic built-in functions for them? Additional built-in > functions for operations that are more complicated to implement in terms > of the existing functions seem perfectly reasonable, even if not strictly > required. Actually, I managed to implement it, here it is (again, incremental patch against your patch + the 2 other incremental patches I've already posted against it). ({ ... }) isn't used and I believe the argument is always evaluated exactly ones. Passes the tst-stdbit.c I've already posted, but also this new test which tests unsigned _BitInt. Also tested with gcc 12 and tst-stdbit.c (i.e. the old type-generic macros). For stdc_bit_ceil I've used ?: extension with omitted middle argument after __extension__ because the idea with % didn't work out. And stdc_bit_floor is the only large macro, which uses stdc_bit_floor_ull for stuff that fits into 64 bits, optionally __bf128_inline for up to 128 bits (but doesn't use that on 32-bit platforms) and for unsigned _BitInt uses the 1 bit larger unsigned _BitInt trick except for BITINT_MAXWIDTH, in which case it uses yet another inline function. --- stdlib/stdbit.h.jj 2023-11-16 14:02:54.533538355 +0100 +++ stdlib/stdbit.h 2023-11-16 16:13:54.985290612 +0100 @@ -32,6 +32,11 @@ #define __STDC_ENDIAN_BIG__ __BIG_ENDIAN #define __STDC_ENDIAN_NATIVE__ __BYTE_ORDER +#if __glibc_has_builtin (__builtin_popcountg) +# define __stdc_type_width(x) \ + __builtin_popcountg ((__typeof (x)) ~(__typeof (x)) 0) +#endif + __BEGIN_DECLS /* Count leading zeros. */ @@ -46,9 +51,15 @@ extern unsigned int stdc_leading_zeros_u __extension__ extern unsigned int stdc_leading_zeros_ull (unsigned long long int __x) __THROW __attribute_const__; -#define stdc_leading_zeros(x) \ +#if defined (__stdc_type_width) && __glibc_has_builtin (__builtin_clzg) +# define stdc_leading_zeros(x) \ + ((unsigned int) \ + __builtin_clzg (x, __stdc_type_width (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 @@ -98,9 +109,16 @@ extern unsigned int stdc_leading_ones_ul __extension__ extern unsigned int stdc_leading_ones_ull (unsigned long long int __x) __THROW __attribute_const__; -#define stdc_leading_ones(x) \ +#if defined (__stdc_type_width) && __glibc_has_builtin (__builtin_clzg) +# define stdc_leading_ones(x) \ + ((unsigned int) \ + __builtin_clzg ((__typeof (x)) ~(x), \ + __stdc_type_width (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 @@ -150,11 +168,16 @@ extern unsigned int stdc_trailing_zeros_ __extension__ extern unsigned int stdc_trailing_zeros_ull (unsigned long long int __x) __THROW __attribute_const__; -#define stdc_trailing_zeros(x) \ +#if defined (__stdc_type_width) && __glibc_has_builtin (__builtin_ctzg) +# define stdc_trailing_zeros(x) \ + ((unsigned int) __builtin_ctzg (x, __stdc_type_width (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 (x) \ : stdc_trailing_zeros_uc (x)) +#endif #if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll) static __always_inline unsigned int @@ -204,7 +227,14 @@ extern unsigned int stdc_trailing_ones_u __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 defined (__stdc_type_width) && __glibc_has_builtin (__builtin_ctzg) +# define stdc_trailing_ones(x) \ + ((unsigned int) \ + __builtin_ctzg ((__typeof (x)) ~(x), \ + __stdc_type_width (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 @@ -254,11 +284,16 @@ extern unsigned int stdc_first_leading_z __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_clzg) +# define stdc_first_leading_zero(x) \ + (__builtin_clzg ((__typeof (x)) ~(x), -1) + 1U) +#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 (x) \ : stdc_first_leading_zero_uc (x)) +#endif #if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll) static __always_inline unsigned int @@ -308,11 +343,16 @@ extern unsigned int stdc_first_leading_o __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_clzg) +# define stdc_first_leading_one(x) \ + (__builtin_clzg (x, -1) + 1U) +#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 (x) \ : stdc_first_leading_one_uc (x)) +#endif #if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_clzll) static __always_inline unsigned int @@ -362,11 +402,16 @@ extern unsigned int stdc_first_trailing_ __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_ctzg) +# define stdc_first_trailing_zero(x) \ + (__builtin_ctzg ((__typeof (x)) ~(x), -1) + 1U) +#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 (x) \ : stdc_first_trailing_zero_uc (x)) +#endif #if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll) static __always_inline unsigned int @@ -416,11 +461,16 @@ extern unsigned int stdc_first_trailing_ __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_ctzg) +# define stdc_first_trailing_one(x) \ + ((unsigned int) __builtin_ctzg (x, -1) + 1U) +#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 (x) \ : stdc_first_trailing_one_uc (x)) +#endif #if __GNUC_PREREQ (3, 4) || __glibc_has_builtin (__builtin_ctzll) static __always_inline unsigned int @@ -470,9 +520,15 @@ extern unsigned int stdc_count_zeros_ul __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_popcountg) +# define stdc_count_zeros(x) \ + ((unsigned int) \ + __builtin_popcountg ((__typeof (x)) ~(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 @@ -522,7 +578,12 @@ extern unsigned int stdc_count_ones_ul ( __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_popcountg) +# define stdc_count_ones(x) \ + ((unsigned int) __builtin_popcountg (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 @@ -572,10 +633,19 @@ extern _Bool stdc_has_single_bit_ul (uns __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_popcountg) +# define stdc_has_single_bit(x) \ + (sizeof (x) <= sizeof (unsigned int) \ + ? stdc_has_single_bit_ui (x) \ + : sizeof (x) <= sizeof (unsigned long long) \ + ? stdc_has_single_bit_ull (x) \ + : (_Bool) (__builtin_popcountg (x) == 1)) +#else +# define stdc_has_single_bit(x) \ (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) @@ -623,7 +693,14 @@ extern unsigned int stdc_bit_width_ul (u __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 defined (__stdc_type_width) && __glibc_has_builtin (__builtin_clzg) +# define stdc_bit_width(x) \ + ((unsigned int) \ + (__stdc_type_width (x) \ + - __builtin_clzg (x, __stdc_type_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 @@ -673,7 +750,47 @@ extern unsigned long int stdc_bit_floor_ __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 defined (__stdc_type_width) && __glibc_has_builtin (__builtin_clzg) +# ifdef __SIZEOF_INT128__ +static __always_inline unsigned __int128 +__bf128_inline (unsigned __int128 __x) +{ + return __x == 0 ? 0 : ((unsigned __int128) 1) << (stdc_bit_width (__x) - 1); +} +# else +# define __bf128_inline stdc_bit_floor_ull +# endif +# ifdef __BITINT_MAXWIDTH__ +static __always_inline unsigned _BitInt(__BITINT_MAXWIDTH__) +__bfbitintmax_inline (unsigned _BitInt(__BITINT_MAXWIDTH__) __x) +{ + return __x == 0 ? 0 : (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 1) + << (stdc_bit_width (__x) - 1)); +} +# define stdc_bit_floor(x) \ + (sizeof (x) <= sizeof (unsigned long long) \ + ? (__typeof (x)) stdc_bit_floor_ull (x) \ + : sizeof (x) <= sizeof (__typeof (__bf128_inline (0))) \ + ? (__typeof (x)) __bf128_inline (x) \ + : __stdc_type_width (x) == __BITINT_MAXWIDTH__ \ + ? (__typeof (x)) __bfbitintmax_inline (x) \ + : (__typeof (x)) \ + ((((unsigned _BitInt(__stdc_type_width (x) \ + == __BITINT_MAXWIDTH__ \ + ? 1 : __stdc_type_width (x) + 1)) 1) \ + << (__stdc_type_width (x) == __BITINT_MAXWIDTH__ ? 0 \ + : (__stdc_type_width (x) \ + - __builtin_clzg (x, __stdc_type_width (x))))) \ + >> 1)) +# else +# define stdc_bit_floor(x) \ + (sizeof (x) <= sizeof (unsigned long long) \ + ? (__typeof (x)) stdc_bit_floor_ull (x) \ + : (__typeof (x)) __bf128_inline (x)) +# endif +#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 @@ -723,7 +840,16 @@ extern unsigned long int stdc_bit_ceil_u __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 defined (__stdc_type_width) && __glibc_has_builtin (__builtin_clzg) +# define stdc_bit_ceil(x) \ + (((__typeof (x)) 1) \ + << (__stdc_type_width (x) \ + - __builtin_clzg ((__typeof (x)) \ + ((__extension__ ((x) ? : 1)) - 1), \ + __stdc_type_width (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 Jakub