Skip to content

Commit c3bb00d

Browse files
authored
[orc-rt] Add substitutes for std::countl_zero and std::bit_width. (#157076)
These can be used until the ORC runtime can assume c++-20 or greater.
1 parent c5da190 commit c3bb00d

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

orc-rt/include/orc-rt/bit.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <cstddef>
1919
#include <cstdint>
20+
#include <limits>
2021
#include <type_traits>
2122
#if defined(_MSC_VER) && !defined(_DEBUG)
2223
#include <stdlib.h>
@@ -105,6 +106,28 @@ template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
105106
}
106107
}
107108

109+
/// Calculates the number of leading zeros.
110+
template <typename T, typename _ = std::enable_if_t<std::is_unsigned_v<T>>>
111+
[[nodiscard]] constexpr int countl_zero(T Val) noexcept {
112+
if (!Val)
113+
return std::numeric_limits<T>::digits;
114+
115+
unsigned ZeroBits = 0;
116+
for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
117+
T Tmp = Val >> Shift;
118+
if (Tmp)
119+
Val = Tmp;
120+
else
121+
ZeroBits |= Shift;
122+
}
123+
return ZeroBits;
124+
}
125+
126+
template <typename T, typename _ = std::enable_if_t<std::is_unsigned_v<T>>>
127+
[[nodiscard]] constexpr int bit_width(T x) noexcept {
128+
return std::numeric_limits<T>::digits - countl_zero(x);
129+
}
130+
108131
} // namespace orc_rt
109132

110133
#endif // ORC_RT_BIT_H

orc-rt/unittests/bit-test.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,77 @@ TEST(BitTest, byte_swap_64) {
7777
ADD_FAILURE() << "BYTE_ORDER is neither BIG_ENDIAN nor LITTLE_ENDIAN.";
7878
#endif
7979
}
80+
81+
TEST(BitTest, CountlZero) {
82+
uint8_t Z8 = 0;
83+
uint16_t Z16 = 0;
84+
uint32_t Z32 = 0;
85+
uint64_t Z64 = 0;
86+
EXPECT_EQ(8, llvm::countl_zero(Z8));
87+
EXPECT_EQ(16, llvm::countl_zero(Z16));
88+
EXPECT_EQ(32, llvm::countl_zero(Z32));
89+
EXPECT_EQ(64, llvm::countl_zero(Z64));
90+
91+
uint8_t NZ8 = 42;
92+
uint16_t NZ16 = 42;
93+
uint32_t NZ32 = 42;
94+
uint64_t NZ64 = 42;
95+
EXPECT_EQ(2, llvm::countl_zero(NZ8));
96+
EXPECT_EQ(10, llvm::countl_zero(NZ16));
97+
EXPECT_EQ(26, llvm::countl_zero(NZ32));
98+
EXPECT_EQ(58, llvm::countl_zero(NZ64));
99+
100+
EXPECT_EQ(8, llvm::countl_zero(0x00F000FFu));
101+
EXPECT_EQ(8, llvm::countl_zero(0x00F12345u));
102+
for (unsigned i = 0; i <= 30; ++i) {
103+
EXPECT_EQ(int(31 - i), llvm::countl_zero(1u << i));
104+
}
105+
106+
EXPECT_EQ(8, llvm::countl_zero(0x00F1234500F12345ULL));
107+
EXPECT_EQ(1, llvm::countl_zero(1ULL << 62));
108+
for (unsigned i = 0; i <= 62; ++i) {
109+
EXPECT_EQ(int(63 - i), llvm::countl_zero(1ULL << i));
110+
}
111+
}
112+
113+
TEST(BitTest, BitWidth) {
114+
EXPECT_EQ(0, llvm::bit_width(uint8_t(0)));
115+
EXPECT_EQ(0, llvm::bit_width(uint16_t(0)));
116+
EXPECT_EQ(0, llvm::bit_width(uint32_t(0)));
117+
EXPECT_EQ(0, llvm::bit_width(uint64_t(0)));
118+
119+
EXPECT_EQ(1, llvm::bit_width(uint8_t(1)));
120+
EXPECT_EQ(1, llvm::bit_width(uint16_t(1)));
121+
EXPECT_EQ(1, llvm::bit_width(uint32_t(1)));
122+
EXPECT_EQ(1, llvm::bit_width(uint64_t(1)));
123+
124+
EXPECT_EQ(2, llvm::bit_width(uint8_t(2)));
125+
EXPECT_EQ(2, llvm::bit_width(uint16_t(2)));
126+
EXPECT_EQ(2, llvm::bit_width(uint32_t(2)));
127+
EXPECT_EQ(2, llvm::bit_width(uint64_t(2)));
128+
129+
EXPECT_EQ(2, llvm::bit_width(uint8_t(3)));
130+
EXPECT_EQ(2, llvm::bit_width(uint16_t(3)));
131+
EXPECT_EQ(2, llvm::bit_width(uint32_t(3)));
132+
EXPECT_EQ(2, llvm::bit_width(uint64_t(3)));
133+
134+
EXPECT_EQ(3, llvm::bit_width(uint8_t(4)));
135+
EXPECT_EQ(3, llvm::bit_width(uint16_t(4)));
136+
EXPECT_EQ(3, llvm::bit_width(uint32_t(4)));
137+
EXPECT_EQ(3, llvm::bit_width(uint64_t(4)));
138+
139+
EXPECT_EQ(7, llvm::bit_width(uint8_t(0x7f)));
140+
EXPECT_EQ(15, llvm::bit_width(uint16_t(0x7fff)));
141+
EXPECT_EQ(31, llvm::bit_width(uint32_t(0x7fffffffu)));
142+
EXPECT_EQ(63, llvm::bit_width(uint64_t(0x7fffffffffffffffull)));
143+
144+
EXPECT_EQ(8, llvm::bit_width(uint8_t(0x80)));
145+
EXPECT_EQ(16, llvm::bit_width(uint16_t(0x8000)));
146+
EXPECT_EQ(32, llvm::bit_width(uint32_t(0x80000000u)));
147+
EXPECT_EQ(64, llvm::bit_width(uint64_t(0x8000000000000000ull)));
148+
149+
EXPECT_EQ(8, llvm::bit_width(uint8_t(0xff)));
150+
EXPECT_EQ(16, llvm::bit_width(uint16_t(0xffff)));
151+
EXPECT_EQ(32, llvm::bit_width(uint32_t(0xffffffffu)));
152+
EXPECT_EQ(64, llvm::bit_width(uint64_t(0xffffffffffffffffull)));
153+
}

0 commit comments

Comments
 (0)