From 4c404d3074d33e1f56e95abc5037f20816727235 Mon Sep 17 00:00:00 2001
From: Yuya Watari <watari.yuya@gmail.com>
Date: Tue, 14 Mar 2023 15:12:18 +0900
Subject: [PATCH v2] Remove bms_is_empty_internal() function calls

Originally, we checked whether the result of the Bitmapset operation
was empty or not by calling the bms_is_empty_internal() function.
However, these calls lead to unnecessary looping over the result
Bitmapset. This commit reduces such redundant calls and improves the
performance.
---
 src/backend/nodes/bitmapset.c | 42 ++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 6 deletions(-)

diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index 7ba3cf635b..47eec5b63b 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -263,6 +263,7 @@ bms_intersect(const Bitmapset *a, const Bitmapset *b)
 	const Bitmapset *other;
 	int			resultlen;
 	int			i;
+	bitmapword	bitwise_or = 0;
 
 	/* Handle cases where either input is NULL */
 	if (a == NULL || b == NULL)
@@ -281,9 +282,17 @@ bms_intersect(const Bitmapset *a, const Bitmapset *b)
 	/* And intersect the longer input with the result */
 	resultlen = result->nwords;
 	for (i = 0; i < resultlen; i++)
-		result->words[i] &= other->words[i];
+	{
+		bitmapword	w = (result->words[i] &= other->words[i]);
+
+		/*
+		 * Compute bitwise OR of all bitmapwords to determine if the result
+		 * is empty
+		 */
+		bitwise_or |= w;
+	}
 	/* If we computed an empty result, we must return NULL */
-	if (bms_is_empty_internal(result))
+	if (bitwise_or == 0)
 	{
 		pfree(result);
 		return NULL;
@@ -929,6 +938,7 @@ bms_int_members(Bitmapset *a, const Bitmapset *b)
 {
 	int			shortlen;
 	int			i;
+	bitmapword	bitwise_or = 0;
 
 	/* Handle cases where either input is NULL */
 	if (a == NULL)
@@ -941,11 +951,19 @@ bms_int_members(Bitmapset *a, const Bitmapset *b)
 	/* Intersect b into a; we need never copy */
 	shortlen = Min(a->nwords, b->nwords);
 	for (i = 0; i < shortlen; i++)
-		a->words[i] &= b->words[i];
+	{
+		bitmapword	w = (a->words[i] &= b->words[i]);
+
+		/*
+		 * Compute bitwise OR of all bitmapwords to determine if the result
+		 * is empty
+		 */
+		bitwise_or |= w;
+	}
 	for (; i < a->nwords; i++)
 		a->words[i] = 0;
 	/* If we computed an empty result, we must return NULL */
-	if (bms_is_empty_internal(a))
+	if (bitwise_or == 0)
 	{
 		pfree(a);
 		return NULL;
@@ -961,6 +979,7 @@ bms_del_members(Bitmapset *a, const Bitmapset *b)
 {
 	int			shortlen;
 	int			i;
+	bitmapword	bitwise_or = 0;
 
 	/* Handle cases where either input is NULL */
 	if (a == NULL)
@@ -970,9 +989,20 @@ bms_del_members(Bitmapset *a, const Bitmapset *b)
 	/* Remove b's bits from a; we need never copy */
 	shortlen = Min(a->nwords, b->nwords);
 	for (i = 0; i < shortlen; i++)
-		a->words[i] &= ~b->words[i];
+	{
+		bitmapword	w = (a->words[i] &= ~b->words[i]);
+
+		/*
+		 * Compute bitwise OR of all bitmapwords to determine if the result
+		 * is empty
+		 */
+		bitwise_or |= w;
+	}
+	/* Compute bitwise OR of extra words in a */
+	for (; i < a->nwords; i++)
+		bitwise_or |= a->words[i];
 	/* If we computed an empty result, we must return NULL */
-	if (bms_is_empty_internal(a))
+	if (bitwise_or == 0)
 	{
 		pfree(a);
 		return NULL;
-- 
2.39.2.windows.1

