Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | /// |
||
9 | /// \file |
||
10 | /// This file implements the C++20 <bit> header. |
||
11 | /// |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_ADT_BIT_H |
||
15 | #define LLVM_ADT_BIT_H |
||
16 | |||
17 | #include "llvm/Support/Compiler.h" |
||
18 | #include <cstdint> |
||
19 | #include <limits> |
||
20 | #include <type_traits> |
||
21 | |||
22 | #if !__has_builtin(__builtin_bit_cast) |
||
23 | #include <cstring> |
||
24 | #endif |
||
25 | |||
26 | #if defined(_MSC_VER) && !defined(_DEBUG) |
||
27 | #include <cstdlib> // for _byteswap_{ushort,ulong,uint64} |
||
28 | #endif |
||
29 | |||
30 | #ifdef _MSC_VER |
||
31 | // Declare these intrinsics manually rather including intrin.h. It's very |
||
32 | // expensive, and bit.h is popular via MathExtras.h. |
||
33 | // #include <intrin.h> |
||
34 | extern "C" { |
||
35 | unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask); |
||
36 | unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); |
||
37 | unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask); |
||
38 | unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); |
||
39 | } |
||
40 | #endif |
||
41 | |||
42 | namespace llvm { |
||
43 | |||
44 | // This implementation of bit_cast is different from the C++20 one in two ways: |
||
45 | // - It isn't constexpr because that requires compiler support. |
||
46 | // - It requires trivially-constructible To, to avoid UB in the implementation. |
||
47 | template < |
||
48 | typename To, typename From, |
||
49 | typename = std::enable_if_t<sizeof(To) == sizeof(From)>, |
||
50 | typename = std::enable_if_t<std::is_trivially_constructible<To>::value>, |
||
51 | typename = std::enable_if_t<std::is_trivially_copyable<To>::value>, |
||
52 | typename = std::enable_if_t<std::is_trivially_copyable<From>::value>> |
||
53 | [[nodiscard]] inline To bit_cast(const From &from) noexcept { |
||
54 | #if __has_builtin(__builtin_bit_cast) |
||
55 | return __builtin_bit_cast(To, from); |
||
56 | #else |
||
57 | To to; |
||
58 | std::memcpy(&to, &from, sizeof(To)); |
||
59 | return to; |
||
60 | #endif |
||
61 | } |
||
62 | |||
63 | /// Reverses the bytes in the given integer value V. |
||
64 | template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> |
||
65 | [[nodiscard]] constexpr T byteswap(T V) noexcept { |
||
66 | if constexpr (sizeof(T) == 1) { |
||
67 | return V; |
||
68 | } else if constexpr (sizeof(T) == 2) { |
||
69 | uint16_t UV = V; |
||
70 | #if defined(_MSC_VER) && !defined(_DEBUG) |
||
71 | // The DLL version of the runtime lacks these functions (bug!?), but in a |
||
72 | // release build they're replaced with BSWAP instructions anyway. |
||
73 | return _byteswap_ushort(UV); |
||
74 | #else |
||
75 | uint16_t Hi = UV << 8; |
||
76 | uint16_t Lo = UV >> 8; |
||
77 | return Hi | Lo; |
||
78 | #endif |
||
79 | } else if constexpr (sizeof(T) == 4) { |
||
80 | uint32_t UV = V; |
||
81 | #if __has_builtin(__builtin_bswap32) |
||
82 | return __builtin_bswap32(UV); |
||
83 | #elif defined(_MSC_VER) && !defined(_DEBUG) |
||
84 | return _byteswap_ulong(UV); |
||
85 | #else |
||
86 | uint32_t Byte0 = UV & 0x000000FF; |
||
87 | uint32_t Byte1 = UV & 0x0000FF00; |
||
88 | uint32_t Byte2 = UV & 0x00FF0000; |
||
89 | uint32_t Byte3 = UV & 0xFF000000; |
||
90 | return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); |
||
91 | #endif |
||
92 | } else if constexpr (sizeof(T) == 8) { |
||
93 | uint64_t UV = V; |
||
94 | #if __has_builtin(__builtin_bswap64) |
||
95 | return __builtin_bswap64(UV); |
||
96 | #elif defined(_MSC_VER) && !defined(_DEBUG) |
||
97 | return _byteswap_uint64(UV); |
||
98 | #else |
||
99 | uint64_t Hi = llvm::byteswap<uint32_t>(UV); |
||
100 | uint32_t Lo = llvm::byteswap<uint32_t>(UV >> 32); |
||
101 | return (Hi << 32) | Lo; |
||
102 | #endif |
||
103 | } else { |
||
104 | static_assert(!sizeof(T *), "Don't know how to handle the given type."); |
||
105 | return 0; |
||
106 | } |
||
107 | } |
||
108 | |||
109 | template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>> |
||
110 | [[nodiscard]] constexpr inline bool has_single_bit(T Value) noexcept { |
||
111 | return (Value != 0) && ((Value & (Value - 1)) == 0); |
||
112 | } |
||
113 | |||
114 | namespace detail { |
||
115 | template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter { |
||
116 | static unsigned count(T Val) { |
||
117 | if (!Val) |
||
118 | return std::numeric_limits<T>::digits; |
||
119 | if (Val & 0x1) |
||
120 | return 0; |
||
121 | |||
122 | // Bisection method. |
||
123 | unsigned ZeroBits = 0; |
||
124 | T Shift = std::numeric_limits<T>::digits >> 1; |
||
125 | T Mask = std::numeric_limits<T>::max() >> Shift; |
||
126 | while (Shift) { |
||
127 | if ((Val & Mask) == 0) { |
||
128 | Val >>= Shift; |
||
129 | ZeroBits |= Shift; |
||
130 | } |
||
131 | Shift >>= 1; |
||
132 | Mask >>= Shift; |
||
133 | } |
||
134 | return ZeroBits; |
||
135 | } |
||
136 | }; |
||
137 | |||
138 | #if defined(__GNUC__) || defined(_MSC_VER) |
||
139 | template <typename T> struct TrailingZerosCounter<T, 4> { |
||
140 | static unsigned count(T Val) { |
||
141 | if (Val == 0) |
||
142 | return 32; |
||
143 | |||
144 | #if __has_builtin(__builtin_ctz) || defined(__GNUC__) |
||
145 | return __builtin_ctz(Val); |
||
146 | #elif defined(_MSC_VER) |
||
147 | unsigned long Index; |
||
148 | _BitScanForward(&Index, Val); |
||
149 | return Index; |
||
150 | #endif |
||
151 | } |
||
152 | }; |
||
153 | |||
154 | #if !defined(_MSC_VER) || defined(_M_X64) |
||
155 | template <typename T> struct TrailingZerosCounter<T, 8> { |
||
156 | static unsigned count(T Val) { |
||
157 | if (Val == 0) |
||
158 | return 64; |
||
159 | |||
160 | #if __has_builtin(__builtin_ctzll) || defined(__GNUC__) |
||
161 | return __builtin_ctzll(Val); |
||
162 | #elif defined(_MSC_VER) |
||
163 | unsigned long Index; |
||
164 | _BitScanForward64(&Index, Val); |
||
165 | return Index; |
||
166 | #endif |
||
167 | } |
||
168 | }; |
||
169 | #endif |
||
170 | #endif |
||
171 | } // namespace detail |
||
172 | |||
173 | /// Count number of 0's from the least significant bit to the most |
||
174 | /// stopping at the first 1. |
||
175 | /// |
||
176 | /// Only unsigned integral types are allowed. |
||
177 | /// |
||
178 | /// Returns std::numeric_limits<T>::digits on an input of 0. |
||
179 | template <typename T> [[nodiscard]] int countr_zero(T Val) { |
||
180 | static_assert(std::is_unsigned_v<T>, |
||
181 | "Only unsigned integral types are allowed."); |
||
182 | return llvm::detail::TrailingZerosCounter<T, sizeof(T)>::count(Val); |
||
183 | } |
||
184 | |||
185 | namespace detail { |
||
186 | template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { |
||
187 | static unsigned count(T Val) { |
||
188 | if (!Val) |
||
189 | return std::numeric_limits<T>::digits; |
||
190 | |||
191 | // Bisection method. |
||
192 | unsigned ZeroBits = 0; |
||
193 | for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { |
||
194 | T Tmp = Val >> Shift; |
||
195 | if (Tmp) |
||
196 | Val = Tmp; |
||
197 | else |
||
198 | ZeroBits |= Shift; |
||
199 | } |
||
200 | return ZeroBits; |
||
201 | } |
||
202 | }; |
||
203 | |||
204 | #if defined(__GNUC__) || defined(_MSC_VER) |
||
205 | template <typename T> struct LeadingZerosCounter<T, 4> { |
||
206 | static unsigned count(T Val) { |
||
207 | if (Val == 0) |
||
208 | return 32; |
||
209 | |||
210 | #if __has_builtin(__builtin_clz) || defined(__GNUC__) |
||
211 | return __builtin_clz(Val); |
||
212 | #elif defined(_MSC_VER) |
||
213 | unsigned long Index; |
||
214 | _BitScanReverse(&Index, Val); |
||
215 | return Index ^ 31; |
||
216 | #endif |
||
217 | } |
||
218 | }; |
||
219 | |||
220 | #if !defined(_MSC_VER) || defined(_M_X64) |
||
221 | template <typename T> struct LeadingZerosCounter<T, 8> { |
||
222 | static unsigned count(T Val) { |
||
223 | if (Val == 0) |
||
224 | return 64; |
||
225 | |||
226 | #if __has_builtin(__builtin_clzll) || defined(__GNUC__) |
||
227 | return __builtin_clzll(Val); |
||
228 | #elif defined(_MSC_VER) |
||
229 | unsigned long Index; |
||
230 | _BitScanReverse64(&Index, Val); |
||
231 | return Index ^ 63; |
||
232 | #endif |
||
233 | } |
||
234 | }; |
||
235 | #endif |
||
236 | #endif |
||
237 | } // namespace detail |
||
238 | |||
239 | /// Count number of 0's from the most significant bit to the least |
||
240 | /// stopping at the first 1. |
||
241 | /// |
||
242 | /// Only unsigned integral types are allowed. |
||
243 | /// |
||
244 | /// Returns std::numeric_limits<T>::digits on an input of 0. |
||
245 | template <typename T> [[nodiscard]] int countl_zero(T Val) { |
||
246 | static_assert(std::is_unsigned_v<T>, |
||
247 | "Only unsigned integral types are allowed."); |
||
248 | return llvm::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val); |
||
249 | } |
||
250 | |||
251 | /// Count the number of ones from the most significant bit to the first |
||
252 | /// zero bit. |
||
253 | /// |
||
254 | /// Ex. countl_one(0xFF0FFF00) == 8. |
||
255 | /// Only unsigned integral types are allowed. |
||
256 | /// |
||
257 | /// Returns std::numeric_limits<T>::digits on an input of all ones. |
||
258 | template <typename T> [[nodiscard]] int countl_one(T Value) { |
||
259 | static_assert(std::is_unsigned_v<T>, |
||
260 | "Only unsigned integral types are allowed."); |
||
261 | return llvm::countl_zero<T>(~Value); |
||
262 | } |
||
263 | |||
264 | /// Count the number of ones from the least significant bit to the first |
||
265 | /// zero bit. |
||
266 | /// |
||
267 | /// Ex. countr_one(0x00FF00FF) == 8. |
||
268 | /// Only unsigned integral types are allowed. |
||
269 | /// |
||
270 | /// Returns std::numeric_limits<T>::digits on an input of all ones. |
||
271 | template <typename T> [[nodiscard]] int countr_one(T Value) { |
||
272 | static_assert(std::is_unsigned_v<T>, |
||
273 | "Only unsigned integral types are allowed."); |
||
274 | return llvm::countr_zero<T>(~Value); |
||
275 | } |
||
276 | |||
277 | /// Returns the number of bits needed to represent Value if Value is nonzero. |
||
278 | /// Returns 0 otherwise. |
||
279 | /// |
||
280 | /// Ex. bit_width(5) == 3. |
||
281 | template <typename T> [[nodiscard]] int bit_width(T Value) { |
||
282 | static_assert(std::is_unsigned_v<T>, |
||
283 | "Only unsigned integral types are allowed."); |
||
284 | return std::numeric_limits<T>::digits - llvm::countl_zero(Value); |
||
285 | } |
||
286 | |||
287 | /// Returns the largest integral power of two no greater than Value if Value is |
||
288 | /// nonzero. Returns 0 otherwise. |
||
289 | /// |
||
290 | /// Ex. bit_floor(5) == 4. |
||
291 | template <typename T> [[nodiscard]] T bit_floor(T Value) { |
||
292 | static_assert(std::is_unsigned_v<T>, |
||
293 | "Only unsigned integral types are allowed."); |
||
294 | if (!Value) |
||
295 | return 0; |
||
296 | return T(1) << (llvm::bit_width(Value) - 1); |
||
297 | } |
||
298 | |||
299 | /// Returns the smallest integral power of two no smaller than Value if Value is |
||
300 | /// nonzero. Returns 0 otherwise. |
||
301 | /// |
||
302 | /// Ex. bit_ceil(5) == 8. |
||
303 | /// |
||
304 | /// The return value is undefined if the input is larger than the largest power |
||
305 | /// of two representable in T. |
||
306 | template <typename T> [[nodiscard]] T bit_ceil(T Value) { |
||
307 | static_assert(std::is_unsigned_v<T>, |
||
308 | "Only unsigned integral types are allowed."); |
||
309 | if (Value < 2) |
||
310 | return 1; |
||
311 | return T(1) << llvm::bit_width<T>(Value - 1u); |
||
312 | } |
||
313 | |||
314 | namespace detail { |
||
315 | template <typename T, std::size_t SizeOfT> struct PopulationCounter { |
||
316 | static int count(T Value) { |
||
317 | // Generic version, forward to 32 bits. |
||
318 | static_assert(SizeOfT <= 4, "Not implemented!"); |
||
319 | #if defined(__GNUC__) |
||
320 | return (int)__builtin_popcount(Value); |
||
321 | #else |
||
322 | uint32_t v = Value; |
||
323 | v = v - ((v >> 1) & 0x55555555); |
||
324 | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); |
||
325 | return int(((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24); |
||
326 | #endif |
||
327 | } |
||
328 | }; |
||
329 | |||
330 | template <typename T> struct PopulationCounter<T, 8> { |
||
331 | static int count(T Value) { |
||
332 | #if defined(__GNUC__) |
||
333 | return (int)__builtin_popcountll(Value); |
||
334 | #else |
||
335 | uint64_t v = Value; |
||
336 | v = v - ((v >> 1) & 0x5555555555555555ULL); |
||
337 | v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); |
||
338 | v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; |
||
339 | return int((uint64_t)(v * 0x0101010101010101ULL) >> 56); |
||
340 | #endif |
||
341 | } |
||
342 | }; |
||
343 | } // namespace detail |
||
344 | |||
345 | /// Count the number of set bits in a value. |
||
346 | /// Ex. popcount(0xF000F000) = 8 |
||
347 | /// Returns 0 if the word is zero. |
||
348 | template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>> |
||
349 | [[nodiscard]] inline int popcount(T Value) noexcept { |
||
350 | return detail::PopulationCounter<T, sizeof(T)>::count(Value); |
||
351 | } |
||
352 | |||
353 | } // namespace llvm |
||
354 | |||
355 | #endif |