13
13
#ifndef PG_BITUTILS_H
14
14
#define PG_BITUTILS_H
15
15
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
+
16
31
extern PGDLLIMPORT const uint8 pg_leftmost_one_pos [256 ];
17
32
extern PGDLLIMPORT const uint8 pg_rightmost_one_pos [256 ];
18
33
extern PGDLLIMPORT const uint8 pg_number_of_ones [256 ];
@@ -27,9 +42,12 @@ pg_leftmost_one_pos32(uint32 word)
27
42
{
28
43
#ifdef HAVE__BUILTIN_CLZ
29
44
int bitscan_result ;
45
+ #elif defined(_MSC_VER )
46
+ unsigned long bitscan_result ;
47
+ bool non_zero ;
30
48
#endif
31
49
32
- #if !defined(HAVE__BUILTIN_CLZ ) || defined(USE_ASSERT_CHECKING )
50
+ #if !defined(HAVE_BITSCAN_REVERSE ) || defined(USE_ASSERT_CHECKING )
33
51
int result ;
34
52
int shift = 32 - 8 ;
35
53
@@ -41,13 +59,20 @@ pg_leftmost_one_pos32(uint32 word)
41
59
result = shift + pg_leftmost_one_pos [(word >> shift ) & 255 ];
42
60
#endif
43
61
62
+ #ifdef HAVE_BITSCAN_REVERSE
63
+
44
64
#if defined(HAVE__BUILTIN_CLZ )
45
65
bitscan_result = 31 - __builtin_clz (word );
66
+ #elif defined(_MSC_VER )
67
+ non_zero = _BitScanReverse (& bitscan_result , word );
68
+ Assert (non_zero );
69
+ #endif
46
70
Assert (bitscan_result == result );
47
71
return bitscan_result ;
72
+
48
73
#else
49
74
return result ;
50
- #endif /* HAVE__BUILTIN_CLZ */
75
+ #endif /* HAVE_BITSCAN_REVERSE */
51
76
}
52
77
53
78
/*
@@ -59,9 +84,12 @@ pg_leftmost_one_pos64(uint64 word)
59
84
{
60
85
#ifdef HAVE__BUILTIN_CLZ
61
86
int bitscan_result ;
87
+ #elif defined(_MSC_VER )
88
+ unsigned long bitscan_result ;
89
+ bool non_zero ;
62
90
#endif
63
91
64
- #if !defined(HAVE__BUILTIN_CLZ ) || defined(USE_ASSERT_CHECKING )
92
+ #if !defined(HAVE_BITSCAN_REVERSE ) || defined(USE_ASSERT_CHECKING )
65
93
int result ;
66
94
int shift = 64 - 8 ;
67
95
@@ -73,6 +101,8 @@ pg_leftmost_one_pos64(uint64 word)
73
101
result = shift + pg_leftmost_one_pos [(word >> shift ) & 255 ];
74
102
#endif
75
103
104
+ #ifdef HAVE_BITSCAN_REVERSE
105
+
76
106
#if defined(HAVE__BUILTIN_CLZ )
77
107
#if defined(HAVE_LONG_INT_64 )
78
108
bitscan_result = 63 - __builtin_clzl (word );
@@ -81,11 +111,17 @@ pg_leftmost_one_pos64(uint64 word)
81
111
#else
82
112
#error must have a working 64-bit integer datatype
83
113
#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 */
84
119
Assert (bitscan_result == result );
85
120
return bitscan_result ;
121
+
86
122
#else
87
123
return result ;
88
- #endif /* HAVE__BUILTIN_CLZ */
124
+ #endif /* HAVE_BITSCAN_REVERSE */
89
125
}
90
126
91
127
/*
@@ -99,9 +135,13 @@ pg_rightmost_one_pos32(uint32 word)
99
135
#ifdef HAVE__BUILTIN_CTZ
100
136
const uint32 orig_word = word ;
101
137
int bitscan_result ;
138
+ #elif defined(_MSC_VER )
139
+ const unsigned long orig_word = word ;
140
+ unsigned long bitscan_result ;
141
+ bool non_zero ;
102
142
#endif
103
143
104
- #if !defined(HAVE__BUILTIN_CTZ ) || defined(USE_ASSERT_CHECKING )
144
+ #if !defined(HAVE_BITSCAN_FORWARD ) || defined(USE_ASSERT_CHECKING )
105
145
int result = 0 ;
106
146
107
147
Assert (word != 0 );
@@ -114,13 +154,20 @@ pg_rightmost_one_pos32(uint32 word)
114
154
result += pg_rightmost_one_pos [word & 255 ];
115
155
#endif
116
156
157
+ #ifdef HAVE_BITSCAN_FORWARD
158
+
117
159
#if defined(HAVE__BUILTIN_CTZ )
118
160
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
119
165
Assert (bitscan_result == result );
120
166
return bitscan_result ;
167
+
121
168
#else
122
169
return result ;
123
- #endif /* HAVE__BUILTIN_CTZ */
170
+ #endif /* HAVE_BITSCAN_FORWARD */
124
171
}
125
172
126
173
/*
@@ -133,9 +180,13 @@ pg_rightmost_one_pos64(uint64 word)
133
180
#ifdef HAVE__BUILTIN_CTZ
134
181
const uint64 orig_word = word ;
135
182
int bitscan_result ;
183
+ #elif defined(_MSC_VER )
184
+ const unsigned __int64 orig_word = word ;
185
+ unsigned long bitscan_result ;
186
+ bool non_zero ;
136
187
#endif
137
188
138
- #if !defined(HAVE__BUILTIN_CTZ ) || defined(USE_ASSERT_CHECKING )
189
+ #if !defined(HAVE_BITSCAN_FORWARD ) || defined(USE_ASSERT_CHECKING )
139
190
int result = 0 ;
140
191
141
192
Assert (word != 0 );
@@ -148,6 +199,8 @@ pg_rightmost_one_pos64(uint64 word)
148
199
result += pg_rightmost_one_pos [word & 255 ];
149
200
#endif
150
201
202
+ #ifdef HAVE_BITSCAN_FORWARD
203
+
151
204
#if defined(HAVE__BUILTIN_CTZ )
152
205
#if defined(HAVE_LONG_INT_64 )
153
206
bitscan_result = __builtin_ctzl (orig_word );
@@ -156,11 +209,17 @@ pg_rightmost_one_pos64(uint64 word)
156
209
#else
157
210
#error must have a working 64-bit integer datatype
158
211
#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 */
159
217
Assert (bitscan_result == result );
160
218
return bitscan_result ;
219
+
161
220
#else
162
221
return result ;
163
- #endif /* HAVE__BUILTIN_CTZ */
222
+ #endif /* HAVE_BITSCAN_FORWARD */
164
223
}
165
224
166
225
/*
0 commit comments