1313#ifndef PG_BITUTILS_H
1414#define PG_BITUTILS_H
1515
16+ #ifdef _MSC_VER
17+ #include <intrin.h>
18+ #define HAVE_BITSCAN_FORWARD
19+ #define HAVE_BITSCAN_REVERSE
20+
21+ #else
22+ #if defined(HAVE__BUILTIN_CTZ )
23+ #define HAVE_BITSCAN_FORWARD
24+ #endif
25+
26+ #if defined(HAVE__BUILTIN_CLZ )
27+ #define HAVE_BITSCAN_REVERSE
28+ #endif
29+ #endif /* _MSC_VER */
30+
1631extern PGDLLIMPORT const uint8 pg_leftmost_one_pos [256 ];
1732extern PGDLLIMPORT const uint8 pg_rightmost_one_pos [256 ];
1833extern PGDLLIMPORT const uint8 pg_number_of_ones [256 ];
@@ -27,9 +42,12 @@ pg_leftmost_one_pos32(uint32 word)
2742{
2843#ifdef HAVE__BUILTIN_CLZ
2944 int bitscan_result ;
45+ #elif defined(_MSC_VER )
46+ unsigned long bitscan_result ;
47+ bool non_zero ;
3048#endif
3149
32- #if !defined(HAVE__BUILTIN_CLZ ) || defined(USE_ASSERT_CHECKING )
50+ #if !defined(HAVE_BITSCAN_REVERSE ) || defined(USE_ASSERT_CHECKING )
3351 int result ;
3452 int shift = 32 - 8 ;
3553
@@ -41,13 +59,20 @@ pg_leftmost_one_pos32(uint32 word)
4159 result = shift + pg_leftmost_one_pos [(word >> shift ) & 255 ];
4260#endif
4361
62+ #ifdef HAVE_BITSCAN_REVERSE
63+
4464#if defined(HAVE__BUILTIN_CLZ )
4565 bitscan_result = 31 - __builtin_clz (word );
66+ #elif defined(_MSC_VER )
67+ non_zero = _BitScanReverse (& bitscan_result , word );
68+ Assert (non_zero );
69+ #endif
4670 Assert (bitscan_result == result );
4771 return bitscan_result ;
72+
4873#else
4974 return result ;
50- #endif /* HAVE__BUILTIN_CLZ */
75+ #endif /* HAVE_BITSCAN_REVERSE */
5176}
5277
5378/*
@@ -59,9 +84,12 @@ pg_leftmost_one_pos64(uint64 word)
5984{
6085#ifdef HAVE__BUILTIN_CLZ
6186 int bitscan_result ;
87+ #elif defined(_MSC_VER )
88+ unsigned long bitscan_result ;
89+ bool non_zero ;
6290#endif
6391
64- #if !defined(HAVE__BUILTIN_CLZ ) || defined(USE_ASSERT_CHECKING )
92+ #if !defined(HAVE_BITSCAN_REVERSE ) || defined(USE_ASSERT_CHECKING )
6593 int result ;
6694 int shift = 64 - 8 ;
6795
@@ -73,6 +101,8 @@ pg_leftmost_one_pos64(uint64 word)
73101 result = shift + pg_leftmost_one_pos [(word >> shift ) & 255 ];
74102#endif
75103
104+ #ifdef HAVE_BITSCAN_REVERSE
105+
76106#if defined(HAVE__BUILTIN_CLZ )
77107#if defined(HAVE_LONG_INT_64 )
78108 bitscan_result = 63 - __builtin_clzl (word );
@@ -81,11 +111,17 @@ pg_leftmost_one_pos64(uint64 word)
81111#else
82112#error must have a working 64-bit integer datatype
83113#endif /* HAVE_LONG_INT_64 */
114+
115+ #elif defined(_MSC_VER )
116+ non_zero = _BitScanReverse64 (& bitscan_result , word );
117+ Assert (non_zero );
118+ #endif /* HAVE__BUILTIN_CLZ */
84119 Assert (bitscan_result == result );
85120 return bitscan_result ;
121+
86122#else
87123 return result ;
88- #endif /* HAVE__BUILTIN_CLZ */
124+ #endif /* HAVE_BITSCAN_REVERSE */
89125}
90126
91127/*
@@ -99,9 +135,13 @@ pg_rightmost_one_pos32(uint32 word)
99135#ifdef HAVE__BUILTIN_CTZ
100136 const uint32 orig_word = word ;
101137 int bitscan_result ;
138+ #elif defined(_MSC_VER )
139+ const unsigned long orig_word = word ;
140+ unsigned long bitscan_result ;
141+ bool non_zero ;
102142#endif
103143
104- #if !defined(HAVE__BUILTIN_CTZ ) || defined(USE_ASSERT_CHECKING )
144+ #if !defined(HAVE_BITSCAN_FORWARD ) || defined(USE_ASSERT_CHECKING )
105145 int result = 0 ;
106146
107147 Assert (word != 0 );
@@ -114,13 +154,20 @@ pg_rightmost_one_pos32(uint32 word)
114154 result += pg_rightmost_one_pos [word & 255 ];
115155#endif
116156
157+ #ifdef HAVE_BITSCAN_FORWARD
158+
117159#if defined(HAVE__BUILTIN_CTZ )
118160 bitscan_result = __builtin_ctz (orig_word );
161+ #elif defined(_MSC_VER )
162+ non_zero = _BitScanForward (& bitscan_result , orig_word );
163+ Assert (non_zero );
164+ #endif
119165 Assert (bitscan_result == result );
120166 return bitscan_result ;
167+
121168#else
122169 return result ;
123- #endif /* HAVE__BUILTIN_CTZ */
170+ #endif /* HAVE_BITSCAN_FORWARD */
124171}
125172
126173/*
@@ -133,9 +180,13 @@ pg_rightmost_one_pos64(uint64 word)
133180#ifdef HAVE__BUILTIN_CTZ
134181 const uint64 orig_word = word ;
135182 int bitscan_result ;
183+ #elif defined(_MSC_VER )
184+ const unsigned __int64 orig_word = word ;
185+ unsigned long bitscan_result ;
186+ bool non_zero ;
136187#endif
137188
138- #if !defined(HAVE__BUILTIN_CTZ ) || defined(USE_ASSERT_CHECKING )
189+ #if !defined(HAVE_BITSCAN_FORWARD ) || defined(USE_ASSERT_CHECKING )
139190 int result = 0 ;
140191
141192 Assert (word != 0 );
@@ -148,6 +199,8 @@ pg_rightmost_one_pos64(uint64 word)
148199 result += pg_rightmost_one_pos [word & 255 ];
149200#endif
150201
202+ #ifdef HAVE_BITSCAN_FORWARD
203+
151204#if defined(HAVE__BUILTIN_CTZ )
152205#if defined(HAVE_LONG_INT_64 )
153206 bitscan_result = __builtin_ctzl (orig_word );
@@ -156,11 +209,17 @@ pg_rightmost_one_pos64(uint64 word)
156209#else
157210#error must have a working 64-bit integer datatype
158211#endif /* HAVE_LONG_INT_64 */
212+
213+ #elif defined(_MSC_VER )
214+ non_zero = _BitScanForward64 (& bitscan_result , orig_word );
215+ Assert (non_zero );
216+ #endif /* HAVE__BUILTIN_CTZ */
159217 Assert (bitscan_result == result );
160218 return bitscan_result ;
219+
161220#else
162221 return result ;
163- #endif /* HAVE__BUILTIN_CTZ */
222+ #endif /* HAVE_BITSCAN_FORWARD */
164223}
165224
166225/*
0 commit comments