blob: 442f3795841acd097978019214e570fd4faf1631 [file] [log] [blame]
//===-- 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 <cstdint>
#include <cstring>
#include <type_traits>
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>>
inline To bit_cast(const From &from) noexcept {
To to;
std::memcpy(&to, &from, sizeof(To));
return to;
}
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
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 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>>>
inline int popcount(T Value) noexcept {
return detail::PopulationCounter<T, sizeof(T)>::count(Value);
}
} // namespace llvm
#endif