Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commitcc4826d

Browse files
Inline pg_popcount{32,64} into pg_popcount().
On some systems, calls to pg_popcount{32,64} are indirected througha function pointer. This commit converts pg_popcount() to afunction pointer on those systems so that we can inline theappropriate pg_popcount{32,64} implementations into each of thepg_popcount() implementations. Since pg_popcount() may callpg_popcount{32,64} several times, this can significantly improveits performance.Suggested-by: David RowleyReviewed-by: David RowleyDiscussion:https://postgr.es/m/CAApHDvrb7MJRB6JuKLDEY2x_LKdFHwVbogpjZBCX547i5%2BrXOQ%40mail.gmail.com
1 parentb7e2121 commitcc4826d

File tree

2 files changed

+121
-39
lines changed

2 files changed

+121
-39
lines changed

‎src/include/port/pg_bitutils.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,17 +302,16 @@ pg_ceil_log2_64(uint64 num)
302302
/* Attempt to use the POPCNT instruction, but perform a runtime check first */
303303
externPGDLLIMPORTint (*pg_popcount32) (uint32word);
304304
externPGDLLIMPORTint (*pg_popcount64) (uint64word);
305+
externPGDLLIMPORTuint64 (*pg_popcount) (constchar*buf,intbytes);
305306

306307
#else
307308
/* Use a portable implementation -- no need for a function pointer. */
308309
externintpg_popcount32(uint32word);
309310
externintpg_popcount64(uint64word);
311+
externuint64pg_popcount(constchar*buf,intbytes);
310312

311313
#endif/* TRY_POPCNT_FAST */
312314

313-
/* Count the number of one-bits in a byte array */
314-
externuint64pg_popcount(constchar*buf,intbytes);
315-
316315
/*
317316
* Rotate the bits of "word" to the right/left by n bits.
318317
*/

‎src/port/pg_bitutils.c

Lines changed: 119 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,22 @@ 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-
staticintpg_popcount32_slow(uint32word);
107-
staticintpg_popcount64_slow(uint64word);
106+
staticinlineintpg_popcount32_slow(uint32word);
107+
staticinlineintpg_popcount64_slow(uint64word);
108+
staticuint64pg_popcount_slow(constchar*buf,intbytes);
108109

109110
#ifdefTRY_POPCNT_FAST
110111
staticboolpg_popcount_available(void);
111112
staticintpg_popcount32_choose(uint32word);
112113
staticintpg_popcount64_choose(uint64word);
113-
staticintpg_popcount32_fast(uint32word);
114-
staticintpg_popcount64_fast(uint64word);
114+
staticuint64pg_popcount_choose(constchar*buf,intbytes);
115+
staticinlineintpg_popcount32_fast(uint32word);
116+
staticinlineintpg_popcount64_fast(uint64word);
117+
staticuint64pg_popcount_fast(constchar*buf,intbytes);
115118

116119
int(*pg_popcount32) (uint32word)=pg_popcount32_choose;
117120
int(*pg_popcount64) (uint64word)=pg_popcount64_choose;
121+
uint64(*pg_popcount) (constchar*buf,intbytes)=pg_popcount_choose;
118122
#endif/* TRY_POPCNT_FAST */
119123

120124
#ifdefTRY_POPCNT_FAST
@@ -151,11 +155,13 @@ pg_popcount32_choose(uint32 word)
151155
{
152156
pg_popcount32=pg_popcount32_fast;
153157
pg_popcount64=pg_popcount64_fast;
158+
pg_popcount=pg_popcount_fast;
154159
}
155160
else
156161
{
157162
pg_popcount32=pg_popcount32_slow;
158163
pg_popcount64=pg_popcount64_slow;
164+
pg_popcount=pg_popcount_slow;
159165
}
160166

161167
returnpg_popcount32(word);
@@ -168,21 +174,42 @@ pg_popcount64_choose(uint64 word)
168174
{
169175
pg_popcount32=pg_popcount32_fast;
170176
pg_popcount64=pg_popcount64_fast;
177+
pg_popcount=pg_popcount_fast;
171178
}
172179
else
173180
{
174181
pg_popcount32=pg_popcount32_slow;
175182
pg_popcount64=pg_popcount64_slow;
183+
pg_popcount=pg_popcount_slow;
176184
}
177185

178186
returnpg_popcount64(word);
179187
}
180188

