LCOV - code coverage report
Current view: top level - src/include/port - pg_bitutils.h (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 43 48 89.6 %
Date: 2025-02-22 07:14:56 Functions: 14 14 100.0 %
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-2025, 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  1346428188 : pg_leftmost_one_pos32(uint32 word)
      42             : {
      43             : #ifdef HAVE__BUILTIN_CLZ
      44             :     Assert(word != 0);
      45             : 
      46  1346428188 :     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     4808948 : pg_leftmost_one_pos64(uint64 word)
      73             : {
      74             : #ifdef HAVE__BUILTIN_CLZ
      75             :     Assert(word != 0);
      76             : 
      77             : #if SIZEOF_LONG == 8
      78     4808948 :     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     5545256 : pg_rightmost_one_pos32(uint32 word)
     112             : {
     113             : #ifdef HAVE__BUILTIN_CTZ
     114             :     Assert(word != 0);
     115             : 
     116     5545256 :     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    24277432 : pg_rightmost_one_pos64(uint64 word)
     146             : {
     147             : #ifdef HAVE__BUILTIN_CTZ
     148             :     Assert(word != 0);
     149             : 
     150             : #if SIZEOF_LONG == 8
     151    24277432 :     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   154931484 : 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   154931484 :     if ((num & (num - 1)) == 0)
     199   146574962 :         return num;             /* already power 2 */
     200             : 
     201     8356522 :     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      180712 : 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      180712 :     if ((num & (num - 1)) == 0)
     222       94128 :         return num;             /* already power 2 */
     223             : 
     224       86584 :     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          36 : pg_prevpower2_32(uint32 num)
     236             : {
     237          36 :     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     1056642 : pg_prevpower2_64(uint64 num)
     249             : {
     250     1056642 :     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      712812 : pg_ceil_log2_32(uint32 num)
     259             : {
     260      712812 :     if (num < 2)
     261           0 :         return 0;
     262             :     else
     263      712812 :         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     1111496 : pg_ceil_log2_64(uint64 num)
     272             : {
     273     1111496 :     if (num < 2)
     274      462758 :         return 0;
     275             :     else
     276      648738 :         return pg_leftmost_one_pos64(num - 1) + 1;
     277             : }
     278             : 
     279             : /*
     280             :  * With MSVC on x86_64 builds, try using native popcnt instructions via the
     281             :  * __popcnt and __popcnt64 intrinsics.  These don't work the same as GCC's
     282             :  * __builtin_popcount* intrinsic functions as they always emit popcnt
     283             :  * instructions.
     284             :  */
     285             : #if defined(_MSC_VER) && defined(_M_AMD64)
     286             : #define HAVE_X86_64_POPCNTQ
     287             : #endif
     288             : 
     289             : /*
     290             :  * On x86_64, we can use the hardware popcount instruction, but only if
     291             :  * we can verify that the CPU supports it via the cpuid instruction.
     292             :  *
     293             :  * Otherwise, we fall back to a hand-rolled implementation.
     294             :  */
     295             : #ifdef HAVE_X86_64_POPCNTQ
     296             : #if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID)
     297             : #define TRY_POPCNT_FAST 1
     298             : #endif
     299             : #endif
     300             : 
     301             : #ifdef TRY_POPCNT_FAST
     302             : /* Attempt to use the POPCNT instruction, but perform a runtime check first */
     303             : extern PGDLLIMPORT int (*pg_popcount32) (uint32 word);
     304             : extern PGDLLIMPORT int (*pg_popcount64) (uint64 word);
     305             : extern PGDLLIMPORT uint64 (*pg_popcount_optimized) (const char *buf, int bytes);
     306             : extern PGDLLIMPORT uint64 (*pg_popcount_masked_optimized) (const char *buf, int bytes, bits8 mask);
     307             : 
     308             : /*
     309             :  * We can also try to use the AVX-512 popcount instruction on some systems.
     310             :  * The implementation of that is located in its own file.
     311             :  */
     312             : #ifdef USE_AVX512_POPCNT_WITH_RUNTIME_CHECK
     313             : extern bool pg_popcount_avx512_available(void);
     314             : extern uint64 pg_popcount_avx512(const char *buf, int bytes);
     315             : extern uint64 pg_popcount_masked_avx512(const char *buf, int bytes, bits8 mask);
     316             : #endif
     317             : 
     318             : #else
     319             : /* Use a portable implementation -- no need for a function pointer. */
     320             : extern int  pg_popcount32(uint32 word);
     321             : extern int  pg_popcount64(uint64 word);
     322             : extern uint64 pg_popcount_optimized(const char *buf, int bytes);
     323             : extern uint64 pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask);
     324             : 
     325             : #endif                          /* TRY_POPCNT_FAST */
     326             : 
     327             : /*
     328             :  * Returns the number of 1-bits in buf.
     329             :  *
     330             :  * If there aren't many bytes to process, the function call overhead of the
     331             :  * optimized versions isn't worth taking, so we inline a loop that consults
     332             :  * pg_number_of_ones in that case.  If there are many bytes to process, we
     333             :  * accept the function call overhead because the optimized versions are likely
     334             :  * to be faster.
     335             :  */
     336             : static inline uint64
     337       10710 : pg_popcount(const char *buf, int bytes)
     338             : {
     339             :     /*
     340             :      * We set the threshold to the point at which we'll first use special
     341             :      * instructions in the optimized version.
     342             :      */
     343             : #if SIZEOF_VOID_P >= 8
     344       10710 :     int         threshold = 8;
     345             : #else
     346             :     int         threshold = 4;
     347             : #endif
     348             : 
     349       10710 :     if (bytes < threshold)
     350             :     {
     351       10682 :         uint64      popcnt = 0;
     352             : 
     353       21444 :         while (bytes--)
     354       10762 :             popcnt += pg_number_of_ones[(unsigned char) *buf++];
     355       10682 :         return popcnt;
     356             :     }
     357             : 
     358          28 :     return pg_popcount_optimized(buf, bytes);
     359             : }
     360             : 
     361             : /*
     362             :  * Returns the number of 1-bits in buf after applying the mask to each byte.
     363             :  *
     364             :  * Similar to pg_popcount(), we only take on the function pointer overhead when
     365             :  * it's likely to be faster.
     366             :  */
     367             : static inline uint64
     368       52584 : pg_popcount_masked(const char *buf, int bytes, bits8 mask)
     369             : {
     370             :     /*
     371             :      * We set the threshold to the point at which we'll first use special
     372             :      * instructions in the optimized version.
     373             :      */
     374             : #if SIZEOF_VOID_P >= 8
     375       52584 :     int         threshold = 8;
     376             : #else
     377             :     int         threshold = 4;
     378             : #endif
     379             : 
     380       52584 :     if (bytes < threshold)
     381             :     {
     382           0 :         uint64      popcnt = 0;
     383             : 
     384           0 :         while (bytes--)
     385           0 :             popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask];
     386           0 :         return popcnt;
     387             :     }
     388             : 
     389       52584 :     return pg_popcount_masked_optimized(buf, bytes, mask);
     390             : }
     391             : 
     392             : /*
     393             :  * Rotate the bits of "word" to the right/left by n bits.
     394             :  */
     395             : static inline uint32
     396    13177226 : pg_rotate_right32(uint32 word, int n)
     397             : {
     398    13177226 :     return (word >> n) | (word << (32 - n));
     399             : }
     400             : 
     401             : static inline uint32
     402  4951388056 : pg_rotate_left32(uint32 word, int n)
     403             : {
     404  4951388056 :     return (word << n) | (word >> (32 - n));
     405             : }
     406             : 
     407             : /* size_t variants of the above, as required */
     408             : 
     409             : #if SIZEOF_SIZE_T == 4
     410             : #define pg_leftmost_one_pos_size_t pg_leftmost_one_pos32
     411             : #define pg_nextpower2_size_t pg_nextpower2_32
     412             : #define pg_prevpower2_size_t pg_prevpower2_32
     413             : #else
     414             : #define pg_leftmost_one_pos_size_t pg_leftmost_one_pos64
     415             : #define pg_nextpower2_size_t pg_nextpower2_64
     416             : #define pg_prevpower2_size_t pg_prevpower2_64
     417             : #endif
     418             : 
     419             : #endif                          /* PG_BITUTILS_H */

Generated by: LCOV version 1.14