summaryrefslogtreecommitdiff
path: root/inline.h
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2021-07-20 10:22:37 -0600
committerKarl Williamson <khw@cpan.org>2021-07-30 05:41:28 -0600
commite88dde507ccbbc2140c509d1e6b0a960d868c6d7 (patch)
tree260f69e66a30e5977b06fad312247f95a28bdae1 /inline.h
parentfc1bb663cac6846450ceb387751b491f2ecef13e (diff)
downloadperl-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.h43
1 files changed, 42 insertions, 1 deletions
diff --git a/inline.h b/inline.h
index c8a88f7a6d..57db98f3bc 100644
--- a/inline.h
+++ b/inline.h
@@ -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 */