diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c index 9cda3b1cc1..2ee7385f02 100644 --- a/src/backend/nodes/bitmapset.c +++ b/src/backend/nodes/bitmapset.c @@ -9,12 +9,7 @@ * the minimum possible number of words, i.e, there are never any trailing * zero words. Enforcing this requires that an empty set is represented as * NULL. Because an empty Bitmapset is represented as NULL, a non-NULL - * Bitmapset always has at least 1 Bitmapword. We can exploit this fact to - * speedup various loops over the Bitmapset's words array by using "do while" - * loops instead of "for" loops. This means the code does not waste time - * checking the loop condition before the first iteration. For Bitmapsets - * containing only a single word (likely the majority of them) this reduces - * the loop condition tests by half. + * Bitmapset always has at least 1 Bitmapword. * * * Copyright (c) 2003-2023, PostgreSQL Global Development Group @@ -96,8 +91,6 @@ bms_copy(const Bitmapset *a) bool bms_equal(const Bitmapset *a, const Bitmapset *b) { - int i; - /* Handle cases where either input is NULL */ if (a == NULL) { @@ -108,17 +101,20 @@ bms_equal(const Bitmapset *a, const Bitmapset *b) else if (b == NULL) return false; - /* can't be equal if the word counts don't match */ - if (a->nwords != b->nwords) + /* + * Most Bitmapsets will likely just have 1 word, so check for equality + * there before checking the number of words match. The sets cannot be + * equal when they don't have the same number of words. + */ + if (a->words[0] != b->words[0] || a->nwords != b->nwords) return false; - /* check each word matches */ - i = 0; - do + /* check all the remaining words match */ + for (int i = 1; i < a->nwords; i++) { if (a->words[i] != b->words[i]) return false; - } while (++i < a->nwords); + } return true; } @@ -353,25 +349,27 @@ bms_difference(const Bitmapset *a, const Bitmapset *b) bool bms_is_subset(const Bitmapset *a, const Bitmapset *b) { - int i; - /* Handle cases where either input is NULL */ if (a == NULL) return true; /* empty set is a subset of anything */ if (b == NULL) return false; - /* 'a' can't be a subset of 'b' if it contains more words */ - if (a->nwords > b->nwords) + /* + * Check the 0th word first as many sets will only have 1 word. + * Otherwise, 'a' can't be a subset of 'b' if it contains more words, so + * there's no need to check remaining words if 'a' contains more words + * than 'b'. + */ + if ((a->words[0] & ~b->words[0]) != 0 || a->nwords > b->nwords) return false; - /* Check all 'a' members are set in 'b' */ - i = 0; - do + /* Check all remaining words to see 'b' has members not set in 'a'. */ + for (int i = 1; i < a->nwords; i++) { if ((a->words[i] & ~b->words[i]) != 0) return false; - } while (++i < a->nwords); + } return true; }