[dawn] Replace `ScanForward()` with `std::countr_zero()` in C++20

Bug: 343500108
Change-Id: I8fd817c6a5f80a0a3f34c0a208f27f3efff6ba0e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/240654
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/common/BitSetRangeIterator.h b/src/dawn/common/BitSetRangeIterator.h
index 6447751..d44ad3c 100644
--- a/src/dawn/common/BitSetRangeIterator.h
+++ b/src/dawn/common/BitSetRangeIterator.h
@@ -28,6 +28,7 @@
 #ifndef SRC_DAWN_COMMON_BITSETRANGEITERATOR_H_
 #define SRC_DAWN_COMMON_BITSETRANGEITERATOR_H_
 
+#include <bit>
 #include <bitset>
 #include <limits>
 #include <utility>
@@ -132,7 +133,8 @@
         mBits >>= kBitsPerWord;
     }
 
-    size_t nextBit = ScanForward(static_cast<uint64_t>((mBits & wordMask).to_ullong()));
+    size_t nextBit = static_cast<size_t>(
+        std::countr_zero(static_cast<uint64_t>((mBits & wordMask).to_ullong())));
     mBits >>= nextBit;
     return offset + nextBit;
 }
diff --git a/src/dawn/common/Math.h b/src/dawn/common/Math.h
index 89f1d82..6a055d8 100644
--- a/src/dawn/common/Math.h
+++ b/src/dawn/common/Math.h
@@ -169,38 +169,7 @@
 }
 
 // The following functions are defined in the header so they may be inlined.
-
 #if DAWN_COMPILER_IS(MSVC)
-// Return the index of the least significant bit set. Indexing is such that bit 0 is the least
-// significant bit. Implemented for different bit widths on different platforms.
-inline uint32_t ScanForward(uint32_t bits) {
-    DAWN_ASSERT(bits != 0u);
-    // NOLINTNEXTLINE(runtime/int)
-    unsigned long firstBitIndex = 0ul;
-    uint8_t ret = _BitScanForward(&firstBitIndex, bits);
-    DAWN_ASSERT(ret != 0u);
-    return static_cast<uint32_t>(firstBitIndex);
-}
-
-inline uint32_t ScanForward(uint64_t bits) {
-    DAWN_ASSERT(bits != 0u);
-    // NOLINTNEXTLINE(runtime/int)
-    unsigned long firstBitIndex = 0ul;
-#if DAWN_PLATFORM_IS(64_BIT)
-    uint8_t ret = _BitScanForward64(&firstBitIndex, bits);
-#else
-    uint8_t ret;
-    if (static_cast<uint32_t>(bits) == 0) {
-        ret = _BitScanForward(&firstBitIndex, static_cast<uint32_t>(bits >> 32));
-        firstBitIndex += 32ul;
-    } else {
-        ret = _BitScanForward(&firstBitIndex, static_cast<uint32_t>(bits));
-    }
-#endif  // DAWN_PLATFORM_IS(64_BIT)
-    DAWN_ASSERT(ret != 0u);
-    return firstBitIndex;
-}
-
 // Return the index of the most significant bit set. Indexing is such that bit 0 is the least
 // significant bit.
 inline uint32_t ScanReverse(uint32_t bits) {
@@ -232,22 +201,6 @@
 }
 #else  // DAWN_COMPILER_IS(MSVC)
 
-inline uint32_t ScanForward(uint32_t bits) {
-    DAWN_ASSERT(bits != 0u);
-    return static_cast<uint32_t>(__builtin_ctz(bits));
-}
-
-inline uint32_t ScanForward(uint64_t bits) {
-    DAWN_ASSERT(bits != 0u);
-#if DAWN_PLATFORM_IS(64_BIT)
-    return static_cast<uint32_t>(__builtin_ctzll(bits));
-#else
-    return static_cast<uint32_t>(static_cast<uint32_t>(bits) == 0
-                                     ? __builtin_ctz(static_cast<uint32_t>(bits >> 32)) + 32
-                                     : __builtin_ctz(static_cast<uint32_t>(bits)));
-#endif  // DAWN_PLATFORM_IS(64_BIT)
-}
-
 inline uint32_t ScanReverse(uint32_t bits) {
     DAWN_ASSERT(bits != 0u);
     return static_cast<uint32_t>((sizeof(uint32_t) * CHAR_BIT) - 1 - __builtin_clz(bits));
@@ -269,14 +222,6 @@
 
 #endif  // !DAWN_COMPILER_IS(MSVC)
 
-inline uint32_t ScanForward(uint8_t bits) {
-    return ScanForward(static_cast<uint32_t>(bits));
-}
-
-inline uint32_t ScanForward(uint16_t bits) {
-    return ScanForward(static_cast<uint32_t>(bits));
-}
-
 inline uint32_t ScanReverse(uint8_t bits) {
     return ScanReverse(static_cast<uint32_t>(bits));
 }
diff --git a/src/dawn/common/ityp_bitset.h b/src/dawn/common/ityp_bitset.h
index 22ac20b..190cc38 100644
--- a/src/dawn/common/ityp_bitset.h
+++ b/src/dawn/common/ityp_bitset.h
@@ -28,6 +28,7 @@
 #ifndef SRC_DAWN_COMMON_ITYP_BITSET_H_
 #define SRC_DAWN_COMMON_ITYP_BITSET_H_
 
+#include <bit>
 #include <bitset>
 #include <limits>
 
@@ -81,7 +82,7 @@
     if (mBits == 0) {
         return 0;
     }
-    return ScanForward(mBits);
+    return std::countr_zero(mBits);
 }
 
 template <typename Index, size_t N>
