Skip to content

Commit 6e92f7e

Browse files
[ADT] Add bit_ceil_constexpr (#164115)
This patch adds llvm::bit_ceil_constexpr, a constexpr version of llvm::bit_ceil. The new function is intended to serve as a marker. When we switch to C++20, we will most likely go through functions in llvm/ADT/bit.h and replace them with their counterparts from <bit>. With llvm::bit_ceil_constexpr, we can easily replace its use with std::bit_ceil. This patch replaces RoundUpToPowerOfTwo in SmallPtrSet.h the new function.
1 parent cf28a47 commit 6e92f7e

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

llvm/include/llvm/ADT/SmallPtrSet.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -532,18 +532,8 @@ class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
532532

533533
using BaseT = SmallPtrSetImpl<PtrType>;
534534

535-
// A constexpr version of llvm::bit_ceil.
536-
// TODO: Replace this with std::bit_ceil once C++20 is available.
537-
static constexpr size_t RoundUpToPowerOfTwo(size_t X) {
538-
size_t C = 1;
539-
size_t CMax = C << (std::numeric_limits<size_t>::digits - 1);
540-
while (C < X && C < CMax)
541-
C <<= 1;
542-
return C;
543-
}
544-
545535
// Make sure that SmallSize is a power of two, round up if not.
546-
static constexpr size_t SmallSizePowTwo = RoundUpToPowerOfTwo(SmallSize);
536+
static constexpr size_t SmallSizePowTwo = llvm::bit_ceil_constexpr(SmallSize);
547537
/// SmallStorage - Fixed size storage used in 'small mode'.
548538
const void *SmallStorage[SmallSizePowTwo];
549539

llvm/include/llvm/ADT/bit.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,21 @@ template <typename T> [[nodiscard]] T bit_ceil(T Value) {
336336
return T(1) << llvm::bit_width<T>(Value - 1u);
337337
}
338338

339+
/// Returns the smallest integral power of two no smaller than Value if Value is
340+
/// nonzero. Returns 1 otherwise.
341+
///
342+
/// Ex. bit_ceil(5) == 8.
343+
///
344+
/// The return value is undefined if the input is larger than the largest power
345+
/// of two representable in T.
346+
template <typename T> [[nodiscard]] constexpr T bit_ceil_constexpr(T Value) {
347+
static_assert(std::is_unsigned_v<T>,
348+
"Only unsigned integral types are allowed.");
349+
if (Value < 2)
350+
return 1;
351+
return T(1) << llvm::bit_width_constexpr<T>(Value - 1u);
352+
}
353+
339354
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
340355
[[nodiscard]] constexpr T rotl(T V, int R) {
341356
constexpr unsigned N = std::numeric_limits<T>::digits;

llvm/unittests/ADT/BitTest.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,22 @@ TEST(BitTest, BitWidthConstexpr) {
270270
llvm::bit_width_constexpr(std::numeric_limits<uint64_t>::max()) == 64);
271271
}
272272

273+
TEST(BitTest, BitCeilConstexpr) {
274+
static_assert(llvm::bit_ceil_constexpr(0u) == 1);
275+
static_assert(llvm::bit_ceil_constexpr(1u) == 1);
276+
static_assert(llvm::bit_ceil_constexpr(2u) == 2);
277+
static_assert(llvm::bit_ceil_constexpr(3u) == 4);
278+
static_assert(llvm::bit_ceil_constexpr(4u) == 4);
279+
static_assert(llvm::bit_ceil_constexpr(5u) == 8);
280+
static_assert(llvm::bit_ceil_constexpr(6u) == 8);
281+
static_assert(llvm::bit_ceil_constexpr(7u) == 8);
282+
static_assert(llvm::bit_ceil_constexpr(8u) == 8);
283+
284+
static_assert(llvm::bit_ceil_constexpr(255u) == 256);
285+
static_assert(llvm::bit_ceil_constexpr(256u) == 256);
286+
static_assert(llvm::bit_ceil_constexpr(257u) == 512);
287+
}
288+
273289
TEST(BitTest, CountlZero) {
274290
uint8_t Z8 = 0;
275291
uint16_t Z16 = 0;

0 commit comments

Comments
 (0)