LLVM: include/llvm/ADT/bit.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14#ifndef LLVM_ADT_BIT_H
15#define LLVM_ADT_BIT_H
16
18#include
19#include
20#include
21#include <type_traits>
22
23#if !__has_builtin(__builtin_bit_cast)
24#include
25#endif
26
27#if defined(_MSC_VER) && !defined(_DEBUG)
28#include
29#endif
30
31#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
32 defined(__Fuchsia__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || \
33 defined(__OpenBSD__) || defined(__DragonFly__) || defined(__managarm__)
34#include <endian.h>
35#elif defined(_AIX)
36#include <sys/machine.h>
37#elif defined(__sun)
38
39#include <sys/types.h>
40#define BIG_ENDIAN 4321
41#define LITTLE_ENDIAN 1234
42#if defined(_BIG_ENDIAN)
43#define BYTE_ORDER BIG_ENDIAN
44#else
45#define BYTE_ORDER LITTLE_ENDIAN
46#endif
47#elif defined(__MVS__)
48#define BIG_ENDIAN 4321
49#define LITTLE_ENDIAN 1234
50#define BYTE_ORDER BIG_ENDIAN
51#else
52#if !defined(BYTE_ORDER) && !defined(_WIN32)
53#include <machine/endian.h>
54#endif
55#endif
56
57#ifdef _MSC_VER
58
59
60
61extern "C" {
62unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
63unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
64unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
65unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
66}
67#endif
68
69namespace llvm {
70
74#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
76#else
78#endif
79};
80
81
82
83
84template <
85 typename To, typename From,
86 typename = std::enable_if_t<sizeof(To) == sizeof(From)>,
87 typename = std::enable_if_t<std::is_trivially_constructible::value>,
88 typename = std::enable_if_t<std::is_trivially_copyable::value>,
89 typename = std::enable_if_t<std::is_trivially_copyable::value>>
90[[nodiscard]] inline To bit_cast(const From &from) noexcept {
91#if __has_builtin(__builtin_bit_cast)
92 return __builtin_bit_cast(To, from);
93#else
94 To to;
95 std::memcpy(&to, &from, sizeof(To));
96 return to;
97#endif
98}
99
100
101template <typename T, typename = std::enable_if_t<std::is_integral_v>>
102[[nodiscard]] constexpr T byteswap(T V) noexcept {
103 if constexpr (sizeof(T) == 1) {
104 return V;
105 } else if constexpr (sizeof(T) == 2) {
107#if defined(_MSC_VER) && !defined(_DEBUG)
108
109
110 return _byteswap_ushort(UV);
111#else
115#endif
116 } else if constexpr (sizeof(T) == 4) {
118#if __has_builtin(__builtin_bswap32)
119 return __builtin_bswap32(UV);
120#elif defined(_MSC_VER) && !defined(_DEBUG)
121 return _byteswap_ulong(UV);
122#else
123 uint32_t Byte0 = UV & 0x000000FF;
124 uint32_t Byte1 = UV & 0x0000FF00;
125 uint32_t Byte2 = UV & 0x00FF0000;
126 uint32_t Byte3 = UV & 0xFF000000;
127 return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
128#endif
129 } else if constexpr (sizeof(T) == 8) {
131#if __has_builtin(__builtin_bswap64)
132 return __builtin_bswap64(UV);
133#elif defined(_MSC_VER) && !defined(_DEBUG)
134 return _byteswap_uint64(UV);
135#else
139#endif
140 } else {
141 static_assert(!sizeof(T *), "Don't know how to handle the given type.");
142 return 0;
143 }
144}
145
146template <typename T, typename = std::enable_if_t<std::is_unsigned_v>>
150
151
152
153
154template [[nodiscard]] constexpr int popcount(T Value) noexcept {
155 static_assert(std::is_unsigned_v, "T must be an unsigned integer type");
156 static_assert(sizeof(T) <= 8, "T must be 8 bytes or less");
157
158 if constexpr (sizeof(T) <= 4) {
159#if defined(__GNUC__)
160 return (int)__builtin_popcount(Value);
161#else
163 V = V - ((V >> 1) & 0x55555555);
164 V = (V & 0x33333333) + ((V >> 2) & 0x33333333);
165 return int(((V + (V >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
166#endif
167 } else {
168#if defined(__GNUC__)
169 return (int)__builtin_popcountll(Value);
170#else
172 V = V - ((V >> 1) & 0x5555555555555555ULL);
173 V = (V & 0x3333333333333333ULL) + ((V >> 2) & 0x3333333333333333ULL);
174 V = (V + (V >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
175 return int((uint64_t)(V * 0x0101010101010101ULL) >> 56);
176#endif
177 }
178}
179
180
181
182
183
184
185
186
187
189 static_assert(std::is_unsigned_v,
190 "Only unsigned integral types are allowed.");
191
192
193 return llvm::popcount(static_cast<std::make_unsigned_t>((Val & -Val) - 1));
194}
195
196
197
198
199
200
201
202template [[nodiscard]] int countr_zero(T Val) {
203 static_assert(std::is_unsigned_v,
204 "Only unsigned integral types are allowed.");
205 if (!Val)
206 return std::numeric_limits::digits;
207
208
209 if constexpr (sizeof(T) <= 4) {
210#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
211 return __builtin_ctz(Val);
212#elif defined(_MSC_VER)
213 unsigned long Index;
214 _BitScanForward(&Index, Val);
215 return Index;
216#endif
217 } else if constexpr (sizeof(T) == 8) {
218#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
219 return __builtin_ctzll(Val);
220#elif defined(_MSC_VER) && defined(_M_X64)
221 unsigned long Index;
222 _BitScanForward64(&Index, Val);
223 return Index;
224#endif
225 }
226
228}
229
230
231
232
233
234
235
236template [[nodiscard]] int countl_zero(T Val) {
237 static_assert(std::is_unsigned_v,
238 "Only unsigned integral types are allowed.");
239 if (!Val)
240 return std::numeric_limits::digits;
241
242
243 if constexpr (sizeof(T) == 4) {
244#if __has_builtin(__builtin_clz) || defined(__GNUC__)
245 return __builtin_clz(Val);
246#elif defined(_MSC_VER)
247 unsigned long Index;
248 _BitScanReverse(&Index, Val);
249 return Index ^ 31;
250#endif
251 } else if constexpr (sizeof(T) == 8) {
252#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
253 return __builtin_clzll(Val);
254#elif defined(_MSC_VER) && defined(_M_X64)
255 unsigned long Index;
256 _BitScanReverse64(&Index, Val);
257 return Index ^ 63;
258#endif
259 }
260
261
262 unsigned ZeroBits = 0;
263 for (T Shift = std::numeric_limits::digits >> 1; Shift; Shift >>= 1) {
264 T Tmp = Val >> Shift;
265 if (Tmp)
266 Val = Tmp;
267 else
268 ZeroBits |= Shift;
269 }
270 return ZeroBits;
271}
272
273
274
275
276
277
278
279
281 static_assert(std::is_unsigned_v,
282 "Only unsigned integral types are allowed.");
284}
285
286
287
288
289
290
291
292
294 static_assert(std::is_unsigned_v,
295 "Only unsigned integral types are allowed.");
297}
298
299
300
301
302
304 static_assert(std::is_unsigned_v,
305 "Only unsigned integral types are allowed.");
307}
308
309
310
311
312
313
314
316 static_assert(std::is_unsigned_v,
317 "Only unsigned integral types are allowed.");
318 int Width = 0;
319 while (Value > 0) {
321 ++Width;
322 }
323 return Width;
324}
325
326
327
328
329
331 static_assert(std::is_unsigned_v,
332 "Only unsigned integral types are allowed.");
334 return 0;
336}
337
338
339
340
341
342
343
344
346 static_assert(std::is_unsigned_v,
347 "Only unsigned integral types are allowed.");
349 return 1;
351}
352
353
354
355
356
357
358
359
361 static_assert(std::is_unsigned_v,
362 "Only unsigned integral types are allowed.");
364 return 1;
366}
367
368template <typename T, typename = std::enable_if_t<std::is_unsigned_v>>
369[[nodiscard]] constexpr T rotl(T V, int R) {
370 constexpr unsigned N = std::numeric_limits::digits;
371
372 static_assert(has_single_bit(N), "& (N - 1) is only valid for powers of two");
373 R = R & (N - 1);
374
375 if (R == 0)
376 return V;
377
378 return (V << R) | (V >> (N - R));
379}
380
381template <typename T, typename = std::enable_if_t<std::is_unsigned_v>>
382[[nodiscard]] constexpr T rotr(T V, int R) {
383 constexpr unsigned N = std::numeric_limits::digits;
384
385 static_assert(has_single_bit(N), "& (N - 1) is only valid for powers of two");
386 R = R & (N - 1);
387
388 if (R == 0)
389 return V;
390
391 return (V >> R) | (V << (N - R));
392}
393
394}
395
396#endif
LLVM Value Representation.
This is an optimization pass for GlobalISel generic memory operations.
constexpr T rotr(T V, int R)
Definition bit.h:382
constexpr T bit_ceil_constexpr(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
Definition bit.h:360
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
Definition bit.h:293
constexpr T byteswap(T V) noexcept
Reverses the bytes in the given integer value V.
Definition bit.h:102
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:303
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
Definition bit.h:345
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:154
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:202
constexpr bool has_single_bit(T Value) noexcept
Definition bit.h:147
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:236
int countl_one(T Value)
Count the number of ones from the most significant bit to the first zero bit.
Definition bit.h:280
To bit_cast(const From &from) noexcept
Definition bit.h:90
constexpr int countr_zero_constexpr(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:188
endianness
Definition bit.h:71
@ native
Definition bit.h:77
@ little
Definition bit.h:73
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:330
constexpr int bit_width_constexpr(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:315
constexpr T rotl(T V, int R)
Definition bit.h:369