Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6773197

Browse filesBrowse files
committed
Add MSVC support for pg_leftmost_one_pos32() and friends
To allow testing for general support for fast bitscan intrinsics, add symbols HAVE_BITSCAN_REVERSE and HAVE_BITSCAN_FORWARD. Also do related cleanup in AllocSetFreeIndex(): Previously, we tested for HAVE__BUILTIN_CLZ and copied the relevant internals of pg_leftmost_one_pos32(), with a special fallback that does less work than the general fallback for that function. Now that we have a more general test, we just call pg_leftmost_one_pos32() directly for platforms with intrinsic support. On gcc at least, there is no difference in the binary for non-assert builds. Discussion: https://www.postgresql.org/message-id/CAFBsxsEPc%2BFnX_0vmmQ5DHv60sk4rL_RZJ%2BMD6ei%3D76L0kFMvA%40mail.gmail.com
1 parent 204b0cb commit 6773197
Copy full SHA for 6773197

File tree

2 files changed

+70
-11
lines changed
Filter options

2 files changed

+70
-11
lines changed

‎src/backend/utils/mmgr/aset.c

Copy file name to clipboardExpand all lines: src/backend/utils/mmgr/aset.c
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ AllocSetFreeIndex(Size size)
289289
* or equivalently
290290
* pg_leftmost_one_pos32(size - 1) - ALLOC_MINBITS + 1
291291
*
292-
* However, rather than just calling that function, we duplicate the
292+
* However, for platforms without intrinsic support, we duplicate the
293293
* logic here, allowing an additional optimization. It's reasonable
294294
* to assume that ALLOC_CHUNK_LIMIT fits in 16 bits, so we can unroll
295295
* the byte-at-a-time loop in pg_leftmost_one_pos32 and just handle
@@ -299,8 +299,8 @@ AllocSetFreeIndex(Size size)
299299
* much trouble.
300300
*----------
301301
*/
302-
#ifdef HAVE__BUILTIN_CLZ
303-
idx = 31 - __builtin_clz((uint32) size - 1) - ALLOC_MINBITS + 1;
302+
#ifdef HAVE_BITSCAN_REVERSE
303+
idx = pg_leftmost_one_pos32((uint32) size - 1) - ALLOC_MINBITS + 1;
304304
#else
305305
uint32 t,
306306
tsize;

‎src/include/port/pg_bitutils.h

Copy file name to clipboardExpand all lines: src/include/port/pg_bitutils.h
+67-8Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@
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+
1631
extern PGDLLIMPORT const uint8 pg_leftmost_one_pos[256];
1732
extern PGDLLIMPORT const uint8 pg_rightmost_one_pos[256];
1833
extern 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

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.