Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions llvm/include/llvm/ADT/BitmaskEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <utility>

#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/ADT/bit.h"
#include "llvm/Support/MathExtras.h"

/// LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can
Expand Down Expand Up @@ -138,10 +139,6 @@ template <typename E> constexpr std::underlying_type_t<E> Underlying(E Val) {
return U;
}

constexpr unsigned bitWidth(uint64_t Value) {
return Value ? 1 + bitWidth(Value >> 1) : 0;
}

template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
constexpr bool operator!(E Val) {
return Val == static_cast<E>(0);
Expand Down Expand Up @@ -220,7 +217,7 @@ e &operator>>=(e &lhs, e rhs) {
// Enable bitmask enums in namespace ::llvm and all nested namespaces.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
template <typename E, typename = std::enable_if_t<is_bitmask_enum<E>::value>>
constexpr unsigned BitWidth = BitmaskEnumDetail::bitWidth(
constexpr unsigned BitWidth = llvm::bit_width_constexpr(
uint64_t{llvm::to_underlying(E::LLVM_BITMASK_LARGEST_ENUMERATOR)});

} // namespace llvm
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/ADT/PointerUnion.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace pointer_union_detail {
/// Determine the number of bits required to store integers with values < n.
/// This is ceil(log2(n)).
constexpr int bitsRequired(unsigned n) {
return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0;
return n == 0 ? 0 : llvm::bit_width_constexpr(n - 1);
}

template <typename... Ts> constexpr int lowBitsAvailable() {
Expand Down
17 changes: 17 additions & 0 deletions llvm/include/llvm/ADT/bit.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,23 @@ template <typename T> [[nodiscard]] int bit_width(T Value) {
return std::numeric_limits<T>::digits - llvm::countl_zero(Value);
}

/// Returns the number of bits needed to represent Value if Value is nonzero.
/// Returns 0 otherwise.
///
/// A constexpr version of bit_width.
///
/// Ex. bit_width_constexpr(5) == 3.
template <typename T> [[nodiscard]] constexpr int bit_width_constexpr(T Value) {
static_assert(std::is_unsigned_v<T>,
"Only unsigned integral types are allowed.");
int Width = 0;
while (Value > 0) {
Value >>= 1;
Width++;
}
return Width;
}

/// Returns the largest integral power of two no greater than Value if Value is
/// nonzero. Returns 0 otherwise.
///
Expand Down
23 changes: 23 additions & 0 deletions llvm/unittests/ADT/BitTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,29 @@ TEST(BitTest, BitWidth) {
EXPECT_EQ(64, llvm::bit_width(uint64_t(0xffffffffffffffffull)));
}

TEST(BitTest, BitWidthConstexpr) {
static_assert(llvm::bit_width_constexpr(0u) == 0);
static_assert(llvm::bit_width_constexpr(1u) == 1);
static_assert(llvm::bit_width_constexpr(2u) == 2);
static_assert(llvm::bit_width_constexpr(3u) == 2);
static_assert(llvm::bit_width_constexpr(4u) == 3);
static_assert(llvm::bit_width_constexpr(5u) == 3);
static_assert(llvm::bit_width_constexpr(6u) == 3);
static_assert(llvm::bit_width_constexpr(7u) == 3);
static_assert(llvm::bit_width_constexpr(8u) == 4);

static_assert(llvm::bit_width_constexpr(255u) == 8);
static_assert(llvm::bit_width_constexpr(256u) == 9);
static_assert(llvm::bit_width_constexpr(257u) == 9);

static_assert(
llvm::bit_width_constexpr(std::numeric_limits<uint16_t>::max()) == 16);
static_assert(
llvm::bit_width_constexpr(std::numeric_limits<uint32_t>::max()) == 32);
static_assert(
llvm::bit_width_constexpr(std::numeric_limits<uint64_t>::max()) == 64);
}

TEST(BitTest, CountlZero) {
uint8_t Z8 = 0;
uint16_t Z16 = 0;
Expand Down