PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_bitutils.h
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_bitutils.h
4 * Miscellaneous functions for bit-wise operations.
5 *
6 *
7 * Copyright (c) 2019-2026, PostgreSQL Global Development Group
8 *
9 * src/include/port/pg_bitutils.h
10 *
11 *-------------------------------------------------------------------------
12 */
13#ifndef PG_BITUTILS_H
14#define PG_BITUTILS_H
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
31extern PGDLLIMPORT const uint8 pg_leftmost_one_pos[256];
32extern PGDLLIMPORT const uint8 pg_rightmost_one_pos[256];
33extern PGDLLIMPORT const uint8 pg_number_of_ones[256];
34
35/*
36 * pg_leftmost_one_pos32
37 * Returns the position of the most significant set bit in "word",
38 * measured from the least significant bit. word must not be 0.
39 */
40static inline int
42{
43#ifdef HAVE__BUILTIN_CLZ
44 Assert(word != 0);
45
46 return 31 - __builtin_clz(word);
47#elif defined(_MSC_VER)
48 unsigned long result;
49 bool non_zero;
50
51 Assert(word != 0);
52
53 non_zero = _BitScanReverse(&result, word);
54 return (int) result;
55#else
56 int shift = 32 - 8;
57
58 Assert(word != 0);
59
60 while ((word >> shift) == 0)
61 shift -= 8;
62
63 return shift + pg_leftmost_one_pos[(word >> shift) & 255];
64#endif /* HAVE__BUILTIN_CLZ */
65}
66
67/*
68 * pg_leftmost_one_pos64
69 * As above, but for a 64-bit word.
70 */
71static inline int
73{
74#ifdef HAVE__BUILTIN_CLZ
75 Assert(word != 0);
76
77#if SIZEOF_LONG == 8
78 return 63 - __builtin_clzl(word);
79#elif SIZEOF_LONG_LONG == 8
80 return 63 - __builtin_clzll(word);
81#else
82#error "cannot find integer type of the same size as uint64_t"
83#endif
84
85#elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
86 unsigned long result;
87 bool non_zero;
88
89 Assert(word != 0);
90
92 return (int) result;
93#else
94 int shift = 64 - 8;
95
96 Assert(word != 0);
97
98 while ((word >> shift) == 0)
99 shift -= 8;
100
101 return shift + pg_leftmost_one_pos[(word >> shift) & 255];
102#endif /* HAVE__BUILTIN_CLZ */
103}
104
105/*
106 * pg_rightmost_one_pos32
107 * Returns the position of the least significant set bit in "word",
108 * measured from the least significant bit. word must not be 0.
109 */
110static inline int
112{
113#ifdef HAVE__BUILTIN_CTZ
114 Assert(word != 0);
115
116 return __builtin_ctz(word);
117#elif defined(_MSC_VER)
118 unsigned long result;
119 bool non_zero;
120
121 Assert(word != 0);
122
123 non_zero = _BitScanForward(&result, word);
124 return (int) result;
125#else
126 int result = 0;
127
128 Assert(word != 0);
129
130 while ((word & 255) == 0)
131 {
132 word >>= 8;
133 result += 8;
134 }
135 result += pg_rightmost_one_pos[word & 255];
136 return result;
137#endif /* HAVE__BUILTIN_CTZ */
138}
139
140/*
141 * pg_rightmost_one_pos64
142 * As above, but for a 64-bit word.
143 */
144static inline int
146{
147#ifdef HAVE__BUILTIN_CTZ
148 Assert(word != 0);
149
150#if SIZEOF_LONG == 8
151 return __builtin_ctzl(word);
152#elif SIZEOF_LONG_LONG == 8
153 return __builtin_ctzll(word);
154#else
155#error "cannot find integer type of the same size as uint64_t"
156#endif
157
158#elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
159 unsigned long result;
160 bool non_zero;
161
162 Assert(word != 0);
163
164 non_zero = _BitScanForward64(&result, word);
165 return (int) result;
166#else
167 int result = 0;
168
169 Assert(word != 0);
170
171 while ((word & 255) == 0)
172 {
173 word >>= 8;
174 result += 8;
175 }
176 result += pg_rightmost_one_pos[word & 255];
177 return result;
178#endif /* HAVE__BUILTIN_CTZ */
179}
180
181/*
182 * pg_nextpower2_32
183 * Returns the next higher power of 2 above 'num', or 'num' if it's
184 * already a power of 2.
185 *
186 * 'num' mustn't be 0 or be above PG_UINT32_MAX / 2 + 1.
187 */
188static inline uint32
190{
191 Assert(num > 0 && num <= PG_UINT32_MAX / 2 + 1);
192
193 /*
194 * A power 2 number has only 1 bit set. Subtracting 1 from such a number
195 * will turn on all previous bits resulting in no common bits being set
196 * between num and num-1.
197 */
198 if ((num & (num - 1)) == 0)
199 return num; /* already power 2 */
200
201 return ((uint32) 1) << (pg_leftmost_one_pos32(num) + 1);
202}
203
204/*
205 * pg_nextpower2_64
206 * Returns the next higher power of 2 above 'num', or 'num' if it's
207 * already a power of 2.
208 *
209 * 'num' mustn't be 0 or be above PG_UINT64_MAX / 2 + 1.
210 */
211static inline uint64
213{
214 Assert(num > 0 && num <= PG_UINT64_MAX / 2 + 1);
215
216 /*
217 * A power 2 number has only 1 bit set. Subtracting 1 from such a number
218 * will turn on all previous bits resulting in no common bits being set
219 * between num and num-1.
220 */
221 if ((num & (num - 1)) == 0)
222 return num; /* already power 2 */
223
224 return ((uint64) 1) << (pg_leftmost_one_pos64(num) + 1);
225}
226
227/*
228 * pg_prevpower2_32
229 * Returns the next lower power of 2 below 'num', or 'num' if it's
230 * already a power of 2.
231 *
232 * 'num' mustn't be 0.
233 */
234static inline uint32
236{
237 return ((uint32) 1) << pg_leftmost_one_pos32(num);
238}
239
240/*
241 * pg_prevpower2_64
242 * Returns the next lower power of 2 below 'num', or 'num' if it's
243 * already a power of 2.
244 *
245 * 'num' mustn't be 0.
246 */
247static inline uint64
249{
250 return ((uint64) 1) << pg_leftmost_one_pos64(num);
251}
252
253/*
254 * pg_ceil_log2_32
255 * Returns equivalent of ceil(log2(num))
256 */
257static inline uint32
259{
260 if (num < 2)
261 return 0;
262 else
263 return pg_leftmost_one_pos32(num - 1) + 1;
264}
265
266/*
267 * pg_ceil_log2_64
268 * Returns equivalent of ceil(log2(num))
269 */
270static inline uint64
272{
273 if (num < 2)
274 return 0;
275 else
276 return pg_leftmost_one_pos64(num - 1) + 1;
277}
278
279extern uint64 pg_popcount_portable(const char *buf, int bytes);
280extern uint64 pg_popcount_masked_portable(const char *buf, int bytes, bits8 mask);
281
282#if defined(HAVE_X86_64_POPCNTQ) || defined(USE_SVE_POPCNT_WITH_RUNTIME_CHECK)
283/*
284 * Attempt to use specialized CPU instructions, but perform a runtime check
285 * first.
286 */
287extern PGDLLIMPORT uint64 (*pg_popcount_optimized) (const char *buf, int bytes);
288extern PGDLLIMPORT uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask);
289
290#else
291/* Use a portable implementation -- no need for a function pointer. */
292extern uint64 pg_popcount_optimized(const char *buf, int bytes);
293extern uint64 pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask);
294
295#endif
296
297/*
298 * pg_popcount32
299 * Return the number of 1 bits set in word
300 *
301 * Adapted from
302 * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel.
303 *
304 * Note that newer versions of popular compilers will automatically replace
305 * this with a special popcount instruction if possible, so we don't bother
306 * using builtin functions or intrinsics.
307 */
308static inline int
310{
311 word -= (word >> 1) & 0x55555555;
312 word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
313 return (((word + (word >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
314}
315
316/*
317 * pg_popcount64
318 * Return the number of 1 bits set in word
319 *
320 * Adapted from
321 * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel.
322 *
323 * Note that newer versions of popular compilers will automatically replace
324 * this with a special popcount instruction if possible, so we don't bother
325 * using builtin functions or intrinsics.
326 */
327static inline int
329{
330 word -= (word >> 1) & UINT64CONST(0x5555555555555555);
331 word = (word & UINT64CONST(0x3333333333333333)) +
332 ((word >> 2) & UINT64CONST(0x3333333333333333));
333 word = (word + (word >> 4)) & UINT64CONST(0xf0f0f0f0f0f0f0f);
334 return (word * UINT64CONST(0x101010101010101)) >> 56;
335}
336
337/*
338 * Returns the number of 1-bits in buf.
339 *
340 * If there aren't many bytes to process, the function call overhead of the
341 * optimized versions isn't worth taking, so we inline a loop that consults
342 * pg_number_of_ones in that case. If there are many bytes to process, we
343 * accept the function call overhead because the optimized versions are likely
344 * to be faster.
345 */
346static inline uint64
347pg_popcount(const char *buf, int bytes)
348{
349 /*
350 * We set the threshold to the point at which we'll first use special
351 * instructions in the optimized version.
352 */
353 if (bytes < 8)
354 {
355 uint64 popcnt = 0;
356
357 while (bytes--)
358 popcnt += pg_number_of_ones[(unsigned char) *buf++];
359 return popcnt;
360 }
361
362 return pg_popcount_optimized(buf, bytes);
363}
364
365/*
366 * Returns the number of 1-bits in buf after applying the mask to each byte.
367 *
368 * Similar to pg_popcount(), we only take on the function pointer overhead when
369 * it's likely to be faster.
370 */
371static inline uint64
372pg_popcount_masked(const char *buf, int bytes, bits8 mask)
373{
374 /*
375 * We set the threshold to the point at which we'll first use special
376 * instructions in the optimized version.
377 */
378 if (bytes < 8)
379 {
380 uint64 popcnt = 0;
381
382 while (bytes--)
383 popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask];
384 return popcnt;
385 }
386
387 return pg_popcount_masked_optimized(buf, bytes, mask);
388}
389
390/*
391 * Rotate the bits of "word" to the right/left by n bits.
392 */
393static inline uint32
395{
396 return (word >> n) | (word << (32 - n));
397}
398
399static inline uint32
401{
402 return (word << n) | (word >> (32 - n));
403}
404
405/* size_t variants of the above, as required */
406
407#if SIZEOF_SIZE_T == 4
408#define pg_leftmost_one_pos_size_t pg_leftmost_one_pos32
409#define pg_nextpower2_size_t pg_nextpower2_32
410#define pg_prevpower2_size_t pg_prevpower2_32
411#else
412#define pg_leftmost_one_pos_size_t pg_leftmost_one_pos64
413#define pg_nextpower2_size_t pg_nextpower2_64
414#define pg_prevpower2_size_t pg_prevpower2_64
415#endif
416
417#endif /* PG_BITUTILS_H */
#define PGDLLIMPORT
Definition c.h:1356
uint8_t uint8
Definition c.h:556
#define PG_UINT32_MAX
Definition c.h:616
#define Assert(condition)
Definition c.h:885
uint8 bits8
Definition c.h:565
uint64_t uint64
Definition c.h:559
uint32_t uint32
Definition c.h:558
#define PG_UINT64_MAX
Definition c.h:619
#define UINT64CONST(x)
Definition c.h:573
uint64 pg_popcount_portable(const char *buf, int bytes)
uint64 pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask)
PGDLLIMPORT const uint8 pg_number_of_ones[256]
Definition pg_bitutils.c:80
uint64 pg_popcount_masked_portable(const char *buf, int bytes, bits8 mask)
static uint32 pg_rotate_left32(uint32 word, int n)
static int pg_rightmost_one_pos64(uint64 word)
static uint32 pg_nextpower2_32(uint32 num)
static uint64 pg_ceil_log2_64(uint64 num)
static uint32 pg_rotate_right32(uint32 word, int n)
uint64 pg_popcount_optimized(const char *buf, int bytes)
static int pg_rightmost_one_pos32(uint32 word)
static uint64 pg_nextpower2_64(uint64 num)
static int pg_popcount64(uint64 word)
static int pg_leftmost_one_pos32(uint32 word)
Definition pg_bitutils.h:41
static int pg_popcount32(uint32 word)
PGDLLIMPORT const uint8 pg_rightmost_one_pos[256]
Definition pg_bitutils.c:55
static uint32 pg_ceil_log2_32(uint32 num)
static uint64 pg_popcount(const char *buf, int bytes)
static uint32 pg_prevpower2_32(uint32 num)
static uint64 pg_prevpower2_64(uint64 num)
static uint64 pg_popcount_masked(const char *buf, int bytes, bits8 mask)
PGDLLIMPORT const uint8 pg_leftmost_one_pos[256]
Definition pg_bitutils.c:27
static int pg_leftmost_one_pos64(uint64 word)
Definition pg_bitutils.h:72
static char buf[DEFAULT_XLOG_SEG_SIZE]
static int fb(int x)
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition regcomp.c:1476