189+
staticuint64
190+
pg_popcount_choose(constchar*buf,intbytes)
191+
{
192+
if (pg_popcount_available())
193+
{
194+
pg_popcount32=pg_popcount32_fast;
195+
pg_popcount64=pg_popcount64_fast;
196+
pg_popcount=pg_popcount_fast;
197+
}
198+
else
199+
{
200+
pg_popcount32=pg_popcount32_slow;
201+
pg_popcount64=pg_popcount64_slow;
202+
pg_popcount=pg_popcount_slow;
203+
}
204+
205+
returnpg_popcount(buf,bytes);
206+
}
207+
181208
/*
182209
* pg_popcount32_fast
183210
*Return the number of 1 bits set in word
184211
*/
185-
staticint
212+
staticinlineint
186213
pg_popcount32_fast(uint32word)
187214
{
188215
#ifdef_MSC_VER
@@ -199,7 +226,7 @@ __asm__ __volatile__(" popcntl %1,%0\n":"=q"(res):"rm"(word):"cc");
199226
* pg_popcount64_fast
200227
*Return the number of 1 bits set in word
201228
*/
202-
staticint
229+
staticinlineint
203230
pg_popcount64_fast(uint64word)
204231
{
205232
#ifdef_MSC_VER
@@ -212,14 +239,60 @@ __asm__ __volatile__(" popcntq %1,%0\n":"=q"(res):"rm"(word):"cc");
212239
#endif
213240
}
214241

242+
/*
243+
* pg_popcount_fast
244+
*Returns the number of 1-bits in buf
245+
*/
246+
staticuint64
247+
pg_popcount_fast(constchar*buf,intbytes)
248+
{
249+
uint64popcnt=0;
250+
251+
#ifSIZEOF_VOID_P >=8
252+
/* Process in 64-bit chunks if the buffer is aligned. */
253+
if (buf== (constchar*)TYPEALIGN(8,buf))
254+
{
255+
constuint64*words= (constuint64*)buf;
256+
257+
while (bytes >=8)
258+
{
259+
popcnt+=pg_popcount64_fast(*words++);
260+
bytes-=8;
261+
}
262+
263+
buf= (constchar*)words;
264+
}
265+
#else
266+
/* Process in 32-bit chunks if the buffer is aligned. */
267+
if (buf== (constchar*)TYPEALIGN(4,buf))
268+
{
269+
constuint32*words= (constuint32*)buf;
270+
271+
while (bytes >=4)
272+
{
273+
popcnt+=pg_popcount32_fast(*words++);
274+
bytes-=4;
275+
}
276+
277+
buf= (constchar*)words;
278+
}
279+
#endif
280+
281+
/* Process any remaining bytes */
282+
while (bytes--)
283+
popcnt+=pg_number_of_ones[(unsignedchar)*buf++];
284+
285+
returnpopcnt;
286+
}
287+
215288
#endif/* TRY_POPCNT_FAST */
216289

217290

218291
/*
219292
* pg_popcount32_slow
220293
*Return the number of 1 bits set in word
221294
*/
222-
staticint
295+
staticinlineint
223296
pg_popcount32_slow(uint32word)
224297
{
225298
#ifdefHAVE__BUILTIN_POPCOUNT
@@ -241,7 +314,7 @@ pg_popcount32_slow(uint32 word)
241314
* pg_popcount64_slow
242315
*Return the number of 1 bits set in word
243316
*/
244-
staticint
317+
staticinlineint
245318
pg_popcount64_slow(uint64word)
246319
{
247320
#ifdefHAVE__BUILTIN_POPCOUNT
@@ -265,35 +338,12 @@ pg_popcount64_slow(uint64 word)
265338
#endif/* HAVE__BUILTIN_POPCOUNT */
266339
}
267340

268-
#ifndefTRY_POPCNT_FAST
269-
270341
/*
271-
* When the POPCNT instruction is not available, there's no point in using
272-
* function pointers to vary the implementation between the fast and slow
273-
* method. We instead just make these actual external functions when
274-
* TRY_POPCNT_FAST is not defined. The compiler should be able to inline
275-
* the slow versions here.
276-
*/
277-
int
278-
pg_popcount32(uint32word)
279-
{
280-
returnpg_popcount32_slow(word);
281-
}
282-
283-
int
284-
pg_popcount64(uint64word)
285-
{
286-
returnpg_popcount64_slow(word);
287-
}
288-
289-
#endif/* !TRY_POPCNT_FAST */
290-
291-
/*
292-
* pg_popcount
342+
* pg_popcount_slow
293343
*Returns the number of 1-bits in buf
294344
*/
295-
uint64
296-
pg_popcount(constchar*buf,intbytes)
345+
staticuint64
346+
pg_popcount_slow(constchar*buf,intbytes)
297347
{
298348
uint64popcnt=0;
299349

@@ -305,7 +355,7 @@ pg_popcount(const char *buf, int bytes)
305355

306356
while (bytes >=8)
307357
{
308-
popcnt+=pg_popcount64(*words++);
358+
popcnt+=pg_popcount64_slow(*words++);
309359
bytes-=8;
310360
}
311361

@@ -319,7 +369,7 @@ pg_popcount(const char *buf, int bytes)
319369

320370
while (bytes >=4)
321371
{
322-
popcnt+=pg_popcount32(*words++);
372+
popcnt+=pg_popcount32_slow(*words++);
323373
bytes-=4;
324374
}
325375

@@ -333,3 +383,36 @@ pg_popcount(const char *buf, int bytes)
333383

334384
returnpopcnt;
335385
}
386+
387+
#ifndefTRY_POPCNT_FAST
388+
389+
/*
390+
* When the POPCNT instruction is not available, there's no point in using
391+
* function pointers to vary the implementation between the fast and slow
392+
* method. We instead just make these actual external functions when
393+
* TRY_POPCNT_FAST is not defined. The compiler should be able to inline
394+
* the slow versions here.
395+
*/
396+
int
397+
pg_popcount32(uint32word)
398+
{
399+
returnpg_popcount32_slow(word);
400+
}
401+
402+
int
403+
pg_popcount64(uint64word)
404+
{
405+
returnpg_popcount64_slow(word);
406+
}
407+
408+
/*
409+
* pg_popcount
410+
*Returns the number of 1-bits in buf
411+
*/
412+
uint64
413+
pg_popcount(constchar*buf,intbytes)
414+
{
415+
returnpg_popcount_slow(buf,bytes);
416+
}
417+
418+
#endif/* !TRY_POPCNT_FAST */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp