Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

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