- //===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- /// 
- /// \file 
- /// This file implements the C++20 <bit> header. 
- /// 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_ADT_BIT_H 
- #define LLVM_ADT_BIT_H 
-   
- #include "llvm/Support/Compiler.h" 
- #include <cstdint> 
- #include <limits> 
- #include <type_traits> 
-   
- #if !__has_builtin(__builtin_bit_cast) 
- #include <cstring> 
- #endif 
-   
- #if defined(_MSC_VER) && !defined(_DEBUG) 
- #include <cstdlib>  // for _byteswap_{ushort,ulong,uint64} 
- #endif 
-   
- #ifdef _MSC_VER 
- // Declare these intrinsics manually rather including intrin.h. It's very 
- // expensive, and bit.h is popular via MathExtras.h. 
- // #include <intrin.h> 
- extern "C" { 
- unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask); 
- unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); 
- unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask); 
- unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); 
- } 
- #endif 
-   
- namespace llvm { 
-   
- // This implementation of bit_cast is different from the C++20 one in two ways: 
- //  - It isn't constexpr because that requires compiler support. 
- //  - It requires trivially-constructible To, to avoid UB in the implementation. 
- template < 
-     typename To, typename From, 
-     typename = std::enable_if_t<sizeof(To) == sizeof(From)>, 
-     typename = std::enable_if_t<std::is_trivially_constructible<To>::value>, 
-     typename = std::enable_if_t<std::is_trivially_copyable<To>::value>, 
-     typename = std::enable_if_t<std::is_trivially_copyable<From>::value>> 
- [[nodiscard]] inline To bit_cast(const From &from) noexcept { 
- #if __has_builtin(__builtin_bit_cast) 
-   return __builtin_bit_cast(To, from); 
- #else 
-   To to; 
-   std::memcpy(&to, &from, sizeof(To)); 
-   return to; 
- #endif 
- } 
-   
- /// Reverses the bytes in the given integer value V. 
- template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> 
- [[nodiscard]] constexpr T byteswap(T V) noexcept { 
-   if constexpr (sizeof(T) == 1) { 
-     return V; 
-   } else if constexpr (sizeof(T) == 2) { 
-     uint16_t UV = V; 
- #if defined(_MSC_VER) && !defined(_DEBUG) 
-     // The DLL version of the runtime lacks these functions (bug!?), but in a 
-     // release build they're replaced with BSWAP instructions anyway. 
-     return _byteswap_ushort(UV); 
- #else 
-     uint16_t Hi = UV << 8; 
-     uint16_t Lo = UV >> 8; 
-     return Hi | Lo; 
- #endif 
-   } else if constexpr (sizeof(T) == 4) { 
-     uint32_t UV = V; 
- #if __has_builtin(__builtin_bswap32) 
-     return __builtin_bswap32(UV); 
- #elif defined(_MSC_VER) && !defined(_DEBUG) 
-     return _byteswap_ulong(UV); 
- #else 
-     uint32_t Byte0 = UV & 0x000000FF; 
-     uint32_t Byte1 = UV & 0x0000FF00; 
-     uint32_t Byte2 = UV & 0x00FF0000; 
-     uint32_t Byte3 = UV & 0xFF000000; 
-     return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); 
- #endif 
-   } else if constexpr (sizeof(T) == 8) { 
-     uint64_t UV = V; 
- #if __has_builtin(__builtin_bswap64) 
-     return __builtin_bswap64(UV); 
- #elif defined(_MSC_VER) && !defined(_DEBUG) 
-     return _byteswap_uint64(UV); 
- #else 
-     uint64_t Hi = llvm::byteswap<uint32_t>(UV); 
-     uint32_t Lo = llvm::byteswap<uint32_t>(UV >> 32); 
-     return (Hi << 32) | Lo; 
- #endif 
-   } else { 
-     static_assert(!sizeof(T *), "Don't know how to handle the given type."); 
-     return 0; 
-   } 
- } 
-   
- template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>> 
- [[nodiscard]] constexpr inline bool has_single_bit(T Value) noexcept { 
-   return (Value != 0) && ((Value & (Value - 1)) == 0); 
- } 
-   
- namespace detail { 
- template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter { 
-   static unsigned count(T Val) { 
-     if (!Val) 
-       return std::numeric_limits<T>::digits; 
-     if (Val & 0x1) 
-       return 0; 
-   
-     // Bisection method. 
-     unsigned ZeroBits = 0; 
-     T Shift = std::numeric_limits<T>::digits >> 1; 
-     T Mask = std::numeric_limits<T>::max() >> Shift; 
-     while (Shift) { 
-       if ((Val & Mask) == 0) { 
-         Val >>= Shift; 
-         ZeroBits |= Shift; 
-       } 
-       Shift >>= 1; 
-       Mask >>= Shift; 
-     } 
-     return ZeroBits; 
-   } 
- }; 
-   
- #if defined(__GNUC__) || defined(_MSC_VER) 
- template <typename T> struct TrailingZerosCounter<T, 4> { 
-   static unsigned count(T Val) { 
-     if (Val == 0) 
-       return 32; 
-   
- #if __has_builtin(__builtin_ctz) || defined(__GNUC__) 
-     return __builtin_ctz(Val); 
- #elif defined(_MSC_VER) 
-     unsigned long Index; 
-     _BitScanForward(&Index, Val); 
-     return Index; 
- #endif 
-   } 
- }; 
-   
- #if !defined(_MSC_VER) || defined(_M_X64) 
- template <typename T> struct TrailingZerosCounter<T, 8> { 
-   static unsigned count(T Val) { 
-     if (Val == 0) 
-       return 64; 
-   
- #if __has_builtin(__builtin_ctzll) || defined(__GNUC__) 
-     return __builtin_ctzll(Val); 
- #elif defined(_MSC_VER) 
-     unsigned long Index; 
-     _BitScanForward64(&Index, Val); 
-     return Index; 
- #endif 
-   } 
- }; 
- #endif 
- #endif 
- } // namespace detail 
-   
- /// Count number of 0's from the least significant bit to the most 
- ///   stopping at the first 1. 
- /// 
- /// Only unsigned integral types are allowed. 
- /// 
- /// Returns std::numeric_limits<T>::digits on an input of 0. 
- template <typename T> [[nodiscard]] int countr_zero(T Val) { 
-   static_assert(std::is_unsigned_v<T>, 
-                 "Only unsigned integral types are allowed."); 
-   return llvm::detail::TrailingZerosCounter<T, sizeof(T)>::count(Val); 
- } 
-   
- namespace detail { 
- template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { 
-   static unsigned count(T Val) { 
-     if (!Val) 
-       return std::numeric_limits<T>::digits; 
-   
-     // Bisection method. 
-     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; 
-   } 
- }; 
-   
- #if defined(__GNUC__) || defined(_MSC_VER) 
- template <typename T> struct LeadingZerosCounter<T, 4> { 
-   static unsigned count(T Val) { 
-     if (Val == 0) 
-       return 32; 
-   
- #if __has_builtin(__builtin_clz) || defined(__GNUC__) 
-     return __builtin_clz(Val); 
- #elif defined(_MSC_VER) 
-     unsigned long Index; 
-     _BitScanReverse(&Index, Val); 
-     return Index ^ 31; 
- #endif 
-   } 
- }; 
-   
- #if !defined(_MSC_VER) || defined(_M_X64) 
- template <typename T> struct LeadingZerosCounter<T, 8> { 
-   static unsigned count(T Val) { 
-     if (Val == 0) 
-       return 64; 
-   
- #if __has_builtin(__builtin_clzll) || defined(__GNUC__) 
-     return __builtin_clzll(Val); 
- #elif defined(_MSC_VER) 
-     unsigned long Index; 
-     _BitScanReverse64(&Index, Val); 
-     return Index ^ 63; 
- #endif 
-   } 
- }; 
- #endif 
- #endif 
- } // namespace detail 
-   
- /// Count number of 0's from the most significant bit to the least 
- ///   stopping at the first 1. 
- /// 
- /// Only unsigned integral types are allowed. 
- /// 
- /// Returns std::numeric_limits<T>::digits on an input of 0. 
- template <typename T> [[nodiscard]] int countl_zero(T Val) { 
-   static_assert(std::is_unsigned_v<T>, 
-                 "Only unsigned integral types are allowed."); 
-   return llvm::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val); 
- } 
-   
- /// Count the number of ones from the most significant bit to the first 
- /// zero bit. 
- /// 
- /// Ex. countl_one(0xFF0FFF00) == 8. 
- /// Only unsigned integral types are allowed. 
- /// 
- /// Returns std::numeric_limits<T>::digits on an input of all ones. 
- template <typename T> [[nodiscard]] int countl_one(T Value) { 
-   static_assert(std::is_unsigned_v<T>, 
-                 "Only unsigned integral types are allowed."); 
-   return llvm::countl_zero<T>(~Value); 
- } 
-   
- /// Count the number of ones from the least significant bit to the first 
- /// zero bit. 
- /// 
- /// Ex. countr_one(0x00FF00FF) == 8. 
- /// Only unsigned integral types are allowed. 
- /// 
- /// Returns std::numeric_limits<T>::digits on an input of all ones. 
- template <typename T> [[nodiscard]] int countr_one(T Value) { 
-   static_assert(std::is_unsigned_v<T>, 
-                 "Only unsigned integral types are allowed."); 
-   return llvm::countr_zero<T>(~Value); 
- } 
-   
- /// Returns the number of bits needed to represent Value if Value is nonzero. 
- /// Returns 0 otherwise. 
- /// 
- /// Ex. bit_width(5) == 3. 
- template <typename T> [[nodiscard]] int bit_width(T Value) { 
-   static_assert(std::is_unsigned_v<T>, 
-                 "Only unsigned integral types are allowed."); 
-   return std::numeric_limits<T>::digits - llvm::countl_zero(Value); 
- } 
-   
- /// Returns the largest integral power of two no greater than Value if Value is 
- /// nonzero.  Returns 0 otherwise. 
- /// 
- /// Ex. bit_floor(5) == 4. 
- template <typename T> [[nodiscard]] T bit_floor(T Value) { 
-   static_assert(std::is_unsigned_v<T>, 
-                 "Only unsigned integral types are allowed."); 
-   if (!Value) 
-     return 0; 
-   return T(1) << (llvm::bit_width(Value) - 1); 
- } 
-   
- /// Returns the smallest integral power of two no smaller than Value if Value is 
- /// nonzero.  Returns 0 otherwise. 
- /// 
- /// Ex. bit_ceil(5) == 8. 
- /// 
- /// The return value is undefined if the input is larger than the largest power 
- /// of two representable in T. 
- template <typename T> [[nodiscard]] T bit_ceil(T Value) { 
-   static_assert(std::is_unsigned_v<T>, 
-                 "Only unsigned integral types are allowed."); 
-   if (Value < 2) 
-     return 1; 
-   return T(1) << llvm::bit_width<T>(Value - 1u); 
- } 
-   
- namespace detail { 
- template <typename T, std::size_t SizeOfT> struct PopulationCounter { 
-   static int count(T Value) { 
-     // Generic version, forward to 32 bits. 
-     static_assert(SizeOfT <= 4, "Not implemented!"); 
- #if defined(__GNUC__) 
-     return (int)__builtin_popcount(Value); 
- #else 
-     uint32_t v = Value; 
-     v = v - ((v >> 1) & 0x55555555); 
-     v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 
-     return int(((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24); 
- #endif 
-   } 
- }; 
-   
- template <typename T> struct PopulationCounter<T, 8> { 
-   static int count(T Value) { 
- #if defined(__GNUC__) 
-     return (int)__builtin_popcountll(Value); 
- #else 
-     uint64_t v = Value; 
-     v = v - ((v >> 1) & 0x5555555555555555ULL); 
-     v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); 
-     v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; 
-     return int((uint64_t)(v * 0x0101010101010101ULL) >> 56); 
- #endif 
-   } 
- }; 
- } // namespace detail 
-   
- /// Count the number of set bits in a value. 
- /// Ex. popcount(0xF000F000) = 8 
- /// Returns 0 if the word is zero. 
- template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>> 
- [[nodiscard]] inline int popcount(T Value) noexcept { 
-   return detail::PopulationCounter<T, sizeof(T)>::count(Value); 
- } 
-   
- } // namespace llvm 
-   
- #endif 
-