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 30, 2021
1 parent fc1bb66 commit e88dde5
Showing 1 changed file with 42 additions and 1 deletion.
43 changes: 42 additions & 1 deletion inline.h
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */

Expand Down

0 comments on commit e88dde5

Please sign in to comment.