@@ -138,7 +139,7 @@
     while (mOffset < N) {
         uint64_t wordBits = static_cast<uint64_t>((mBits & wordMask).to_ullong());
         if (wordBits != 0ull) {
-            return ScanForward(wordBits) + mOffset;
+            return std::countr_zero(wordBits) + mOffset;
         }
 
         mBits >>= kBitsPerWord;
diff --git a/src/dawn/native/AttachmentState.cpp b/src/dawn/native/AttachmentState.cpp
index 59c786a..492ec90 100644
--- a/src/dawn/native/AttachmentState.cpp
+++ b/src/dawn/native/AttachmentState.cpp
@@ -27,6 +27,8 @@
 
 #include "dawn/native/AttachmentState.h"
 
+#include <bit>
+
 #include "dawn/common/Enumerator.h"
 #include "dawn/common/ityp_span.h"
 #include "dawn/native/ChainUtils.h"
@@ -328,8 +330,8 @@
     auto availableSlots = ~mColorAttachmentsSet;
     for (size_t i = 0; i < mStorageAttachmentSlots.size(); i++) {
         DAWN_ASSERT(!availableSlots.none());
-        auto slot = ColorAttachmentIndex(
-            uint8_t(ScanForward(static_cast<uint32_t>(availableSlots.to_ulong()))));
+        auto slot = ColorAttachmentIndex(static_cast<uint8_t>(
+            std::countr_zero(static_cast<uint32_t>(availableSlots.to_ulong()))));
         availableSlots.reset(slot);
         result[i] = slot;
     }
diff --git a/src/dawn/tests/unittests/MathTests.cpp b/src/dawn/tests/unittests/MathTests.cpp
index 063b93b..12a3dca 100644
--- a/src/dawn/tests/unittests/MathTests.cpp
+++ b/src/dawn/tests/unittests/MathTests.cpp
@@ -53,49 +53,6 @@
 namespace dawn {
 namespace {
 
-// Tests for ScanForward
-TEST(Math, ScanForward) {
-    // 8-bit
-    // Test extrema
-    ASSERT_EQ(ScanForward(uint8_t(1)), 0u);
-    ASSERT_EQ(ScanForward(uint8_t(0x80)), 7u);
-
-    // Test with more than one bit set.
-    ASSERT_EQ(ScanForward(uint8_t(64)), 6u);
-    ASSERT_EQ(ScanForward(uint8_t(64 + 32)), 5u);
-    ASSERT_EQ(ScanForward(uint8_t(128 + 64 + 32)), 5u);
-
-    // 16-bit
-    // Test extrema
-    ASSERT_EQ(ScanForward(uint16_t(1)), 0u);
-    ASSERT_EQ(ScanForward(uint16_t(0x8000)), 15u);
-
-    // Test with more than one bit set.
-    ASSERT_EQ(ScanForward(uint16_t(256)), 8u);
-    ASSERT_EQ(ScanForward(uint16_t(256 + 32)), 5u);
-    ASSERT_EQ(ScanForward(uint16_t(1024u + 256 + 32)), 5u);
-
-    // 32-bit
-    // Test extrema
-    ASSERT_EQ(ScanForward(1u), 0u);
-    ASSERT_EQ(ScanForward(0x80000000u), 31u);
-
-    // Test with more than one bit set.
-    ASSERT_EQ(ScanForward(256u), 8u);
-    ASSERT_EQ(ScanForward(256u + 32u), 5u);
-    ASSERT_EQ(ScanForward(1024u + 256u + 32u), 5u);
-
-    // 64-bit
-    // Test extrema
-    ASSERT_EQ(ScanForward(uint64_t(1)), 0u);
-    ASSERT_EQ(ScanForward(uint64_t(0x8000000000000000ull)), 63u);
-
-    // Test with more than one bit set.
-    ASSERT_EQ(ScanForward(uint64_t(256ull)), 8u);
-    ASSERT_EQ(ScanForward(uint64_t(256ull + 32ull)), 5u);
-    ASSERT_EQ(ScanForward(uint64_t(0x800000000ull + 256ull + 32ull)), 5u);
-}
-
 // Tests for ScanReverse
 TEST(Math, ScanReverse) {
     // 8-bit