From f32cf51e1f84ddcfc34be1ab9fe096e5b3f61631 Mon Sep 17 00:00:00 2001 From: Karl Williamson Date: Tue, 20 Jul 2021 10:41:39 -0600 Subject: [PATCH] Use ffs(), ffsl() for lsb_pos, if available ffs() is a POSIX function that serves to find the lsb of a word. It should be faster than anything we hand-roll, but slower than any available intrinsics that the previous commits use; so this commit looks for it only if they aren't available. Some platforms have an equivalent ffsl() for longs, which we use if the word is long-sized. --- inline.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/inline.h b/inline.h index be5ce02895be..9cc54c865e6c 100644 --- a/inline.h +++ b/inline.h @@ -731,6 +731,21 @@ Perl_is_utf8_invariant_string_loc(const U8* const s, STRLEN len, const U8 ** ep) # endif #endif +#if U32SIZE == INTSIZE && defined(HAS_FFS) +# define PERL_FFS32 ffs +#elif U32SIZE == LONGSIZE && defined(HAS_FFSL) +# define PERL_FFS32 ffsl +#endif +#ifdef HAS_QUAD +# if U64SIZE == INTSIZE && defined(HAS_FFS) +# define PERL_FFS64 ffs +# elif U64SIZE == LONGSIZE && defined(HAS_FFSL) +# define PERL_FFS64 ffsl +# elif U64SIZE == LONGLONGSIZE && defined(HAS_FFSLL) +# define PERL_FFS64 ffsll +# endif +#endif + #if defined(_MSC_VER) && _MSC_VER >= 1400 # include # pragma intrinsic(_BitScanForward) @@ -771,6 +786,10 @@ Perl_lsbit_pos64(U64 word) return (unsigned)index; } +# elif defined(PERL_FFS64) + + return PERL_FFS64(word) - 1; /* ffs() returns bit position indexed from 1 */ + # else /* Here, we didn't find a fast method for finding the lsb. Fall back to @@ -823,6 +842,10 @@ Perl_lsbit_pos32(U32 word) return (unsigned)index; } +#elif defined(PERL_FFS32) + + return PERL_FFS32(word) - 1; + #else return single_1bit_pos32(word & (~word + 1));