Skip to content

Commit

Permalink
Use windows builtins for msb_pos, lsb_pos, if avail
Browse files Browse the repository at this point in the history
Windows has different intrinsics than the previous commit added, with a
different API for counting leading/trailing zeros
  • Loading branch information
khwilliamson committed Jul 20, 2021
1 parent 63c270c commit 012129c
Showing 1 changed file with 42 additions and 1 deletion.
43 changes: 42 additions & 1 deletion inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,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
Expand All @@ -753,6 +763,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
Expand Down Expand Up @@ -797,6 +815,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));
Expand Down Expand Up @@ -826,6 +852,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
Expand Down Expand Up @@ -873,6 +907,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);
Expand Down Expand Up @@ -927,7 +969,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 */

Expand Down

0 comments on commit 012129c

Please sign in to comment.