[llvm] [orc-rt] Add substitutes for std::countl_zero and std::bit_width. (PR #157076)
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 5 04:17:27 PDT 2025
https://github.com/lhames created https://github.com/llvm/llvm-project/pull/157076
These can be used until the ORC runtime can assume c++-20 or greater.
>From 588e692b2fedce151b1ca8194499a81e98304faa Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Fri, 5 Sep 2025 21:11:42 +1000
Subject: [PATCH] [orc-rt] Add substitutes for std::countl_zero and
std::bit_width.
These can be used until the ORC runtime can assume c++-20 or greater.
---
orc-rt/include/orc-rt/bit.h | 23 +++++++++++
orc-rt/unittests/bit-test.cpp | 74 +++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+)
diff --git a/orc-rt/include/orc-rt/bit.h b/orc-rt/include/orc-rt/bit.h
index d86c047e0973f..241a529436de5 100644
--- a/orc-rt/include/orc-rt/bit.h
+++ b/orc-rt/include/orc-rt/bit.h
@@ -17,6 +17,7 @@
#include <cstddef>
#include <cstdint>
+#include <limits>
#include <type_traits>
#if defined(_MSC_VER) && !defined(_DEBUG)
#include <stdlib.h>
@@ -105,6 +106,28 @@ template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
}
}
+/// Calculates the number of leading zeros.
+template <typename T, typename _ = std::enable_if_t<std::is_unsigned_v<T>>>
+[[nodiscard]] constexpr int countl_zero(T Val) noexcept {
+ if (!Val)
+ return std::numeric_limits<T>::digits;
+
+ unsigned ZeroBits = 0;
+ for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
+ T Tmp = Val >> Shift;
+ if (Tmp)
+ Val = Tmp;
+ else
+ ZeroBits |= Shift;
+ }
+ return ZeroBits;
+}
+
+template <typename T, typename _ = std::enable_if_t<std::is_unsigned_v<T>>>
+[[nodiscard]] constexpr int bit_width(T x) noexcept {
+ return std::numeric_limits<T>::digits - countl_zero(x);
+}
+
} // namespace orc_rt
#endif // ORC_RT_BIT_H
diff --git a/orc-rt/unittests/bit-test.cpp b/orc-rt/unittests/bit-test.cpp
index 86e4633a5b505..fabf62b771365 100644
--- a/orc-rt/unittests/bit-test.cpp
+++ b/orc-rt/unittests/bit-test.cpp
@@ -77,3 +77,77 @@ TEST(BitTest, byte_swap_64) {
ADD_FAILURE() << "BYTE_ORDER is neither BIG_ENDIAN nor LITTLE_ENDIAN.";
#endif
}
+
+TEST(BitTest, CountlZero) {
+ uint8_t Z8 = 0;
+ uint16_t Z16 = 0;
+ uint32_t Z32 = 0;
+ uint64_t Z64 = 0;
+ EXPECT_EQ(8, llvm::countl_zero(Z8));
+ EXPECT_EQ(16, llvm::countl_zero(Z16));
+ EXPECT_EQ(32, llvm::countl_zero(Z32));
+ EXPECT_EQ(64, llvm::countl_zero(Z64));
+
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(2, llvm::countl_zero(NZ8));
+ EXPECT_EQ(10, llvm::countl_zero(NZ16));
+ EXPECT_EQ(26, llvm::countl_zero(NZ32));
+ EXPECT_EQ(58, llvm::countl_zero(NZ64));
+
+ EXPECT_EQ(8, llvm::countl_zero(0x00F000FFu));
+ EXPECT_EQ(8, llvm::countl_zero(0x00F12345u));
+ for (unsigned i = 0; i <= 30; ++i) {
+ EXPECT_EQ(int(31 - i), llvm::countl_zero(1u << i));
+ }
+
+ EXPECT_EQ(8, llvm::countl_zero(0x00F1234500F12345ULL));
+ EXPECT_EQ(1, llvm::countl_zero(1ULL << 62));
+ for (unsigned i = 0; i <= 62; ++i) {
+ EXPECT_EQ(int(63 - i), llvm::countl_zero(1ULL << i));
+ }
+}
+
+TEST(BitTest, BitWidth) {
+ EXPECT_EQ(0, llvm::bit_width(uint8_t(0)));
+ EXPECT_EQ(0, llvm::bit_width(uint16_t(0)));
+ EXPECT_EQ(0, llvm::bit_width(uint32_t(0)));
+ EXPECT_EQ(0, llvm::bit_width(uint64_t(0)));
+
+ EXPECT_EQ(1, llvm::bit_width(uint8_t(1)));
+ EXPECT_EQ(1, llvm::bit_width(uint16_t(1)));
+ EXPECT_EQ(1, llvm::bit_width(uint32_t(1)));
+ EXPECT_EQ(1, llvm::bit_width(uint64_t(1)));
+
+ EXPECT_EQ(2, llvm::bit_width(uint8_t(2)));
+ EXPECT_EQ(2, llvm::bit_width(uint16_t(2)));
+ EXPECT_EQ(2, llvm::bit_width(uint32_t(2)));
+ EXPECT_EQ(2, llvm::bit_width(uint64_t(2)));
+
+ EXPECT_EQ(2, llvm::bit_width(uint8_t(3)));
+ EXPECT_EQ(2, llvm::bit_width(uint16_t(3)));
+ EXPECT_EQ(2, llvm::bit_width(uint32_t(3)));
+ EXPECT_EQ(2, llvm::bit_width(uint64_t(3)));
+
+ EXPECT_EQ(3, llvm::bit_width(uint8_t(4)));
+ EXPECT_EQ(3, llvm::bit_width(uint16_t(4)));
+ EXPECT_EQ(3, llvm::bit_width(uint32_t(4)));
+ EXPECT_EQ(3, llvm::bit_width(uint64_t(4)));
+
+ EXPECT_EQ(7, llvm::bit_width(uint8_t(0x7f)));
+ EXPECT_EQ(15, llvm::bit_width(uint16_t(0x7fff)));
+ EXPECT_EQ(31, llvm::bit_width(uint32_t(0x7fffffffu)));
+ EXPECT_EQ(63, llvm::bit_width(uint64_t(0x7fffffffffffffffull)));
+
+ EXPECT_EQ(8, llvm::bit_width(uint8_t(0x80)));
+ EXPECT_EQ(16, llvm::bit_width(uint16_t(0x8000)));
+ EXPECT_EQ(32, llvm::bit_width(uint32_t(0x80000000u)));
+ EXPECT_EQ(64, llvm::bit_width(uint64_t(0x8000000000000000ull)));
+
+ EXPECT_EQ(8, llvm::bit_width(uint8_t(0xff)));
+ EXPECT_EQ(16, llvm::bit_width(uint16_t(0xffff)));
+ EXPECT_EQ(32, llvm::bit_width(uint32_t(0xffffffffu)));
+ EXPECT_EQ(64, llvm::bit_width(uint64_t(0xffffffffffffffffull)));
+}
More information about the llvm-commits
mailing list