diff --git a/llvm/include/llvm/ADT/SmallPtrSet.h b/llvm/include/llvm/ADT/SmallPtrSet.h index f588a77a53b2a..8e7c8b30293b2 100644 --- a/llvm/include/llvm/ADT/SmallPtrSet.h +++ b/llvm/include/llvm/ADT/SmallPtrSet.h @@ -532,18 +532,8 @@ class SmallPtrSet : public SmallPtrSetImpl { using BaseT = SmallPtrSetImpl; - // A constexpr version of llvm::bit_ceil. - // TODO: Replace this with std::bit_ceil once C++20 is available. - static constexpr size_t RoundUpToPowerOfTwo(size_t X) { - size_t C = 1; - size_t CMax = C << (std::numeric_limits::digits - 1); - while (C < X && C < CMax) - C <<= 1; - return C; - } - // Make sure that SmallSize is a power of two, round up if not. - static constexpr size_t SmallSizePowTwo = RoundUpToPowerOfTwo(SmallSize); + static constexpr size_t SmallSizePowTwo = llvm::bit_ceil_constexpr(SmallSize); /// SmallStorage - Fixed size storage used in 'small mode'. const void *SmallStorage[SmallSizePowTwo]; diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h index 8c68d0a90c753..8b60b6998ca0b 100644 --- a/llvm/include/llvm/ADT/bit.h +++ b/llvm/include/llvm/ADT/bit.h @@ -336,6 +336,21 @@ template [[nodiscard]] T bit_ceil(T Value) { return T(1) << llvm::bit_width(Value - 1u); } +/// Returns the smallest integral power of two no smaller than Value if Value is +/// nonzero. Returns 1 otherwise. +/// +/// Ex. bit_ceil(5) == 8. +/// +/// The return value is undefined if the input is larger than the largest power +/// of two representable in T. +template [[nodiscard]] constexpr T bit_ceil_constexpr(T Value) { + static_assert(std::is_unsigned_v, + "Only unsigned integral types are allowed."); + if (Value < 2) + return 1; + return T(1) << llvm::bit_width_constexpr(Value - 1u); +} + template >> [[nodiscard]] constexpr T rotl(T V, int R) { constexpr unsigned N = std::numeric_limits::digits; diff --git a/llvm/unittests/ADT/BitTest.cpp b/llvm/unittests/ADT/BitTest.cpp index eaed4e1fe327d..5b3df918e62b0 100644 --- a/llvm/unittests/ADT/BitTest.cpp +++ b/llvm/unittests/ADT/BitTest.cpp @@ -270,6 +270,22 @@ TEST(BitTest, BitWidthConstexpr) { llvm::bit_width_constexpr(std::numeric_limits::max()) == 64); } +TEST(BitTest, BitCeilConstexpr) { + static_assert(llvm::bit_ceil_constexpr(0u) == 1); + static_assert(llvm::bit_ceil_constexpr(1u) == 1); + static_assert(llvm::bit_ceil_constexpr(2u) == 2); + static_assert(llvm::bit_ceil_constexpr(3u) == 4); + static_assert(llvm::bit_ceil_constexpr(4u) == 4); + static_assert(llvm::bit_ceil_constexpr(5u) == 8); + static_assert(llvm::bit_ceil_constexpr(6u) == 8); + static_assert(llvm::bit_ceil_constexpr(7u) == 8); + static_assert(llvm::bit_ceil_constexpr(8u) == 8); + + static_assert(llvm::bit_ceil_constexpr(255u) == 256); + static_assert(llvm::bit_ceil_constexpr(256u) == 256); + static_assert(llvm::bit_ceil_constexpr(257u) == 512); +} + TEST(BitTest, CountlZero) { uint8_t Z8 = 0; uint16_t Z16 = 0;