From 9390a74f1712d58c88ac513afff8d878071c040c Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Tue, 24 Jan 2023 15:57:53 +0700
Subject: [PATCH v3 2/3] Add MSVC support for bitscan reverse/forward

---
 src/include/port/pg_bitutils.h | 38 ++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
index 9a53f53d11..ce04f4ffad 100644
--- a/src/include/port/pg_bitutils.h
+++ b/src/include/port/pg_bitutils.h
@@ -13,6 +13,10 @@
 #ifndef PG_BITUTILS_H
 #define PG_BITUTILS_H
 
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
 extern PGDLLIMPORT const uint8 pg_leftmost_one_pos[256];
 extern PGDLLIMPORT const uint8 pg_rightmost_one_pos[256];
 extern PGDLLIMPORT const uint8 pg_number_of_ones[256];
@@ -27,6 +31,9 @@ pg_leftmost_one_pos32(uint32 word)
 {
 #ifdef HAVE__BUILTIN_CLZ
 	int			bitscan_result;
+#elif defined(_MSC_VER)
+	unsigned long bitscan_result;
+	unsigned char non_zero; // XXX can this be bool?
 #endif
 
 #if !defined(HAVE__BUILTIN_CLZ) || defined(USE_ASSERT_CHECKING)
@@ -45,6 +52,11 @@ pg_leftmost_one_pos32(uint32 word)
 	bitscan_result = 31 - __builtin_clz(word);
 	Assert(bitscan_result == result);
 	return bitscan_result;
+#elif defined(_MSC_VER)
+	non_zero = _BitScanReverse(&bitscan_result, word);
+	Assert(non_zero);
+	Assert(bitscan_result == result);
+	return bitscan_result;
 #else
 	return result;
 #endif							/* HAVE__BUILTIN_CLZ */
@@ -59,6 +71,9 @@ pg_leftmost_one_pos64(uint64 word)
 {
 #ifdef HAVE__BUILTIN_CLZ
 	int			bitscan_result;
+#elif defined(_MSC_VER)
+	unsigned long bitscan_result;
+	unsigned char non_zero; // XXX can this be bool?
 #endif
 
 #if !defined(HAVE__BUILTIN_CLZ) || defined(USE_ASSERT_CHECKING)
@@ -83,6 +98,11 @@ pg_leftmost_one_pos64(uint64 word)
 #endif							/* HAVE_LONG_... */
 	Assert(bitscan_result == result);
 	return bitscan_result;
+#elif defined(_MSC_VER)
+	non_zero = _BitScanReverse64(&bitscan_result, word);
+	Assert(non_zero);
+	Assert(bitscan_result == result);
+	return bitscan_result;
 #else
 	return result;
 #endif							/* HAVE__BUILTIN_CLZ */
@@ -99,6 +119,10 @@ pg_rightmost_one_pos32(uint32 word)
 #ifdef HAVE__BUILTIN_CTZ
 	const uint32 orig_word = word;
 	int			bitscan_result;
+#elif defined(_MSC_VER)
+	const unsigned long orig_word = word;
+	unsigned long bitscan_result;
+	unsigned char non_zero; // XXX can this be bool?
 #endif
 
 #if !defined(HAVE__BUILTIN_CTZ) || defined(USE_ASSERT_CHECKING)
@@ -118,6 +142,11 @@ pg_rightmost_one_pos32(uint32 word)
 	bitscan_result = __builtin_ctz(orig_word);
 	Assert(bitscan_result == result);
 	return bitscan_result;
+#elif defined(_MSC_VER)
+	non_zero = _BitScanForward(&bitscan_result, orig_word);
+	Assert(non_zero);
+	Assert(bitscan_result == result);
+	return bitscan_result;
 #else
 	return result;
 #endif							/* HAVE__BUILTIN_CTZ */
@@ -133,6 +162,10 @@ pg_rightmost_one_pos64(uint64 word)
 #ifdef HAVE__BUILTIN_CTZ
 	const uint64 orig_word = word;
 	int			bitscan_result;
+#elif defined(_MSC_VER)
+	const unsigned __int64 orig_word = word;
+	unsigned long bitscan_result;
+	unsigned char non_zero; // XXX can this be bool?
 #endif
 
 #if !defined(HAVE__BUILTIN_CTZ) || defined(USE_ASSERT_CHECKING)
@@ -158,6 +191,11 @@ pg_rightmost_one_pos64(uint64 word)
 #endif							/* HAVE_LONG_... */
 	Assert(bitscan_result == result);
 	return bitscan_result;
+#elif defined(_MSC_VER)
+	non_zero = _BitScanForward64(&bitscan_result, orig_word);
+	Assert(non_zero);
+	Assert(bitscan_result == result);
+	return bitscan_result;
 #else
 	return result;
 #endif							/* HAVE__BUILTIN_CTZ */
-- 
2.39.0

