Add assert checking to pg_leftmost_one_pos32() and friends
authorJohn Naylor <john.naylor@postgresql.org>
Tue, 24 Jan 2023 07:39:26 +0000 (14:39 +0700)
committerJohn Naylor <john.naylor@postgresql.org>
Mon, 20 Feb 2023 07:16:34 +0000 (14:16 +0700)
Discussion: https://www.postgresql.org/message-id/CAFBsxsEPc%2BFnX_0vmmQ5DHv60sk4rL_RZJ%2BMD6ei%3D76L0kFMvA%40mail.gmail.com

src/include/port/pg_bitutils.h

index a49a9c03d92a1cd378b18349f1459cca09d9ca7c..a5df4f1a3551b1cd035f5a84309c0af32356909c 100644 (file)
@@ -26,10 +26,11 @@ static inline int
 pg_leftmost_one_pos32(uint32 word)
 {
 #ifdef HAVE__BUILTIN_CLZ
-       Assert(word != 0);
+       int                     bitscan_result;
+#endif
 
-       return 31 - __builtin_clz(word);
-#else
+#if !defined(HAVE__BUILTIN_CLZ) || defined(USE_ASSERT_CHECKING)
+       int                     result;
        int                     shift = 32 - 8;
 
        Assert(word != 0);
@@ -37,7 +38,15 @@ pg_leftmost_one_pos32(uint32 word)
        while ((word >> shift) == 0)
                shift -= 8;
 
-       return shift + pg_leftmost_one_pos[(word >> shift) & 255];
+       result = shift + pg_leftmost_one_pos[(word >> shift) & 255];
+#endif
+
+#if defined(HAVE__BUILTIN_CLZ)
+       bitscan_result = 31 - __builtin_clz(word);
+       Assert(bitscan_result == result);
+       return bitscan_result;
+#else
+       return result;
 #endif                                                 /* HAVE__BUILTIN_CLZ */
 }
 
@@ -49,16 +58,11 @@ static inline int
 pg_leftmost_one_pos64(uint64 word)
 {
 #ifdef HAVE__BUILTIN_CLZ
-       Assert(word != 0);
-
-#if defined(HAVE_LONG_INT_64)
-       return 63 - __builtin_clzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-       return 63 - __builtin_clzll(word);
-#else
-#error must have a working 64-bit integer datatype
+       int                     bitscan_result;
 #endif
-#else                                                  /* !HAVE__BUILTIN_CLZ */
+
+#if !defined(HAVE__BUILTIN_CLZ) || defined(USE_ASSERT_CHECKING)
+       int                     result;
        int                     shift = 64 - 8;
 
        Assert(word != 0);
@@ -66,7 +70,21 @@ pg_leftmost_one_pos64(uint64 word)
        while ((word >> shift) == 0)
                shift -= 8;
 
-       return shift + pg_leftmost_one_pos[(word >> shift) & 255];
+       result = shift + pg_leftmost_one_pos[(word >> shift) & 255];
+#endif
+
+#if defined(HAVE__BUILTIN_CLZ)
+#if defined(HAVE_LONG_INT_64)
+       bitscan_result = 63 - __builtin_clzl(word);
+#elif defined(HAVE_LONG_LONG_INT_64)
+       bitscan_result = 63 - __builtin_clzll(word);
+#else
+#error must have a working 64-bit integer datatype
+#endif                                                 /* HAVE_LONG_INT_64 */
+       Assert(bitscan_result == result);
+       return bitscan_result;
+#else
+       return result;
 #endif                                                 /* HAVE__BUILTIN_CLZ */
 }
 
@@ -79,10 +97,11 @@ static inline int
 pg_rightmost_one_pos32(uint32 word)
 {
 #ifdef HAVE__BUILTIN_CTZ
-       Assert(word != 0);
+       const uint32 orig_word = word;
+       int                     bitscan_result;
+#endif
 
-       return __builtin_ctz(word);
-#else
+#if !defined(HAVE__BUILTIN_CTZ) || defined(USE_ASSERT_CHECKING)
        int                     result = 0;
 
        Assert(word != 0);
@@ -93,6 +112,13 @@ pg_rightmost_one_pos32(uint32 word)
                result += 8;
        }
        result += pg_rightmost_one_pos[word & 255];
+#endif
+
+#if defined(HAVE__BUILTIN_CTZ)
+       bitscan_result = __builtin_ctz(orig_word);
+       Assert(bitscan_result == result);
+       return bitscan_result;
+#else
        return result;
 #endif                                                 /* HAVE__BUILTIN_CTZ */
 }
@@ -105,16 +131,11 @@ static inline int
 pg_rightmost_one_pos64(uint64 word)
 {
 #ifdef HAVE__BUILTIN_CTZ
-       Assert(word != 0);
-
-#if defined(HAVE_LONG_INT_64)
-       return __builtin_ctzl(word);
-#elif defined(HAVE_LONG_LONG_INT_64)
-       return __builtin_ctzll(word);
-#else
-#error must have a working 64-bit integer datatype
+       const uint64 orig_word = word;
+       int                     bitscan_result;
 #endif
-#else                                                  /* !HAVE__BUILTIN_CTZ */
+
+#if !defined(HAVE__BUILTIN_CTZ) || defined(USE_ASSERT_CHECKING)
        int                     result = 0;
 
        Assert(word != 0);
@@ -125,6 +146,19 @@ pg_rightmost_one_pos64(uint64 word)
                result += 8;
        }
        result += pg_rightmost_one_pos[word & 255];
+#endif
+
+#if defined(HAVE__BUILTIN_CTZ)
+#if defined(HAVE_LONG_INT_64)
+       bitscan_result = __builtin_ctzl(orig_word);
+#elif defined(HAVE_LONG_LONG_INT_64)
+       bitscan_result = __builtin_ctzll(orig_word);
+#else
+#error must have a working 64-bit integer datatype
+#endif                                                 /* HAVE_LONG_INT_64 */
+       Assert(bitscan_result == result);
+       return bitscan_result;
+#else
        return result;
 #endif                                                 /* HAVE__BUILTIN_CTZ */
 }