From 21b10d8c1dafe77dfdd06b52dd84cf79fa471019 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 1 Aug 2024 20:51:22 -0700 Subject: [PATCH] [useful] Drop bespoke CountTrailingZeros impl (#37084) use `absl::countr_zero` instead Built on #37083 which should be merged first Closes #37084 COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/37084 from ctiller:less-bespoke-3 8c30e8fdc5387f9acb1cbf0035b4474bf397775d PiperOrigin-RevId: 658642077 --- src/core/lib/promise/party.cc | 6 ++--- src/core/util/useful.h | 24 ----------------- test/core/util/useful_test.cc | 49 ----------------------------------- 3 files changed, 3 insertions(+), 76 deletions(-) diff --git a/src/core/lib/promise/party.cc b/src/core/lib/promise/party.cc index cdf6dd10296..c8bde2d198f 100644 --- a/src/core/lib/promise/party.cc +++ b/src/core/lib/promise/party.cc @@ -276,7 +276,7 @@ void Party::RunPartyAndUnref(uint64_t prev_state) { auto wakeup_mask = std::exchange(wakeup_mask_, 0); while (wakeup_mask != 0) { const uint64_t t = LowestOneBit(wakeup_mask); - const int i = CountTrailingZeros(t); + const int i = absl::countr_zero(t); wakeup_mask ^= t; // If the participant is null, skip. // This allows participants to complete whilst wakers still exist @@ -364,7 +364,7 @@ void Party::AddParticipants(Participant** participants, size_t count) { } wakeup_mask |= new_mask; allocated |= new_mask; - slots[i] = CountTrailingZeros(new_mask); + slots[i] = absl::countr_zero(new_mask); } // Try to allocate this slot and take a ref (atomically). // Ref needs to be taken because once we store the participant it could be @@ -406,7 +406,7 @@ void Party::AddParticipant(Participant* participant) { << "No available slots for new participant; allocated=" << allocated << " state=" << state << " wakeup_mask=" << wakeup_mask; allocated |= wakeup_mask; - slot = CountTrailingZeros(wakeup_mask); + slot = absl::countr_zero(wakeup_mask); // Try to allocate this slot and take a ref (atomically). // Ref needs to be taken because once we store the participant it could be // spuriously woken up and unref the party. diff --git a/src/core/util/useful.h b/src/core/util/useful.h index 37a51611901..8007c4ca334 100644 --- a/src/core/util/useful.h +++ b/src/core/util/useful.h @@ -57,30 +57,6 @@ bool GetBit(T i, size_t n) { return (i & (T(1) << n)) != 0; } -#if GRPC_HAS_BUILTIN(__builtin_ctz) -GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline uint32_t CountTrailingZeros( - uint32_t i) { - DCHECK_NE(i, 0u); // __builtin_ctz returns undefined behavior for 0 - return __builtin_ctz(i); -} -GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline uint32_t CountTrailingZeros( - uint64_t i) { - DCHECK_NE(i, 0u); // __builtin_ctz returns undefined behavior for 0 - return __builtin_ctzll(i); -} -#else -GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline uint32_t CountTrailingZeros( - uint32_t i) { - DCHECK_NE(i, 0); // __builtin_ctz returns undefined behavior for 0 - return absl::popcount((i & -i) - 1); -} -GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline uint32_t CountTrailingZeros( - uint64_t i) { - DCHECK_NE(i, 0); // __builtin_ctz returns undefined behavior for 0 - return absl::popcount((i & -i) - 1); -} -#endif - // This function uses operator< to implement a qsort-style comparison, whereby: // if a is smaller than b, a number smaller than 0 is returned. // if a is bigger than b, a number greater than 0 is returned. diff --git a/test/core/util/useful_test.cc b/test/core/util/useful_test.cc index 53067bfb629..506b2da3040 100644 --- a/test/core/util/useful_test.cc +++ b/test/core/util/useful_test.cc @@ -81,55 +81,6 @@ TEST(UsefulTest, RoundUpToPowerOf2) { EXPECT_EQ(RoundUpToPowerOf2(8), 8); } -TEST(UsefulTest, CountTrailingZeros32) { - EXPECT_EQ(CountTrailingZeros(static_cast(1)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(2)), 1); - EXPECT_EQ(CountTrailingZeros(static_cast(3)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(4)), 2); - EXPECT_EQ(CountTrailingZeros(static_cast(5)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(6)), 1); - EXPECT_EQ(CountTrailingZeros(static_cast(7)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(8)), 3); - EXPECT_EQ(CountTrailingZeros(static_cast(9)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(10)), 1); - EXPECT_EQ(CountTrailingZeros(static_cast(11)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(12)), 2); - EXPECT_EQ(CountTrailingZeros(static_cast(13)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(14)), 1); - EXPECT_EQ(CountTrailingZeros(static_cast(15)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(16)), 4); - EXPECT_EQ(CountTrailingZeros(static_cast(256)), 8); - EXPECT_EQ(CountTrailingZeros(static_cast(65535)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(65536)), 16); - EXPECT_EQ(CountTrailingZeros(static_cast(0x80000000)), 31); -} - -TEST(UsefulTest, CountTrailingZeros64) { - EXPECT_EQ(CountTrailingZeros(static_cast(1)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(2)), 1); - EXPECT_EQ(CountTrailingZeros(static_cast(3)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(4)), 2); - EXPECT_EQ(CountTrailingZeros(static_cast(5)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(6)), 1); - EXPECT_EQ(CountTrailingZeros(static_cast(7)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(8)), 3); - EXPECT_EQ(CountTrailingZeros(static_cast(9)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(10)), 1); - EXPECT_EQ(CountTrailingZeros(static_cast(11)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(12)), 2); - EXPECT_EQ(CountTrailingZeros(static_cast(13)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(14)), 1); - EXPECT_EQ(CountTrailingZeros(static_cast(15)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(16)), 4); - EXPECT_EQ(CountTrailingZeros(static_cast(256)), 8); - EXPECT_EQ(CountTrailingZeros(static_cast(65535)), 0); - EXPECT_EQ(CountTrailingZeros(static_cast(65536)), 16); - EXPECT_EQ(CountTrailingZeros(static_cast(0x80000000)), 31); - EXPECT_EQ(CountTrailingZeros(static_cast(0x100000000)), 32); - EXPECT_EQ(CountTrailingZeros(static_cast(0x1000000000000)), 48); - EXPECT_EQ(CountTrailingZeros(static_cast(0x8000000000000000)), 63); -} - TEST(UsefulTest, LowestOneBit8) { EXPECT_EQ(LowestOneBit(static_cast(0)), 0); EXPECT_EQ(LowestOneBit(static_cast(1)), 1);