LCOV - code coverage report
Current view: top level - src/include/port - pg_bitutils.h (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 92.3 % 52 48
Test Date: 2026-03-16 21:15:04 Functions: 100.0 % 15 15
Legend: Lines:     hit not hit

            Line data    Source code
       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              : 
      31              : extern PGDLLIMPORT const uint8 pg_leftmost_one_pos[256];
      32              : extern PGDLLIMPORT const uint8 pg_rightmost_one_pos[256];
      33              : extern 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              :  */
      40              : static inline int
      41    713221625 : pg_leftmost_one_pos32(uint32 word)
      42              : {
      43              : #ifdef HAVE__BUILTIN_CLZ
      44              :     Assert(word != 0);
      45              : 
      46    713221625 :     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              :  */
      71              : static inline int
      72      2704042 : pg_leftmost_one_pos64(uint64 word)
      73              : {
      74              : #ifdef HAVE__BUILTIN_CLZ
      75              :     Assert(word != 0);
      76              : 
      77              : #if SIZEOF_LONG == 8
      78      2704042 :     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              : 
      91              :     non_zero = _BitScanReverse64(&result, word);
      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              :  */
     110              : static inline int
     111    119923858 : pg_rightmost_one_pos32(uint32 word)
     112              : {
     113              : #ifdef HAVE__BUILTIN_CTZ
     114              :     Assert(word != 0);
     115              : 
     116    119923858 :     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              :  */
     144              : static inline int
     145     12058386 : pg_rightmost_one_pos64(uint64 word)
     146              : {
     147              : #ifdef HAVE__BUILTIN_CTZ
     148              :     Assert(word != 0);
     149              : 
     150              : #if SIZEOF_LONG == 8
     151     12058386 :     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              :  */
     188              : static inline uint32
     189     74209206 : pg_nextpower2_32(uint32 num)
     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     74209206 :     if ((num & (num - 1)) == 0)
     199     70136043 :         return num;             /* already power 2 */
     200              : 
     201      4073163 :     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              :  */
     211              : static inline uint64
     212       168060 : pg_nextpower2_64(uint64 num)
     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       168060 :     if ((num & (num - 1)) == 0)
     222        86192 :         return num;             /* already power 2 */
     223              : 
     224        81868 :     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              :  */
     234              : static inline uint32
     235           18 : pg_prevpower2_32(uint32 num)
     236              : {
     237           18 :     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              :  */
     247              : static inline uint64
     248       559354 : pg_prevpower2_64(uint64 num)
     249              : {
     250       559354 :     return ((uint64) 1) << pg_leftmost_one_pos64(num);
     251              : }
     252              : 
     253              : /*
     254              :  * pg_ceil_log2_32
     255              :  *      Returns equivalent of ceil(log2(num))
     256              :  */
     257              : static inline uint32
     258       383168 : pg_ceil_log2_32(uint32 num)
     259              : {
     260       383168 :     if (num < 2)
     261           43 :         return 0;
     262              :     else
     263       383125 :         return pg_leftmost_one_pos32(num - 1) + 1;
     264              : }
     265              : 
     266              : /*
     267              :  * pg_ceil_log2_64
     268              :  *      Returns equivalent of ceil(log2(num))
     269              :  */
     270              : static inline uint64
     271       796594 : pg_ceil_log2_64(uint64 num)
     272              : {
     273       796594 :     if (num < 2)
     274       349309 :         return 0;
     275              :     else
     276       447285 :         return pg_leftmost_one_pos64(num - 1) + 1;
     277              : }
     278              : 
     279              : extern uint64 pg_popcount_portable(const char *buf, int bytes);
     280              : extern 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              :  */
     287              : extern PGDLLIMPORT uint64 (*pg_popcount_optimized) (const char *buf, int bytes);
     288              : extern 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. */
     292              : extern uint64 pg_popcount_optimized(const char *buf, int bytes);
     293              : extern 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              :  */
     308              : static inline int
     309              : pg_popcount32(uint32 word)
     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              :  */
     327              : static inline int
     328       948884 : pg_popcount64(uint64 word)
     329              : {
     330       948884 :     word -= (word >> 1) & UINT64CONST(0x5555555555555555);
     331       948884 :     word = (word & UINT64CONST(0x3333333333333333)) +
     332       948884 :         ((word >> 2) & UINT64CONST(0x3333333333333333));
     333       948884 :     word = (word + (word >> 4)) & UINT64CONST(0xf0f0f0f0f0f0f0f);
     334       948884 :     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              :  */
     346              : static inline uint64
     347         8022 : pg_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         8022 :     if (bytes < 8)
     354              :     {
     355         7997 :         uint64      popcnt = 0;
     356              : 
     357        13380 :         while (bytes--)
     358         5383 :             popcnt += pg_number_of_ones[(unsigned char) *buf++];
     359         7997 :         return popcnt;
     360              :     }
     361              : 
     362           25 :     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              :  */
     371              : static inline uint64
     372       109437 : pg_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       109437 :     if (bytes < 8)
     379              :     {
     380            0 :         uint64      popcnt = 0;
     381              : 
     382            0 :         while (bytes--)
     383            0 :             popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask];
     384            0 :         return popcnt;
     385              :     }
     386              : 
     387       109437 :     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              :  */
     393              : static inline uint32
     394      7839647 : pg_rotate_right32(uint32 word, int n)
     395              : {
     396      7839647 :     return (word >> n) | (word << (32 - n));
     397              : }
     398              : 
     399              : static inline uint32
     400   3102439842 : pg_rotate_left32(uint32 word, int n)
     401              : {
     402   3102439842 :     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 */
        

Generated by: LCOV version 2.0-1