Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2e28124

Browse files
committed
Add POPCNT support for MSVC x86_64 builds
02a6a54 added code to make use of the POPCNT instruction when available for many of our common platforms. Here we do the same for MSVC for x86_64 machines. MSVC's intrinsic functions for popcnt seem to differ from GCCs in that they always appear to emit the popcnt instructions. In GCC the behavior will depend on if the source file was compiled with -mpopcnt or not. For this reason, the MSVC intrinsic function has been lumped into the pg_popcount*_asm function, however doing that sort of invalidates the name of that function, so let's rename it to pg_popcount*_fast(). Author: David Rowley Reviewed-by: John Naylor Discussion: https://postgr.es/m/CAApHDvqL3cbbK%3DGzNcwzsNR9Gi%2BaUvTudKkC4XgnQfXirJ_oRQ%40mail.gmail.com
1 parent d8a75b1 commit 2e28124

File tree

1 file changed

+33
-15
lines changed

1 file changed

+33
-15
lines changed

src/port/pg_bitutils.c

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@ const uint8 pg_number_of_ones[256] = {
103103
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
104104
};
105105

106+
/*
107+
* With MSVC on x86_64 builds, try using native popcnt instructions via the
108+
* __popcnt and __popcnt64 intrinsics. These don't work the same as GCC's
109+
* __builtin_popcount* intrinsic functions as they always emit popcnt
110+
* instructions.
111+
*/
112+
#if defined(_MSC_VER) && defined(_M_AMD64)
113+
#define HAVE_X86_64_POPCNTQ
114+
#endif
115+
106116
/*
107117
* On x86_64, we can use the hardware popcount instruction, but only if
108118
* we can verify that the CPU supports it via the cpuid instruction.
@@ -112,28 +122,28 @@ const uint8 pg_number_of_ones[256] = {
112122
*/
113123
#ifdef HAVE_X86_64_POPCNTQ
114124
#if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID)
115-
#define USE_POPCNT_ASM 1
125+
#define TRY_POPCNT_FAST 1
116126
#endif
117127
#endif
118128

119129
static int pg_popcount32_slow(uint32 word);
120130
static int pg_popcount64_slow(uint64 word);
121131

122-
#ifdef USE_POPCNT_ASM
132+
#ifdef TRY_POPCNT_FAST
123133
static bool pg_popcount_available(void);
124134
static int pg_popcount32_choose(uint32 word);
125135
static int pg_popcount64_choose(uint64 word);
126-
static int pg_popcount32_asm(uint32 word);
127-
static int pg_popcount64_asm(uint64 word);
136+
static int pg_popcount32_fast(uint32 word);
137+
static int pg_popcount64_fast(uint64 word);
128138

129139
int (*pg_popcount32) (uint32 word) = pg_popcount32_choose;
130140
int (*pg_popcount64) (uint64 word) = pg_popcount64_choose;
131141
#else
132142
int (*pg_popcount32) (uint32 word) = pg_popcount32_slow;
133143
int (*pg_popcount64) (uint64 word) = pg_popcount64_slow;
134-
#endif /* USE_POPCNT_ASM */
144+
#endif /* TRY_POPCNT_FAST */
135145

136-
#ifdef USE_POPCNT_ASM
146+
#ifdef TRY_POPCNT_FAST
137147

138148
/*
139149
* Return true if CPUID indicates that the POPCNT instruction is available.
@@ -165,8 +175,8 @@ pg_popcount32_choose(uint32 word)
165175
{
166176
if (pg_popcount_available())
167177
{
168-
pg_popcount32 = pg_popcount32_asm;
169-
pg_popcount64 = pg_popcount64_asm;
178+
pg_popcount32 = pg_popcount32_fast;
179+
pg_popcount64 = pg_popcount64_fast;
170180
}
171181
else
172182
{
@@ -182,8 +192,8 @@ pg_popcount64_choose(uint64 word)
182192
{
183193
if (pg_popcount_available())
184194
{
185-
pg_popcount32 = pg_popcount32_asm;
186-
pg_popcount64 = pg_popcount64_asm;
195+
pg_popcount32 = pg_popcount32_fast;
196+
pg_popcount64 = pg_popcount64_fast;
187197
}
188198
else
189199
{
@@ -195,32 +205,40 @@ pg_popcount64_choose(uint64 word)
195205
}
196206

197207
/*
198-
* pg_popcount32_asm
208+
* pg_popcount32_fast
199209
* Return the number of 1 bits set in word
200210
*/
201211
static int
202-
pg_popcount32_asm(uint32 word)
212+
pg_popcount32_fast(uint32 word)
203213
{
214+
#ifdef _MSC_VER
215+
return __popcnt(word);
216+
#else
204217
uint32 res;
205218

206219
__asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc");
207220
return (int) res;
221+
#endif
208222
}
209223

210224
/*
211-
* pg_popcount64_asm
225+
* pg_popcount64_fast
212226
* Return the number of 1 bits set in word
213227
*/
214228
static int
215-
pg_popcount64_asm(uint64 word)
229+
pg_popcount64_fast(uint64 word)
216230
{
231+
#ifdef _MSC_VER
232+
return __popcnt64(word);
233+
#else
217234
uint64 res;
218235

219236
__asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc");
220237
return (int) res;
238+
#endif
221239
}
222240

223-
#endif /* USE_POPCNT_ASM */
241+
#endif /* TRY_POPCNT_FAST */
224242

225243

226244
/*

0 commit comments

Comments
 (0)