]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Make use of pg_popcount() in more places.
authorNathan Bossart <nathan@postgresql.org>
Mon, 23 Feb 2026 15:26:00 +0000 (09:26 -0600)
committerNathan Bossart <nathan@postgresql.org>
Mon, 23 Feb 2026 15:26:00 +0000 (09:26 -0600)
This replaces some loops over word-length popcount functions with
calls to pg_popcount().  Since pg_popcount() may use a function
pointer for inputs with sizes >= a Bitmapset word, this produces a
small regression for the common one-word case in bms_num_members().
To deal with that, this commit adds an inlined fast-path for that
case.  This fast-path could arguably go in pg_popcount() itself
(with an appropriate alignment check), but that is left for future
study.

Suggested-by: John Naylor <johncnaylorls@gmail.com>
Reviewed-by: John Naylor <johncnaylorls@gmail.com>
Discussion: https://postgr.es/m/CANWCAZY7R%2Biy%2Br9YM_sySNydHzNqUirx1xk0tB3ej5HO62GdgQ%40mail.gmail.com

src/backend/nodes/bitmapset.c
src/include/lib/radixtree.h

index a4765876c31ed6b5d1ee4d3fe95307b416096efc..786f343b3c93037f04f4fe099d682705cc0507c5 100644 (file)
@@ -553,14 +553,8 @@ bms_member_index(Bitmapset *a, int x)
        bitnum = BITNUM(x);
 
        /* count bits in preceding words */
-       for (int i = 0; i < wordnum; i++)
-       {
-               bitmapword      w = a->words[i];
-
-               /* No need to count the bits in a zero word */
-               if (w != 0)
-                       result += bmw_popcount(w);
-       }
+       result += pg_popcount((const char *) a->words,
+                                                 wordnum * sizeof(bitmapword));
 
        /*
         * Now add bits of the last word, but only those before the item. We can
@@ -749,26 +743,17 @@ bms_get_singleton_member(const Bitmapset *a, int *member)
 int
 bms_num_members(const Bitmapset *a)
 {
-       int                     result = 0;
-       int                     nwords;
-       int                     wordnum;
-
        Assert(bms_is_valid_set(a));
 
        if (a == NULL)
                return 0;
 
-       nwords = a->nwords;
-       wordnum = 0;
-       do
-       {
-               bitmapword      w = a->words[wordnum];
+       /* fast-path for common case */
+       if (a->nwords == 1)
+               return bmw_popcount(a->words[0]);
 
-               /* No need to count the bits in a zero word */
-               if (w != 0)
-                       result += bmw_popcount(w);
-       } while (++wordnum < nwords);
-       return result;
+       return pg_popcount((const char *) a->words,
+                                          a->nwords * sizeof(bitmapword));
 }
 
 /*
index b223ce10a2d3e38d94edcc0d1b16f2d2fdff39c1..e6c9a591c173f20d7eaaea9985f0bb430a6e2f5e 100644 (file)
@@ -2721,12 +2721,12 @@ RT_VERIFY_NODE(RT_NODE * node)
                case RT_NODE_KIND_256:
                        {
                                RT_NODE_256 *n256 = (RT_NODE_256 *) node;
-                               int                     cnt = 0;
+                               int                     cnt;
 
                                /* RT_DUMP_NODE(node); */
 
-                               for (int i = 0; i < RT_BM_IDX(RT_NODE_MAX_SLOTS); i++)
-                                       cnt += bmw_popcount(n256->isset[i]);
+                               cnt = pg_popcount((const char *) n256->isset,
+                                                                 RT_NODE_MAX_SLOTS / BITS_PER_BYTE);
 
                                /*
                                 * Check if the number of used chunk matches, accounting for