diff options
author | Karl Williamson <khw@cpan.org> | 2021-07-20 10:22:37 -0600 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2021-07-30 05:41:28 -0600 |
commit | e88dde507ccbbc2140c509d1e6b0a960d868c6d7 (patch) | |
tree | 260f69e66a30e5977b06fad312247f95a28bdae1 /inline.h | |
parent | fc1bb663cac6846450ceb387751b491f2ecef13e (diff) | |
download | perl-e88dde507ccbbc2140c509d1e6b0a960d868c6d7.tar.gz |
Use windows builtins for msb_pos, lsb_pos, if avail
Windows has different intrinsics than the previous commit added, with a
different API for counting leading/trailing zeros
Diffstat (limited to 'inline.h')
-rw-r--r-- | inline.h | 43 |
1 files changed, 42 insertions, 1 deletions
@@ -717,6 +717,16 @@ Perl_is_utf8_invariant_string_loc(const U8* const s, STRLEN len, const U8 ** ep) # endif #endif +#if defined(_MSC_VER) && _MSC_VER >= 1400 +# include <intrin.h> +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanReverse) +# ifdef _WIN64 +# pragma intrinsic(_BitScanForward64) +# pragma intrinsic(_BitScanReverse64) +# endif +#endif + /* Below are functions to find the first, last, or only set bit in a word. On * platforms with 64-bit capability, there is a pair for each operation; the * first taking a 64 bit operand, and the second a 32 bit one. The logic is @@ -739,6 +749,14 @@ Perl_lsbit_pos64(U64 word) return (unsigned) PERL_CTZ_64(word); +# elif U64SIZE == 8 && defined(_MSC_VER) && _MSC_VER >= 1400 + + { + unsigned long index; + _BitScanForward64(&index, word); + return (unsigned)index; + } + # else /* Here, we didn't find a fast method for finding the lsb. Fall back to @@ -783,6 +801,14 @@ Perl_lsbit_pos32(U32 word) return (unsigned) PERL_CTZ_32(word); +#elif U32SIZE == 4 && defined(_MSC_VER) && _MSC_VER >= 1400 + + { + unsigned long index; + _BitScanForward(&index, word); + return (unsigned)index; + } + #else return single_1bit_pos32(word & (~word + 1)); @@ -812,6 +838,14 @@ Perl_msbit_pos64(U64 word) return (unsigned) LZC_TO_MSBIT_POS_(U64, PERL_CLZ_64(word)); +# elif U64SIZE == 8 && defined(_WIN64) && defined(_MSC_VER) && _MSC_VER >= 1400 + + { + unsigned long index; + _BitScanReverse64(&index, word); + return (unsigned)index; + } + # else /* Here, we didn't find a fast method for finding the msb. Fall back to @@ -859,6 +893,14 @@ Perl_msbit_pos32(U32 word) return (unsigned) LZC_TO_MSBIT_POS_(U32, PERL_CLZ_32(word)); +#elif U32SIZE == 4 && defined(_MSC_VER) && _MSC_VER >= 1400 + + { + unsigned long index; + _BitScanReverse(&index, word); + return (unsigned)index; + } + #else word |= (word >> 1); @@ -917,7 +959,6 @@ Perl_single_1bit_pos32(U32 word) PERL_STATIC_INLINE unsigned int Perl_variant_byte_number(PERL_UINTMAX_T word) { - /* This returns the position in a word (0..7) of the first variant byte in * it. This is a helper function. Note that there are no branches */ |