Make use of pg_popcount() in more places.

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
This commit is contained in:
Nathan Bossart 2026-02-23 09:26:00 -06:00
parent eb9ab7e093
commit f33b8793fd
2 changed files with 10 additions and 25 deletions

View 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));
}
/*

View 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