diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 502bf72ae9906..d6dbad661cb73 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -135,13 +135,13 @@ add_header_library( .str_to_num_result .uint128 libc.src.__support.common - libc.src.__support.CPP.bit libc.src.__support.CPP.limits libc.src.__support.CPP.optional libc.src.__support.FPUtil.dyadic_float libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.rounding_mode + libc.src.__support.bit libc.src.errno.errno ) @@ -188,10 +188,10 @@ add_header_library( HDRS integer_utils.h DEPENDS + .bit .math_extras .number_pair libc.src.__support.common - libc.src.__support.CPP.bit libc.src.__support.CPP.type_traits ) @@ -200,11 +200,11 @@ add_header_library( HDRS UInt.h DEPENDS + .bit .integer_utils .math_extras .number_pair libc.src.__support.CPP.array - libc.src.__support.CPP.bit libc.src.__support.CPP.type_traits libc.src.__support.macros.optimization ) @@ -231,9 +231,8 @@ add_header_library( HDRS hash.h DEPENDS + .bit .uint128 - libc.src.__support.CPP.bit - libc.src.__support.CPP.limits libc.src.__support.macros.attributes ) diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt index 3d6d712fc2058..58a182eaa797b 100644 --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -41,6 +41,7 @@ add_header_library( libc.src.__support.common libc.src.__support.CPP.bit libc.src.__support.CPP.type_traits + libc.src.__support.bit ) add_header_library( @@ -145,6 +146,7 @@ add_header_library( libc.src.__support.common libc.src.__support.CPP.bit libc.src.__support.CPP.type_traits + libc.src.__support.bit libc.src.__support.uint128 ) diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index ca98aa7126249..f5b73440de215 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -11,6 +11,7 @@ #include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" +#include "src/__support/bit.h" #include "src/__support/common.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE @@ -221,7 +222,7 @@ template struct FPBits { LIBC_INLINE static constexpr FPBits make_value(UIntType number, int ep) { FPBits result; // offset: +1 for sign, but -1 for implicit first bit - int lz = cpp::countl_zero(number) - FloatProp::EXPONENT_WIDTH; + int lz = unsafe_clz(number) - FloatProp::EXPONENT_WIDTH; number <<= lz; ep -= lz; diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h index 8a6eb4b920acd..db2a62fbdf2a1 100644 --- a/libc/src/__support/FPUtil/Hypot.h +++ b/libc/src/__support/FPUtil/Hypot.h @@ -16,6 +16,7 @@ #include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/UInt128.h" +#include "src/__support/bit.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { @@ -27,7 +28,7 @@ template LIBC_INLINE T find_leading_one(T mant, int &shift_length) { shift_length = 0; if (mant > 0) { - shift_length = (sizeof(mant) * 8) - 1 - cpp::countl_zero(mant); + shift_length = (sizeof(mant) * 8) - 1 - unsafe_clz(mant); } return T(1) << shift_length; } @@ -36,13 +37,9 @@ LIBC_INLINE T find_leading_one(T mant, int &shift_length) { template struct DoubleLength; -template <> struct DoubleLength { - using Type = uint32_t; -}; +template <> struct DoubleLength { using Type = uint32_t; }; -template <> struct DoubleLength { - using Type = uint64_t; -}; +template <> struct DoubleLength { using Type = uint64_t; }; template <> struct DoubleLength { using Type = UInt128; diff --git a/libc/src/__support/FPUtil/generic/CMakeLists.txt b/libc/src/__support/FPUtil/generic/CMakeLists.txt index b17f325210473..c799d502b47d6 100644 --- a/libc/src/__support/FPUtil/generic/CMakeLists.txt +++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt @@ -11,6 +11,7 @@ add_header_library( libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.rounding_mode + libc.src.__support.bit libc.src.__support.uint128 ) @@ -20,13 +21,13 @@ add_header_library( FMA.h DEPENDS libc.src.__support.common - libc.src.__support.CPP.bit libc.src.__support.CPP.type_traits libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.float_properties libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.rounding_mode libc.src.__support.macros.optimization + libc.src.__support.bit libc.src.__support.uint128 ) @@ -36,12 +37,12 @@ add_header_library( FMod.h DEPENDS libc.src.__support.common - libc.src.__support.CPP.bit libc.src.__support.CPP.type_traits libc.src.__support.FPUtil.fenv_impl libc.src.__support.FPUtil.float_properties libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.rounding_mode libc.src.__support.macros.optimization + libc.src.__support.bit libc.src.math.generic.math_utils ) diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h index 4a825f2f4942c..5a856d1447330 100644 --- a/libc/src/__support/FPUtil/generic/FMA.h +++ b/libc/src/__support/FPUtil/generic/FMA.h @@ -9,13 +9,13 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_FMA_H #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_FMA_H -#include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/FloatProperties.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/UInt128.h" +#include "src/__support/bit.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY @@ -209,9 +209,9 @@ template <> LIBC_INLINE double fma(double x, double y, double z) { // Normalize the result. if (prod_mant != 0) { uint64_t prod_hi = static_cast(prod_mant >> 64); - int lead_zeros = - prod_hi ? cpp::countl_zero(prod_hi) - : 64 + cpp::countl_zero(static_cast(prod_mant)); + int lead_zeros = prod_hi + ? unsafe_clz(prod_hi) + : 64 + unsafe_clz(static_cast(prod_mant)); // Move the leading 1 to the most significant bit. prod_mant <<= lead_zeros; // The lower 64 bits are always sticky bits after moving the leading 1 to diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h index 0e71b039d5c06..6f934cd4a87bd 100644 --- a/libc/src/__support/FPUtil/generic/FMod.h +++ b/libc/src/__support/FPUtil/generic/FMod.h @@ -9,11 +9,11 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_FMOD_H #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_FMOD_H -#include "src/__support/CPP/bit.h" #include "src/__support/CPP/limits.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" +#include "src/__support/bit.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY #include "src/math/generic/math_utils.h" @@ -229,7 +229,7 @@ class FMod { if (LIBC_LIKELY(sx.uintval() <= sy.uintval())) { if (sx.uintval() < sy.uintval()) - return sx; // |x|<|y| return x + return sx; // |x|<|y| return x return FPB(FPB::zero()); // |x|=|y| return 0.0 } @@ -264,11 +264,11 @@ class FMod { e_y--; } else { m_y = sy.get_mantissa(); - lead_zeros_m_y = cpp::countl_zero(m_y); + lead_zeros_m_y = unsafe_clz(m_y); } // Assume hy != 0 - int tail_zeros_m_y = cpp::countr_zero(m_y); + int tail_zeros_m_y = unsafe_ctz(m_y); int sides_zeroes_count = lead_zeros_m_y + tail_zeros_m_y; // n > 0 by conditions above int exp_diff = e_x - e_y; diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h index 6ae2171bacf7b..b93fa7a35f826 100644 --- a/libc/src/__support/FPUtil/generic/sqrt.h +++ b/libc/src/__support/FPUtil/generic/sqrt.h @@ -10,12 +10,13 @@ #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_SQRT_H #include "sqrt_80_bit_long_double.h" -#include "src/__support/CPP/bit.h" // countl_zero +#include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/UInt128.h" +#include "src/__support/bit.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { @@ -36,7 +37,7 @@ template <> struct SpecialLongDouble { template LIBC_INLINE void normalize(int &exponent, typename FPBits::UIntType &mantissa) { - const int shift = cpp::countl_zero(mantissa) - + const int shift = unsafe_clz(mantissa) - (8 * sizeof(mantissa) - 1 - MantissaWidth::VALUE); exponent -= shift; mantissa <<= shift; @@ -51,9 +52,9 @@ LIBC_INLINE void normalize(int &exponent, uint64_t &mantissa) { template <> LIBC_INLINE void normalize(int &exponent, UInt128 &mantissa) { const uint64_t hi_bits = static_cast(mantissa >> 64); - const int shift = - hi_bits ? (cpp::countl_zero(hi_bits) - 15) - : (cpp::countl_zero(static_cast(mantissa)) + 49); + const int shift = hi_bits + ? (unsafe_clz(hi_bits) - 15) + : (unsafe_clz(static_cast(mantissa)) + 49); exponent -= shift; mantissa <<= shift; } @@ -136,7 +137,7 @@ LIBC_INLINE cpp::enable_if_t, T> sqrt(T x) { // We compute one more iteration in order to round correctly. bool lsb = static_cast(y & 1); // Least significant bit - bool rb = false; // Round bit + bool rb = false; // Round bit r <<= 2; UIntType tmp = (y << 2) + 1; if (r >= tmp) { diff --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h index 0e7907e82943a..a3bf7e3cabad3 100644 --- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h +++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h @@ -9,11 +9,11 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_SQRT_80_BIT_LONG_DOUBLE_H #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_SQRT_80_BIT_LONG_DOUBLE_H -#include "src/__support/CPP/bit.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/UInt128.h" +#include "src/__support/bit.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { @@ -22,7 +22,7 @@ namespace x86 { LIBC_INLINE void normalize(int &exponent, UInt128 &mantissa) { const unsigned int shift = static_cast( - cpp::countl_zero(static_cast(mantissa)) - + unsafe_clz(static_cast(mantissa)) - (8 * sizeof(uint64_t) - 1 - MantissaWidth::VALUE)); exponent -= shift; mantissa <<= shift; @@ -101,7 +101,7 @@ LIBC_INLINE long double sqrt(long double x) { // We compute one more iteration in order to round correctly. bool lsb = static_cast(y & 1); // Least significant bit - bool rb = false; // Round bit + bool rb = false; // Round bit r <<= 2; UIntType tmp = (y << 2) + 1; if (r >= tmp) { diff --git a/libc/src/__support/HashTable/CMakeLists.txt b/libc/src/__support/HashTable/CMakeLists.txt index 920ba194badd9..e9b4aa31290a1 100644 --- a/libc/src/__support/HashTable/CMakeLists.txt +++ b/libc/src/__support/HashTable/CMakeLists.txt @@ -6,7 +6,7 @@ add_header_library( PREFER_GENERIC DEPENDS libc.src.__support.common - libc.src.__support.CPP.bit + libc.src.__support.bit libc.src.__support.macros.properties.cpu_features ) @@ -25,17 +25,17 @@ add_header_library( table.h DEPENDS .bitmask - libc.include.llvm-libc-types.ENTRY - libc.src.__support.CPP.bit - libc.src.__support.CPP.new + libc.src.__support.memory_size + libc.src.__support.bit libc.src.__support.CPP.type_traits - libc.src.__support.hash + libc.src.__support.CPP.new libc.src.__support.macros.attributes libc.src.__support.macros.optimization - libc.src.__support.memory_size + libc.src.__support.hash libc.src.string.memset libc.src.string.strcmp libc.src.string.strlen + libc.include.llvm-libc-types.ENTRY ) add_header_library( diff --git a/libc/src/__support/HashTable/bitmask.h b/libc/src/__support/HashTable/bitmask.h index c775b09f2236f..38c9860020594 100644 --- a/libc/src/__support/HashTable/bitmask.h +++ b/libc/src/__support/HashTable/bitmask.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_HASHTABLE_BITMASK_H #define LLVM_LIBC_SRC___SUPPORT_HASHTABLE_BITMASK_H -#include "src/__support/CPP/bit.h" +#include "src/__support/bit.h" #include "src/__support/macros/properties/cpu_features.h" #include // size_t #include // uint8_t, uint64_t @@ -45,7 +45,7 @@ template struct BitMaskAdaptor { // Count trailing zeros with respect to stride. (Assume the bitmask is none // zero.) LIBC_INLINE constexpr size_t lowest_set_bit_nonzero() const { - return cpp::countr_zero(word) / WORD_STRIDE; + return unsafe_ctz(word) / WORD_STRIDE; } }; diff --git a/libc/src/__support/HashTable/table.h b/libc/src/__support/HashTable/table.h index 305fe59792d5a..ec0ec78869ad5 100644 --- a/libc/src/__support/HashTable/table.h +++ b/libc/src/__support/HashTable/table.h @@ -10,10 +10,10 @@ #define LLVM_LIBC_SRC___SUPPORT_HASHTABLE_table_H #include "include/llvm-libc-types/ENTRY.h" -#include "src/__support/CPP/bit.h" // bit_ceil #include "src/__support/CPP/new.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/HashTable/bitmask.h" +#include "src/__support/bit.h" #include "src/__support/hash.h" #include "src/__support/macros/attributes.h" #include "src/__support/macros/optimization.h" @@ -70,7 +70,7 @@ LIBC_INLINE size_t capacity_to_entries(size_t cap) { if (cap < sizeof(Group)) cap = sizeof(Group); // overflow is always checked in allocate() - return cpp::bit_ceil(cap * 8 / 7); + return next_power_of_two(cap * 8 / 7); } // The heap memory layout for N buckets HashTable is as follows: @@ -98,8 +98,7 @@ struct HashTable { LIBC_INLINE size_t offset_from_entries() const { size_t entries_size = num_of_entries() * sizeof(ENTRY); - return entries_size + - SafeMemSize::offset_to(entries_size, table_alignment()); + return entries_size + offset_to(entries_size, table_alignment()); } LIBC_INLINE constexpr static size_t table_alignment() { diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h index 3bec2e3a47130..248324c326dfb 100644 --- a/libc/src/__support/UInt.h +++ b/libc/src/__support/UInt.h @@ -10,10 +10,10 @@ #define LLVM_LIBC_SRC___SUPPORT_UINT_H #include "src/__support/CPP/array.h" -#include "src/__support/CPP/bit.h" // countl_zero #include "src/__support/CPP/limits.h" #include "src/__support/CPP/optional.h" #include "src/__support/CPP/type_traits.h" +#include "src/__support/bit.h" // unsafe_clz #include "src/__support/integer_utils.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY @@ -557,7 +557,7 @@ template struct BigInt { if (val[i - 1] == 0) { leading_zeroes += sizeof(uint64_t) * 8; } else { - leading_zeroes += countl_zero(val[i - 1]); + leading_zeroes += unsafe_clz(val[i - 1]); break; } } diff --git a/libc/src/__support/bit.h b/libc/src/__support/bit.h new file mode 100644 index 0000000000000..ba7fc31de1227 --- /dev/null +++ b/libc/src/__support/bit.h @@ -0,0 +1,117 @@ +//===-- Mimics llvm/ADT/Bit.h -----------------------------------*- C++ -*-===// +// Provides useful bit functions. +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_BIT_H +#define LLVM_LIBC_SRC___SUPPORT_BIT_H + +#include "src/__support/CPP/type_traits.h" // make_unsigned +#include "src/__support/macros/attributes.h" // LIBC_INLINE + +namespace LIBC_NAMESPACE { + +// The following overloads are matched based on what is accepted by +// __builtin_clz/ctz* rather than using the exactly-sized aliases from stdint.h. +// This way, we can avoid making any assumptions about integer sizes and let the +// compiler match for us. +namespace __internal { + +template LIBC_INLINE int constexpr correct_zero(T val, int bits) { + if (val == T(0)) + return sizeof(T(0)) * 8; + else + return bits; +} + +template LIBC_INLINE constexpr int clz(T val); +template <> LIBC_INLINE int clz(unsigned char val) { + return __builtin_clz(static_cast(val)) - + 8 * static_cast(sizeof(unsigned int) - sizeof(unsigned char)); +} +template <> LIBC_INLINE int clz(unsigned short val) { + return __builtin_clz(static_cast(val)) - + 8 * static_cast(sizeof(unsigned int) - sizeof(unsigned short)); +} +template <> LIBC_INLINE int clz(unsigned int val) { + return __builtin_clz(val); +} +template <> +LIBC_INLINE constexpr int clz(unsigned long int val) { + return __builtin_clzl(val); +} +template <> +LIBC_INLINE constexpr int +clz(unsigned long long int val) { + return __builtin_clzll(val); +} + +template LIBC_INLINE constexpr int ctz(T val); +template <> LIBC_INLINE int ctz(unsigned char val) { + return __builtin_ctz(static_cast(val)); +} +template <> LIBC_INLINE int ctz(unsigned short val) { + return __builtin_ctz(static_cast(val)); +} +template <> LIBC_INLINE int ctz(unsigned int val) { + return __builtin_ctz(val); +} +template <> +LIBC_INLINE constexpr int ctz(unsigned long int val) { + return __builtin_ctzl(val); +} +template <> +LIBC_INLINE constexpr int +ctz(unsigned long long int val) { + return __builtin_ctzll(val); +} +} // namespace __internal + +template LIBC_INLINE constexpr int safe_ctz(T val) { + return __internal::correct_zero(val, __internal::ctz(val)); +} + +template LIBC_INLINE constexpr int unsafe_ctz(T val) { + return __internal::ctz(val); +} + +template LIBC_INLINE constexpr int safe_clz(T val) { + return __internal::correct_zero(val, __internal::clz(val)); +} + +template LIBC_INLINE constexpr int unsafe_clz(T val) { + return __internal::clz(val); +} + +template LIBC_INLINE constexpr T next_power_of_two(T val) { + if (val == 0) + return 1; + T idx = safe_clz(val - 1); + return static_cast(1) << ((8ull * sizeof(T)) - idx); +} + +template LIBC_INLINE constexpr bool is_power_of_two(T val) { + return val != 0 && (val & (val - 1)) == 0; +} + +template LIBC_INLINE constexpr T offset_to(T val, T align) { + return (-val) & (align - 1); +} + +template LIBC_INLINE constexpr T rotate_left(T val, T amount) { + // Implementation taken from "Safe, Efficient, and Portable Rotate in C/C++" + // https://blog.regehr.org/archives/1063 + // Using the safe version as the rotation pattern is now recognized by both + // GCC and Clang. + using U = cpp::make_unsigned_t; + U v = static_cast(val); + U a = static_cast(amount); + return (v << a) | (v >> ((-a) & (sizeof(U) * 8 - 1))); +} +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC___SUPPORT_BIT_H diff --git a/libc/src/__support/hash.h b/libc/src/__support/hash.h index 6b362ba831891..ad12cf79e8d2c 100644 --- a/libc/src/__support/hash.h +++ b/libc/src/__support/hash.h @@ -9,9 +9,8 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_HASH_H #define LLVM_LIBC_SRC___SUPPORT_HASH_H -#include "src/__support/CPP/bit.h" // rotl -#include "src/__support/CPP/limits.h" // numeric_limits #include "src/__support/UInt128.h" // UInt128 +#include "src/__support/bit.h" // rotate_left #include "src/__support/macros/attributes.h" // LIBC_INLINE #include // For uint64_t @@ -104,7 +103,7 @@ class HashState { uint64_t combined = folded_multiply(low ^ extra_keys[0], high ^ extra_keys[1]); buffer = (buffer + pad) ^ combined; - buffer = cpp::rotl(buffer, ROTATE); + buffer = rotate_left(buffer, ROTATE); } LIBC_INLINE static uint64_t mix(uint64_t seed) { HashState mixer{RANDOMNESS[0][0], RANDOMNESS[0][1], RANDOMNESS[0][2], @@ -153,9 +152,9 @@ class HashState { } } LIBC_INLINE uint64_t finish() { - int rot = buffer & 63; + uint64_t rot = buffer & 63; uint64_t folded = folded_multiply(buffer, pad); - return cpp::rotl(folded, rot); + return rotate_left(folded, rot); } }; diff --git a/libc/src/__support/integer_utils.h b/libc/src/__support/integer_utils.h index 1d9a134934cc5..661318f03bfd3 100644 --- a/libc/src/__support/integer_utils.h +++ b/libc/src/__support/integer_utils.h @@ -12,6 +12,7 @@ #include "src/__support/CPP/type_traits.h" #include "src/__support/common.h" +#include "bit.h" #include "math_extras.h" #include "number_pair.h" diff --git a/libc/src/__support/memory_size.h b/libc/src/__support/memory_size.h index 4c7d2079553e8..df179a6604714 100644 --- a/libc/src/__support/memory_size.h +++ b/libc/src/__support/memory_size.h @@ -6,12 +6,11 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/CPP/bit.h" // has_single_bit #include "src/__support/CPP/limits.h" #include "src/__support/CPP/type_traits.h" +#include "src/__support/bit.h" #include "src/__support/macros/attributes.h" #include "src/__support/macros/optimization.h" -#include "src/string/memory_utils/utils.h" namespace LIBC_NAMESPACE { namespace internal { @@ -38,18 +37,10 @@ class SafeMemSize { public: LIBC_INLINE_VAR static constexpr size_t MAX_MEM_SIZE = static_cast(cpp::numeric_limits::max()); - LIBC_INLINE explicit SafeMemSize(size_t value) : value(value <= MAX_MEM_SIZE ? static_cast(value) : -1) {} - - LIBC_INLINE static constexpr size_t offset_to(size_t val, size_t align) { - return (-val) & (align - 1); - } - LIBC_INLINE operator size_t() { return static_cast(value); } - LIBC_INLINE bool valid() { return value >= 0; } - LIBC_INLINE SafeMemSize operator+(const SafeMemSize &other) { type result; if (LIBC_UNLIKELY((value | other.value) < 0)) @@ -57,7 +48,6 @@ class SafeMemSize { result = value + other.value; return SafeMemSize{result}; } - LIBC_INLINE SafeMemSize operator*(const SafeMemSize &other) { type result; if (LIBC_UNLIKELY((value | other.value) < 0)) @@ -66,12 +56,11 @@ class SafeMemSize { result = -1; return SafeMemSize{result}; } - LIBC_INLINE SafeMemSize align_up(size_t alignment) { - if (!cpp::has_single_bit(alignment) || alignment > MAX_MEM_SIZE || !valid()) + if (!is_power_of_two(alignment) || alignment > MAX_MEM_SIZE || !valid()) return SafeMemSize{type{-1}}; - type offset = offset_to(value, alignment); + type offset = LIBC_NAMESPACE::offset_to(value, alignment); if (LIBC_UNLIKELY(offset > static_cast(MAX_MEM_SIZE) - value)) return SafeMemSize{type{-1}}; diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h index ad73e93f6faa8..a872c25e2f099 100644 --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -16,6 +16,7 @@ #include "src/__support/FPUtil/dyadic_float.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/UInt128.h" +#include "src/__support/bit.h" #include "src/__support/common.h" #include "src/__support/ctype_utils.h" #include "src/__support/detailed_powers_of_ten.h" @@ -68,12 +69,12 @@ template LIBC_INLINE uint32_t leading_zeroes(T inputNumber) { template <> LIBC_INLINE uint32_t leading_zeroes(uint32_t inputNumber) { - return cpp::countl_zero(inputNumber); + return safe_clz(inputNumber); } template <> LIBC_INLINE uint32_t leading_zeroes(uint64_t inputNumber) { - return cpp::countl_zero(inputNumber); + return safe_clz(inputNumber); } LIBC_INLINE uint64_t low64(const UInt128 &num) { diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 214d57842d93b..5380502210828 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -780,6 +780,7 @@ add_entrypoint_object( .explogxf libc.include.errno libc.include.math + libc.src.__support.bit libc.src.__support.CPP.bit libc.src.__support.CPP.optional libc.src.__support.FPUtil.fenv_impl diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp index 5f2e95b44e528..2de8e76b04b5a 100644 --- a/libc/src/math/generic/powf.cpp +++ b/libc/src/math/generic/powf.cpp @@ -18,6 +18,7 @@ #include "src/__support/FPUtil/nearest_integer.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/FPUtil/sqrt.h" // Speedup for powf(x, 1/2) = sqrtf(x) +#include "src/__support/bit.h" #include "src/__support/common.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY @@ -391,7 +392,7 @@ LIBC_INLINE bool is_odd_integer(float x) { uint32_t x_u = cpp::bit_cast(x); int x_e = static_cast((x_u & FloatProp::EXPONENT_MASK) >> FloatProp::MANTISSA_WIDTH); - int lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK); + int lsb = unsafe_ctz(x_u | FloatProp::EXPONENT_MASK); constexpr int UNIT_EXPONENT = static_cast(FloatProp::EXPONENT_BIAS + FloatProp::MANTISSA_WIDTH); return (x_e + lsb == UNIT_EXPONENT); @@ -402,7 +403,7 @@ LIBC_INLINE bool is_integer(float x) { uint32_t x_u = cpp::bit_cast(x); int x_e = static_cast((x_u & FloatProp::EXPONENT_MASK) >> FloatProp::MANTISSA_WIDTH); - int lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK); + int lsb = unsafe_ctz(x_u | FloatProp::EXPONENT_MASK); constexpr int UNIT_EXPONENT = static_cast(FloatProp::EXPONENT_BIAS + FloatProp::MANTISSA_WIDTH); return (x_e + lsb >= UNIT_EXPONENT); diff --git a/libc/src/string/memory_utils/op_builtin.h b/libc/src/string/memory_utils/op_builtin.h index 16c9f519c37e3..cfa58e43d7455 100644 --- a/libc/src/string/memory_utils/op_builtin.h +++ b/libc/src/string/memory_utils/op_builtin.h @@ -15,7 +15,6 @@ #ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_BUILTIN_H -#include "src/__support/CPP/type_traits.h" #include "src/string/memory_utils/utils.h" namespace LIBC_NAMESPACE::builtin { @@ -76,8 +75,7 @@ template struct Memset { #ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE __builtin_memset_inline(dst, value, Size); #else - static_assert(cpp::always_false, - "Missing __builtin_memset_inline"); + deferred_static_assert("Missing __builtin_memset_inline"); (void)dst; (void)value; #endif @@ -109,23 +107,22 @@ template struct Bcmp { using ME = Bcmp; static constexpr size_t SIZE = Size; LIBC_INLINE static BcmpReturnType block(CPtr, CPtr) { - static_assert(cpp::always_false, - "Missing __builtin_memcmp_inline"); + deferred_static_assert("Missing __builtin_memcmp_inline"); return BcmpReturnType::ZERO(); } LIBC_INLINE static BcmpReturnType tail(CPtr, CPtr, size_t) { - static_assert(cpp::always_false, "Not implemented"); + deferred_static_assert("Not implemented"); return BcmpReturnType::ZERO(); } LIBC_INLINE static BcmpReturnType head_tail(CPtr, CPtr, size_t) { - static_assert(cpp::always_false, "Not implemented"); + deferred_static_assert("Not implemented"); return BcmpReturnType::ZERO(); } LIBC_INLINE static BcmpReturnType loop_and_tail(CPtr, CPtr, size_t) { - static_assert(cpp::always_false, "Not implemented"); + deferred_static_assert("Not implemented"); return BcmpReturnType::ZERO(); } }; @@ -136,23 +133,22 @@ template struct Memcmp { using ME = Memcmp; static constexpr size_t SIZE = Size; LIBC_INLINE static MemcmpReturnType block(CPtr, CPtr) { - static_assert(cpp::always_false, - "Missing __builtin_memcmp_inline"); + deferred_static_assert("Missing __builtin_memcmp_inline"); return MemcmpReturnType::ZERO(); } LIBC_INLINE static MemcmpReturnType tail(CPtr, CPtr, size_t) { - static_assert(cpp::always_false, "Not implemented"); + deferred_static_assert("Not implemented"); return MemcmpReturnType::ZERO(); } LIBC_INLINE static MemcmpReturnType head_tail(CPtr, CPtr, size_t) { - static_assert(cpp::always_false, "Not implemented"); + deferred_static_assert("Not implemented"); return MemcmpReturnType::ZERO(); } LIBC_INLINE static MemcmpReturnType loop_and_tail(CPtr, CPtr, size_t) { - static_assert(cpp::always_false, "Not implemented"); + deferred_static_assert("Not implemented"); return MemcmpReturnType::ZERO(); } }; diff --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h index 5cd716e033d6a..9c293185a2e9f 100644 --- a/libc/src/string/memory_utils/utils.h +++ b/libc/src/string/memory_utils/utils.h @@ -22,12 +22,45 @@ namespace LIBC_NAMESPACE { +// Allows compile time error reporting in `if constexpr` branches. +template +LIBC_INLINE void deferred_static_assert(const char *msg) { + static_assert(flag, "compilation error"); + (void)msg; +} + +// Return whether `value` is zero or a power of two. +LIBC_INLINE constexpr bool is_power2_or_zero(size_t value) { + return (value & (value - 1U)) == 0; +} + +// Return whether `value` is a power of two. +LIBC_INLINE constexpr bool is_power2(size_t value) { + return value && is_power2_or_zero(value); +} + +// Compile time version of log2 that handles 0. +LIBC_INLINE constexpr size_t log2s(size_t value) { + return (value == 0 || value == 1) ? 0 : 1 + log2s(value / 2); +} + +// Returns the first power of two preceding value or value if it is already a +// power of two (or 0 when value is 0). +LIBC_INLINE constexpr size_t le_power2(size_t value) { + return value == 0 ? value : 1ULL << log2s(value); +} + +// Returns the first power of two following value or value if it is already a +// power of two (or 0 when value is 0). +LIBC_INLINE constexpr size_t ge_power2(size_t value) { + return is_power2_or_zero(value) ? value : 1ULL << (log2s(value) + 1); +} + // Returns the number of bytes to substract from ptr to get to the previous // multiple of alignment. If ptr is already aligned returns 0. template LIBC_INLINE uintptr_t distance_to_align_down(const void *ptr) { - static_assert(cpp::has_single_bit(alignment), - "alignment must be a power of 2"); + static_assert(is_power2(alignment), "alignment must be a power of 2"); return reinterpret_cast(ptr) & (alignment - 1U); } @@ -35,8 +68,7 @@ LIBC_INLINE uintptr_t distance_to_align_down(const void *ptr) { // alignment. If ptr is already aligned returns 0. template LIBC_INLINE uintptr_t distance_to_align_up(const void *ptr) { - static_assert(cpp::has_single_bit(alignment), - "alignment must be a power of 2"); + static_assert(is_power2(alignment), "alignment must be a power of 2"); // The logic is not straightforward and involves unsigned modulo arithmetic // but the generated code is as fast as it can be. return -reinterpret_cast(ptr) & (alignment - 1U); @@ -233,7 +265,7 @@ LIBC_INLINE ValueType load_aligned(CPtr src) { else if constexpr (Endian::IS_BIG) return (value << shift) | next; else - static_assert(cpp::always_false, "Invalid endianness"); + deferred_static_assert("Invalid endianness"); } else { return value; } @@ -270,7 +302,7 @@ LIBC_INLINE void store_aligned(ValueType value, Ptr dst) { if constexpr (sizeof...(TS) > 0) store_aligned(value >> shift, dst); } else { - static_assert(cpp::always_false, "Invalid endianness"); + deferred_static_assert("Invalid endianness"); } } @@ -328,8 +360,7 @@ LIBC_INLINE void align_to_next_boundary(T1 *__restrict &p1, T2 *__restrict &p2, else if constexpr (AlignOn == Arg::P2) align_p1_to_next_boundary(p2, p1, count); // swapping p1 and p2. else - static_assert(cpp::always_false, - "AlignOn must be either Arg::P1 or Arg::P2"); + deferred_static_assert("AlignOn must be either Arg::P1 or Arg::P2"); } template struct AlignHelper { diff --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt index 740209bc83d75..2b9fa93bb548e 100644 --- a/libc/test/src/__support/CMakeLists.txt +++ b/libc/test/src/__support/CMakeLists.txt @@ -23,6 +23,18 @@ add_libc_test( libc.src.__support.common ) + +add_libc_test( + bit_test + SUITE + libc-support-tests + SRCS + bit_test.cpp + DEPENDS + libc.src.__support.bit +) + + add_libc_test( math_extras_test SUITE @@ -33,6 +45,7 @@ add_libc_test( libc.src.__support.math_extras ) + add_libc_test( high_precision_decimal_test SUITE diff --git a/libc/test/src/__support/HashTable/table_test.cpp b/libc/test/src/__support/HashTable/table_test.cpp index 715bd6588d237..f0aa82f2d5c76 100644 --- a/libc/test/src/__support/HashTable/table_test.cpp +++ b/libc/test/src/__support/HashTable/table_test.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/CPP/bit.h" // bit_ceil #include "src/__support/HashTable/randomness.h" #include "src/__support/HashTable/table.h" #include "test/UnitTest/Test.h" @@ -38,7 +37,7 @@ TEST(LlvmLibcTableTest, Insertion) { for (size_t k = 0; k < 256; ++k) { keys[k].value = LIBC_NAMESPACE::Endian::to_little_endian(k); } - constexpr size_t CAP = cpp::bit_ceil((sizeof(Group) + 1) * 8 / 7) / 8 * 7; + constexpr size_t CAP = next_power_of_two((sizeof(Group) + 1) * 8 / 7) / 8 * 7; static_assert(CAP + 1 < 256, "CAP is too large for this test."); HashTable *table = HashTable::allocate(sizeof(Group) + 1, randomness::next_random_seed()); diff --git a/libc/test/src/__support/bit_test.cpp b/libc/test/src/__support/bit_test.cpp new file mode 100644 index 0000000000000..e585735394e2c --- /dev/null +++ b/libc/test/src/__support/bit_test.cpp @@ -0,0 +1,67 @@ +//===-- Unittests for BlockStore ------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/bit.h" +#include "test/UnitTest/Test.h" + +namespace LIBC_NAMESPACE { + +TEST(LlvmLibcBlockBitTest, TODO) { + // TODO Implement me. +} + +TEST(LlvmLibcBlockBitTest, OffsetTo) { + ASSERT_EQ(offset_to(0, 512), 0); + ASSERT_EQ(offset_to(1, 512), 511); + ASSERT_EQ(offset_to(2, 512), 510); + ASSERT_EQ(offset_to(13, 1), 0); + ASSERT_EQ(offset_to(13, 4), 3); + for (unsigned int i = 0; i < 31; ++i) { + ASSERT_EQ((offset_to(i, 1u << i) + i) % (1u << i), 0u); + } +} + +TEST(LlvmLibcBlockBitTest, RotateLeft) { + { + unsigned current = 1; + for (unsigned i = 0; i < 8 * sizeof(unsigned); ++i) { + ASSERT_EQ(1u << i, current); + ASSERT_EQ(current, rotate_left(1u, i)); + current = rotate_left(current, 1u); + } + ASSERT_EQ(current, 1u); + } + { + int current = 1; + for (int i = 0; i < 8 * static_cast(sizeof(int)); ++i) { + ASSERT_EQ(1 << i, current); + ASSERT_EQ(current, rotate_left(1, i)); + current = rotate_left(current, 1); + } + ASSERT_EQ(current, 1); + } +} + +TEST(LlvmLibcBlockBitTest, NextPowerOfTwo) { + ASSERT_EQ(1u, next_power_of_two(0u)); + for (unsigned int i = 0; i < 31; ++i) { + ASSERT_EQ(1u << (i + 1), next_power_of_two((1u << i) + 1)); + ASSERT_EQ(1u << i, next_power_of_two(1u << i)); + } +} + +TEST(LlvmLibcBlockBitTest, IsPowerOfTwo) { + ASSERT_FALSE(is_power_of_two(0u)); + ASSERT_TRUE(is_power_of_two(1u)); + for (unsigned int i = 1; i < 31; ++i) { + ASSERT_TRUE(is_power_of_two(1u << i)); + ASSERT_FALSE(is_power_of_two((1u << i) + 1)); + } +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/test/src/__support/memory_size_test.cpp b/libc/test/src/__support/memory_size_test.cpp index 3cfddeb499d48..98b6a613e62fb 100644 --- a/libc/test/src/__support/memory_size_test.cpp +++ b/libc/test/src/__support/memory_size_test.cpp @@ -81,16 +81,5 @@ TEST(LlvmLibcMemSizeTest, AlignUp) { auto max = SafeMemSize{SAFE_MEM_SIZE_TEST_LIMIT}; ASSERT_FALSE(max.align_up(8).valid()); } - -TEST(LlvmLibcBlockBitTest, OffsetTo) { - ASSERT_EQ(SafeMemSize::offset_to(0, 512), 0UL); - ASSERT_EQ(SafeMemSize::offset_to(1, 512), 511UL); - ASSERT_EQ(SafeMemSize::offset_to(2, 512), 510UL); - ASSERT_EQ(SafeMemSize::offset_to(13, 1), 0UL); - ASSERT_EQ(SafeMemSize::offset_to(13, 4), 3UL); - for (unsigned int i = 0; i < 31; ++i) { - ASSERT_EQ((SafeMemSize::offset_to(i, 1u << i) + i) % (1u << i), 0UL); - } -} } // namespace internal } // namespace LIBC_NAMESPACE diff --git a/libc/test/src/search/hsearch_test.cpp b/libc/test/src/search/hsearch_test.cpp index d6fdeec5714a4..bc9dea748758a 100644 --- a/libc/test/src/search/hsearch_test.cpp +++ b/libc/test/src/search/hsearch_test.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/CPP/bit.h" // bit_ceil #include "src/__support/HashTable/table.h" +#include "src/__support/bit.h" #include "src/search/hcreate.h" #include "src/search/hcreate_r.h" #include "src/search/hdestroy.h" @@ -48,7 +48,7 @@ char search_data2[] = constexpr size_t GROUP_SIZE = sizeof(LIBC_NAMESPACE::internal::Group); constexpr size_t CAP = - LIBC_NAMESPACE::cpp::bit_ceil((GROUP_SIZE + 1) * 8 / 7) / 8 * 7; + LIBC_NAMESPACE::next_power_of_two((GROUP_SIZE + 1) * 8 / 7) / 8 * 7; static_assert(CAP < sizeof(search_data), "CAP too large"); TEST(LlvmLibcHSearchTest, InsertTooMany) { diff --git a/libc/test/src/string/memory_utils/utils_test.cpp b/libc/test/src/string/memory_utils/utils_test.cpp index 5ed35b08cdffd..8e9052de56f1b 100644 --- a/libc/test/src/string/memory_utils/utils_test.cpp +++ b/libc/test/src/string/memory_utils/utils_test.cpp @@ -12,6 +12,66 @@ namespace LIBC_NAMESPACE { +TEST(LlvmLibcUtilsTest, IsPowerOfTwoOrZero) { + static const cpp::array kExpectedValues{ + 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 0-15 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48-63 + 1 // 64 + }; + for (size_t i = 0; i < kExpectedValues.size(); ++i) + EXPECT_EQ(is_power2_or_zero(i), kExpectedValues[i]); +} + +TEST(LlvmLibcUtilsTest, IsPowerOfTwo) { + static const cpp::array kExpectedValues{ + 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 0-15 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48-63 + 1 // 64 + }; + for (size_t i = 0; i < kExpectedValues.size(); ++i) + EXPECT_EQ(is_power2(i), kExpectedValues[i]); +} + +TEST(LlvmLibcUtilsTest, Log2) { + static const cpp::array kExpectedValues{ + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 0-15 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 16-31 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 32-47 + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 48-63 + 6 // 64 + }; + for (size_t i = 0; i < kExpectedValues.size(); ++i) + EXPECT_EQ(log2s(i), kExpectedValues[i]); +} + +TEST(LlvmLibcUtilsTest, LEPowerOf2) { + static const cpp::array kExpectedValues{ + 0, 1, 2, 2, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, // 0-15 + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, // 16-31 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 32-47 + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 48-63 + 64 // 64 + }; + for (size_t i = 0; i < kExpectedValues.size(); ++i) + EXPECT_EQ(le_power2(i), kExpectedValues[i]); +} + +TEST(LlvmLibcUtilsTest, GEPowerOf2) { + static const cpp::array kExpectedValues{ + 0, 1, 2, 4, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, // 0-15 + 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 16-31 + 32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, // 32-47 + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, // 48-63 + 64, 128 // 64-65 + }; + for (size_t i = 0; i < kExpectedValues.size(); ++i) + EXPECT_EQ(ge_power2(i), kExpectedValues[i]); +} + using UINT = uintptr_t; // Converts an offset into a pointer. diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 24f03715a6bb8..0b6e725aa4d31 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -439,6 +439,7 @@ libc_support_library( name = "__support_integer_utils", hdrs = ["src/__support/integer_utils.h"], deps = [ + ":__support_bit", ":__support_common", ":__support_cpp_type_traits", ":__support_math_extras", @@ -450,6 +451,7 @@ libc_support_library( name = "__support_uint", hdrs = ["src/__support/UInt.h"], deps = [ + ":__support_bit", ":__support_cpp_array", ":__support_cpp_limits", ":__support_cpp_optional", @@ -535,8 +537,8 @@ libc_support_library( "src/__support/str_to_float.h", ], deps = [ + ":__support_bit", ":__support_common", - ":__support_cpp_bit", ":__support_cpp_limits", ":__support_cpp_optional", ":__support_ctype_utils", @@ -585,6 +587,15 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_bit", + hdrs = ["src/__support/bit.h"], + deps = [ + ":__support_cpp_type_traits", + ":__support_macros_attributes", + ], +) + libc_support_library( name = "__support_math_extras", hdrs = ["src/__support/math_extras.h"], @@ -599,8 +610,8 @@ libc_support_library( name = "__support_fputil_generic_fmod", hdrs = ["src/__support/FPUtil/generic/FMod.h"], deps = [ + ":__support_bit", ":__support_common", - ":__support_cpp_bit", ":__support_cpp_limits", ":__support_cpp_type_traits", ":__support_fputil_fenv_impl", @@ -672,6 +683,7 @@ libc_support_library( hdrs = ["src/__support/FPUtil/FPBits.h"], textual_hdrs = ["src/__support/FPUtil/x86_64/LongDoubleBits.h"], deps = [ + ":__support_bit", ":__support_common", ":__support_cpp_bit", ":__support_cpp_type_traits", @@ -699,6 +711,7 @@ libc_support_library( name = "__support_fputil_hypot", hdrs = ["src/__support/FPUtil/Hypot.h"], deps = [ + ":__support_bit", ":__support_common", ":__support_cpp_bit", ":__support_cpp_type_traits", @@ -769,6 +782,7 @@ libc_support_library( name = "__support_fputil_sqrt", hdrs = sqrt_hdrs, deps = [ + ":__support_bit", ":__support_common", ":__support_cpp_bit", ":__support_cpp_type_traits", @@ -796,6 +810,7 @@ libc_support_library( # doesn't support FMA, so they can't be compiled on their own. textual_hdrs = fma_platform_hdrs, deps = [ + ":__support_bit", ":__support_cpp_bit", ":__support_cpp_type_traits", ":__support_fputil_fenv_impl", diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel index a973e6541da01..23071c292b827 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel @@ -10,6 +10,12 @@ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) +libc_test( + name = "bit_test", + srcs = ["bit_test.cpp"], + deps = ["//libc:__support_bit"], +) + libc_test( name = "math_extras_test", srcs = ["math_extras_test.cpp"], diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/libc_math_test_rules.bzl b/utils/bazel/llvm-project-overlay/libc/test/src/math/libc_math_test_rules.bzl index 1dffafdd53949..2843270d414a7 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/math/libc_math_test_rules.bzl +++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/libc_math_test_rules.bzl @@ -25,6 +25,7 @@ def math_test(name, hdrs = [], deps = [], **kwargs): srcs = [test_name + ".cpp"] + hdrs, libc_function_deps = ["//libc:func_name".replace("func_name", name)], deps = [ + "//libc:__support_bit", "//libc:__support_fputil_basic_operations", "//libc:__support_fputil_fenv_impl", "//libc:__support_fputil_float_properties",