LCOV - differential code coverage report
Current view: top level - src/include/port - pg_bitutils.h (source / functions) Coverage Total Hit UIC GIC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 97.2 % 36 35 1 33 2 1 28 5
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 11 11 11 10 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 7 7 7 4
Legend: Lines: hit not hit (240..) days: 96.6 % 29 28 1 26 2 1 20
Function coverage date bins:
[..60] days: 0.0 % 2 0 2
(240..) days: 64.7 % 17 11 11 6

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * pg_bitutils.h
                                  4                 :  *    Miscellaneous functions for bit-wise operations.
                                  5                 :  *
                                  6                 :  *
                                  7                 :  * Copyright (c) 2019-2023, 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
 1514 tgl                        41 GIC   537097964 : pg_leftmost_one_pos32(uint32 word)
                                 42                 : {
                                 43                 : #ifdef HAVE__BUILTIN_CLZ
   46 john.naylor                44       537097964 :     Assert(word != 0);
                                 45                 : 
                                 46       537097964 :     return 31 - __builtin_clz(word);
                                 47                 : #elif defined(_MSC_VER)
                                 48                 :     unsigned long result;
                                 49                 :     bool        non_zero;
                                 50                 : 
                                 51                 :     non_zero = _BitScanReverse(&result, word);
                                 52                 :     Assert(non_zero);
                                 53                 :     return (int) result;
                                 54                 : #else
                                 55                 :     int         shift = 32 - 8;
                                 56                 : 
                                 57                 :     Assert(word != 0);
                                 58                 : 
                                 59                 :     while ((word >> shift) == 0)
                                 60                 :         shift -= 8;
                                 61                 : 
                                 62                 :     return shift + pg_leftmost_one_pos[(word >> shift) & 255];
   46 john.naylor                63 ECB             : #endif                          /* HAVE__BUILTIN_CLZ */
                                 64                 : }
                                 65                 : 
 1514 tgl                        66                 : /*
                                 67                 :  * pg_leftmost_one_pos64
                                 68                 :  *      As above, but for a 64-bit word.
                                 69                 :  */
                                 70                 : static inline int
 1514 tgl                        71 GIC     1941001 : pg_leftmost_one_pos64(uint64 word)
                                 72                 : {
                                 73                 : #ifdef HAVE__BUILTIN_CLZ
                                 74         1941001 :     Assert(word != 0);
                                 75                 : 
                                 76                 : #if defined(HAVE_LONG_INT_64)
   46 john.naylor                77         1941001 :     return 63 - __builtin_clzl(word);
                                 78                 : #elif defined(HAVE_LONG_LONG_INT_64)
                                 79                 :     return 63 - __builtin_clzll(word);
                                 80                 : #else
                                 81                 : #error must have a working 64-bit integer datatype
                                 82                 : #endif                          /* HAVE_LONG_INT_64 */
                                 83                 : 
                                 84                 : #elif defined(_MSC_VER)
                                 85                 :     unsigned long result;
                                 86                 :     bool        non_zero;
                                 87                 : 
                                 88                 :     non_zero = _BitScanReverse64(&result, word);
                                 89                 :     Assert(non_zero);
                                 90                 :     return (int) result;
                                 91                 : #else
                                 92                 :     int         shift = 64 - 8;
                                 93                 : 
                                 94                 :     Assert(word != 0);
                                 95                 : 
                                 96                 :     while ((word >> shift) == 0)
                                 97                 :         shift -= 8;
                                 98                 : 
                                 99                 :     return shift + pg_leftmost_one_pos[(word >> shift) & 255];
                                100                 : #endif                          /* HAVE__BUILTIN_CLZ */
 1514 tgl                       101 ECB             : }
                                102                 : 
                                103                 : /*
                                104                 :  * pg_rightmost_one_pos32
                                105                 :  *      Returns the position of the least significant set bit in "word",
                                106                 :  *      measured from the least significant bit.  word must not be 0.
                                107                 :  */
                                108                 : static inline int
 1514 tgl                       109 GIC         248 : pg_rightmost_one_pos32(uint32 word)
                                110                 : {
                                111                 : #ifdef HAVE__BUILTIN_CTZ
   46 john.naylor               112             248 :     Assert(word != 0);
                                113                 : 
                                114             248 :     return __builtin_ctz(word);
                                115                 : #elif defined(_MSC_VER)
                                116                 :     unsigned long result;
                                117                 :     bool        non_zero;
                                118                 : 
                                119                 :     non_zero = _BitScanForward(&result, word);
                                120                 :     Assert(non_zero);
                                121                 :     return (int) result;
                                122                 : #else
                                123                 :     int         result = 0;
                                124                 : 
                                125                 :     Assert(word != 0);
                                126                 : 
                                127                 :     while ((word & 255) == 0)
                                128                 :     {
                                129                 :         word >>= 8;
                                130                 :         result += 8;
                                131                 :     }
                                132                 :     result += pg_rightmost_one_pos[word & 255];
                                133                 :     return result;
                                134                 : #endif                          /* HAVE__BUILTIN_CTZ */
                                135                 : }
                                136                 : 
                                137                 : /*
                                138                 :  * pg_rightmost_one_pos64
                                139                 :  *      As above, but for a 64-bit word.
                                140                 :  */
                                141                 : static inline int
 1514 tgl                       142         6021068 : pg_rightmost_one_pos64(uint64 word)
                                143                 : {
                                144                 : #ifdef HAVE__BUILTIN_CTZ
   46 john.naylor               145         6021068 :     Assert(word != 0);
   46 john.naylor               146 ECB             : 
                                147                 : #if defined(HAVE_LONG_INT_64)
   46 john.naylor               148 GIC     6021068 :     return __builtin_ctzl(word);
   46 john.naylor               149 ECB             : #elif defined(HAVE_LONG_LONG_INT_64)
                                150                 :     return __builtin_ctzll(word);
                                151                 : #else
                                152                 : #error must have a working 64-bit integer datatype
                                153                 : #endif                          /* HAVE_LONG_INT_64 */
                                154                 : 
                                155                 : #elif defined(_MSC_VER)
                                156                 :     unsigned long result;
                                157                 :     bool        non_zero;
                                158                 : 
                                159                 :     non_zero = _BitScanForward64(&result, word);
                                160                 :     Assert(non_zero);
                                161                 :     return (int) result;
                                162                 : #else
                                163                 :     int         result = 0;
                                164                 : 
                                165                 :     Assert(word != 0);
                                166                 : 
                                167                 :     while ((word & 255) == 0)
                                168                 :     {
                                169                 :         word >>= 8;
                                170                 :         result += 8;
                                171                 :     }
                                172                 :     result += pg_rightmost_one_pos[word & 255];
                                173                 :     return result;
                                174                 : #endif                          /* HAVE__BUILTIN_CTZ */
                                175                 : }
                                176                 : 
                                177                 : /*
                                178                 :  * pg_nextpower2_32
                                179                 :  *      Returns the next higher power of 2 above 'num', or 'num' if it's
                                180                 :  *      already a power of 2.
                                181                 :  *
                                182                 :  * 'num' mustn't be 0 or be above PG_UINT32_MAX / 2 + 1.
                                183                 :  */
                                184                 : static inline uint32
 1096 drowley                   185 GIC    42318361 : pg_nextpower2_32(uint32 num)
                                186                 : {
 1096 drowley                   187 CBC    42318361 :     Assert(num > 0 && num <= PG_UINT32_MAX / 2 + 1);
                                188                 : 
                                189                 :     /*
 1096 drowley                   190 ECB             :      * A power 2 number has only 1 bit set.  Subtracting 1 from such a number
                                191                 :      * will turn on all previous bits resulting in no common bits being set
                                192                 :      * between num and num-1.
                                193                 :      */
 1096 drowley                   194 GIC    42318361 :     if ((num & (num - 1)) == 0)
                                195        40561670 :         return num;             /* already power 2 */
                                196                 : 
                                197         1756691 :     return ((uint32) 1) << (pg_leftmost_one_pos32(num) + 1);
                                198                 : }
                                199                 : 
                                200                 : /*
                                201                 :  * pg_nextpower2_64
                                202                 :  *      Returns the next higher power of 2 above 'num', or 'num' if it's
                                203                 :  *      already a power of 2.
                                204                 :  *
                                205                 :  * 'num' mustn't be 0 or be above PG_UINT64_MAX / 2  + 1.
                                206                 :  */
                                207                 : static inline uint64
                                208           28657 : pg_nextpower2_64(uint64 num)
                                209                 : {
                                210           28657 :     Assert(num > 0 && num <= PG_UINT64_MAX / 2 + 1);
                                211                 : 
                                212                 :     /*
                                213                 :      * A power 2 number has only 1 bit set.  Subtracting 1 from such a number
                                214                 :      * will turn on all previous bits resulting in no common bits being set
                                215                 :      * between num and num-1.
                                216                 :      */
                                217           28657 :     if ((num & (num - 1)) == 0)
                                218            4999 :         return num;             /* already power 2 */
                                219                 : 
                                220           23658 :     return ((uint64) 1) << (pg_leftmost_one_pos64(num) + 1);
                                221                 : }
                                222                 : 
                                223                 : /*
                                224                 :  * pg_prevpower2_32
                                225                 :  *      Returns the next lower power of 2 below 'num', or 'num' if it's
                                226                 :  *      already a power of 2.
                                227                 :  *
                                228                 :  * 'num' mustn't be 0.
  623 tgl                       229 ECB             :  */
                                230                 : static inline uint32
                                231                 : pg_prevpower2_32(uint32 num)
                                232                 : {
                                233                 :     return ((uint32) 1) << pg_leftmost_one_pos32(num);
                                234                 : }
                                235                 : 
                                236                 : /*
                                237                 :  * pg_prevpower2_64
                                238                 :  *      Returns the next lower power of 2 below 'num', or 'num' if it's
                                239                 :  *      already a power of 2.
                                240                 :  *
                                241                 :  * 'num' mustn't be 0.
                                242                 :  */
                                243                 : static inline uint64
  623 tgl                       244 GIC      236685 : pg_prevpower2_64(uint64 num)
  623 tgl                       245 ECB             : {
  623 tgl                       246 GIC      236685 :     return ((uint64) 1) << pg_leftmost_one_pos64(num);
                                247                 : }
                                248                 : 
                                249                 : /*
                                250                 :  * pg_ceil_log2_32
                                251                 :  *      Returns equivalent of ceil(log2(num))
                                252                 :  */
                                253                 : static inline uint32
 1096 drowley                   254          345616 : pg_ceil_log2_32(uint32 num)
                                255                 : {
                                256          345616 :     if (num < 2)
 1096 drowley                   257 UIC           0 :         return 0;
                                258                 :     else
 1096 drowley                   259 GIC      345616 :         return pg_leftmost_one_pos32(num - 1) + 1;
                                260                 : }
                                261                 : 
                                262                 : /*
                                263                 :  * pg_ceil_log2_64
                                264                 :  *      Returns equivalent of ceil(log2(num))
                                265                 :  */
                                266                 : static inline uint64
                                267          547029 : pg_ceil_log2_64(uint64 num)
                                268                 : {
 1096 drowley                   269 CBC      547029 :     if (num < 2)
 1096 drowley                   270 GIC      205886 :         return 0;
 1096 drowley                   271 ECB             :     else
 1096 drowley                   272 GIC      341143 :         return pg_leftmost_one_pos64(num - 1) + 1;
                                273                 : }
                                274                 : 
                                275                 : /*
                                276                 :  * With MSVC on x86_64 builds, try using native popcnt instructions via the
                                277                 :  * __popcnt and __popcnt64 intrinsics.  These don't work the same as GCC's
                                278                 :  * __builtin_popcount* intrinsic functions as they always emit popcnt
  601 john.naylor               279 ECB             :  * instructions.
                                280                 :  */
                                281                 : #if defined(_MSC_VER) && defined(_M_AMD64)
  601 john.naylor               282 EUB             : #define HAVE_X86_64_POPCNTQ
                                283                 : #endif
  601 john.naylor               284 ECB             : 
                                285                 : /*
                                286                 :  * On x86_64, we can use the hardware popcount instruction, but only if
                                287                 :  * we can verify that the CPU supports it via the cpuid instruction.
                                288                 :  *
                                289                 :  * Otherwise, we fall back to a hand-rolled implementation.
                                290                 :  */
                                291                 : #ifdef HAVE_X86_64_POPCNTQ
                                292                 : #if defined(HAVE__GET_CPUID) || defined(HAVE__CPUID)
                                293                 : #define TRY_POPCNT_FAST 1
                                294                 : #endif
                                295                 : #endif
                                296                 : 
                                297                 : #ifdef TRY_POPCNT_FAST
                                298                 : /* Attempt to use the POPCNT instruction, but perform a runtime check first */
                                299                 : extern int  (*pg_popcount32) (uint32 word);
                                300                 : extern int  (*pg_popcount64) (uint64 word);
                                301                 : 
                                302                 : #else
                                303                 : /* Use a portable implementation -- no need for a function pointer. */
                                304                 : extern int  pg_popcount32(uint32 word);
                                305                 : extern int  pg_popcount64(uint64 word);
                                306                 : 
                                307                 : #endif                          /* TRY_POPCNT_FAST */
                                308                 : 
                                309                 : /* Count the number of one-bits in a byte array */
                                310                 : extern uint64 pg_popcount(const char *buf, int bytes);
                                311                 : 
                                312                 : /*
                                313                 :  * Rotate the bits of "word" to the right/left by n bits.
                                314                 :  */
                                315                 : static inline uint32
 1202 tmunro                    316 GIC     7629697 : pg_rotate_right32(uint32 word, int n)
                                317                 : {
  413 john.naylor               318         7629697 :     return (word >> n) | (word << (32 - n));
                                319                 : }
                                320                 : 
                                321                 : static inline uint32
                                322      3373203228 : pg_rotate_left32(uint32 word, int n)
                                323                 : {
                                324      3373203228 :     return (word << n) | (word >> (32 - n));
                                325                 : }
                                326                 : 
                                327                 : /* size_t variants of the above, as required */
                                328                 : 
                                329                 : #if SIZEOF_SIZE_T == 4
                                330                 : #define pg_leftmost_one_pos_size_t pg_leftmost_one_pos32
                                331                 : #define pg_nextpower2_size_t pg_nextpower2_32
                                332                 : #define pg_prevpower2_size_t pg_prevpower2_32
                                333                 : #else
                                334                 : #define pg_leftmost_one_pos_size_t pg_leftmost_one_pos64
                                335                 : #define pg_nextpower2_size_t pg_nextpower2_64
                                336                 : #define pg_prevpower2_size_t pg_prevpower2_64
                                337                 : #endif
                                338                 : 
                                339                 : #endif                          /* PG_BITUTILS_H */
        

Generated by: LCOV version v1.16-55-g56c0a2a