From: Jakub Jelinek <jakub@redhat.com>
To: Joseph Myers <joseph@codesourcery.com>
Cc: libc-alpha@sourceware.org
Subject: Re: [RFC] stdbit.h implementation
Date: Tue, 14 Nov 2023 20:14:52 +0100 [thread overview]
Message-ID: <ZVPHLPhG1b5dlSBb@tucnak> (raw)
In-Reply-To: <299d386f-ae57-b48c-cc9-82fb41f5ebd@codesourcery.com>
On Tue, Nov 14, 2023 at 06:02:12PM +0000, Joseph Myers wrote:
> On Tue, 14 Nov 2023, Jakub Jelinek wrote:
>
> > In order to double-check the __builtin_{clz,ctz,popcount}g builtins
> > I've added today to GCC, I've tried to implement the C23 stdbit.h
> > header (but just the header, not anything further) plus a test (though,
> > in GCC style where it aborts on error and returns 0 otherwise) for it.
>
> The following is my current in-progress patch (which needs tests and
> documentation, so it's quite possible some implementations are currently
> incorrect) - including all the out-of-line implementations (defined so
> that the out-of-line function implementations use the inline macro
> implementations from the header). It doesn't attempt to use the new
> built-in functions (or, thus, to support _BitInt). Among my notes for
> things to cover in tests include that all macros are usable inside sizeof
> etc. outside of a function (thus, do not use ({ })) - also that
> type-specific calls have the correct implicit argument conversions, also
> that both type-specific and type-generic calls evaluate arguments exactly
> once. I haven't tested how well-optimized code is for any of these
> implementations (type-specific or type-generic) - but if it isn't, it
> probably should be, since I think all of these are among reasonable
> options for how to express the operations in terms of the underlying
> built-in functions.
I think the fallback _Generic versions satisfy that, but the
__builtin_{clz,ctz,popcount}g unfortunately do use ({ }) in 3 of them.
In one case it is just an optimization attempt and it isn't strictly
necessary, stdc_bit_width can be implemented as popcount (value) == 1
or as value && (value & (value - 1)) == 0 or as
value && (value & -value) == value, and perhaps we could just optimize
popcount (value) == 1 into the second test in GCC in match.pd.
But, I'm really out of ideas what to do about stdc_bit_floor and
stdc_bit_ceil to
1) evaluate argument just once
2) handle all _BitInts
3) avoid ({ })
One can't use an inline function because of 2), unless 65535+
functions are added, 3) was a way to handle 1).
Actually, maybe
#define stdc_bit_ceil(value) \
(((__typeof (value)) 1) << ((__builtin_popcountg ((__typeof (value)) ~(__typeof (value)) 0) - __builtin_clzg ((__typeof (value)) (value - 1), 0)) % __builtin_popcountg ((__typeof (value)) ~(__typeof (value)) 0)))
where say on unsigned _BitInt(275)
the above will be
(((unsigned _BitInt(275)) 1) << ((275 - __builtin_clzg ((__typeof (value)) (value - 1), 0)) % 275))
and so for 0
(((unsigned _BitInt(275)) 1) << (0 % 275))
and for 1
(((unsigned _BitInt(275)) 1) << (275 % 275))
Maybe add some unsigned int cast in there to avoid the modulo being
signed and allow e.g. ffor powers of two width to be handled more
efficiently.
But the stdc_bit_floor needs 0 return value for input value of 0
and otherwise 1 << something, so
((value) == 0 ? (__typeof (value)) 0 : ((__typeof (value)) 1) << (__builtin_popcountg ((__typeof (value)) ~(__typeof (value)) 0) - 1 - __builtin_clzg (value)))
is inappropriate because if evaluates value twice; and while I can make
the shift count into whatever int value we want for value == 0 when
evaluating it just once, it won't turn the result into 0 unless << -1
would be allowed and result into >> 1.
?: with left out middle operand is yet another way how to avoid evaluating
something twice, but no idea how to use it here.
Maybe one ugly way for unsigned _BitInt with the exception of
unsigned _BitInt(__BITINT_MAXWIDTH__) would be (after
__builtin_classify_type (value) == 18 check) to use
((__typeof (value)) (((unsigned _BitInt(__builtin_popcountg ((__typeof (value)) ~(__typeof (value)) 0) + 1) 1) << (__builtin_popcountg ((__typeof (value)) ~(__typeof (value)) 0) - __builtin_clzg (value, __builtin_popcountg ((__typeof (value)) ~(__typeof (value)) 0)))) >> 1))
i.e. perform the left shift in one bit wider _BitInt type than value, say
again for unsigned _BitInt(275) value shift ((unsigned _BitInt(276)) 1) left
by 0 for the value == 0 case and by 1..275 for the other cases, then shift
right by 1 bit and cast.
And perhaps the unsigned _BitInt(__BITINT_MAXWIDTH__) case could be handled
in an static inline function (like the non-_BitInt cases).
BTW, in my stdbit.h version, I've added explicit casts in all the
sizeof/_Generic using type-generic macros, because otherwise GCC
-Wconversion was quite noisy on lots of uses in the testcase.
Anyway, feel free to cherry-pick anything useful from the posted patch.
Jakub
next prev parent reply other threads:[~2023-11-14 19:15 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-14 17:00 Jakub Jelinek
2023-11-14 18:02 ` Joseph Myers
2023-11-14 19:14 ` Jakub Jelinek [this message]
2023-11-14 21:52 ` Joseph Myers
2023-11-15 19:18 ` Andrew Pinski
2023-11-16 15:59 ` Jakub Jelinek
2023-11-16 16:01 ` Jakub Jelinek
2023-11-18 10:10 ` Florian Weimer
2023-11-18 10:22 ` Jakub Jelinek
2023-11-18 10:51 ` Florian Weimer
2023-11-18 11:09 ` Jakub Jelinek
2023-11-15 19:11 ` tavianator
2023-11-16 13:18 ` Jakub Jelinek
2023-11-14 19:58 ` Jakub Jelinek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZVPHLPhG1b5dlSBb@tucnak \
--to=jakub@redhat.com \
--cc=joseph@codesourcery.com \
--cc=libc-alpha@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).