[llvm-branch-commits] [libc] 4fdb933 - Revert "[libc][NFC] Remove __support/bit.h and use __support/CPP/bit.h instead (#73939)"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Dec 5 02:24:41 PST 2023
Author: Guillaume Chatelet
Date: 2023-12-05T11:24:38+01:00
New Revision: 4fdb9338fbe534521d9e79035561d9ca9db399c6
URL: https://github.com/llvm/llvm-project/commit/4fdb9338fbe534521d9e79035561d9ca9db399c6
DIFF: https://github.com/llvm/llvm-project/commit/4fdb9338fbe534521d9e79035561d9ca9db399c6.diff
LOG: Revert "[libc][NFC] Remove __support/bit.h and use __support/CPP/bit.h instead (#73939)"
This reverts commit b14094885077fb10ae688a4cae85f7cfee795fb3.
Added:
libc/src/__support/bit.h
libc/test/src/__support/bit_test.cpp
Modified:
libc/src/__support/CMakeLists.txt
libc/src/__support/FPUtil/CMakeLists.txt
libc/src/__support/FPUtil/FPBits.h
libc/src/__support/FPUtil/Hypot.h
libc/src/__support/FPUtil/generic/CMakeLists.txt
libc/src/__support/FPUtil/generic/FMA.h
libc/src/__support/FPUtil/generic/FMod.h
libc/src/__support/FPUtil/generic/sqrt.h
libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
libc/src/__support/HashTable/CMakeLists.txt
libc/src/__support/HashTable/bitmask.h
libc/src/__support/HashTable/table.h
libc/src/__support/UInt.h
libc/src/__support/hash.h
libc/src/__support/integer_utils.h
libc/src/__support/memory_size.h
libc/src/__support/str_to_float.h
libc/src/math/generic/CMakeLists.txt
libc/src/math/generic/powf.cpp
libc/src/string/memory_utils/op_builtin.h
libc/src/string/memory_utils/utils.h
libc/test/src/__support/CMakeLists.txt
libc/test/src/__support/HashTable/table_test.cpp
libc/test/src/__support/memory_size_test.cpp
libc/test/src/search/hsearch_test.cpp
libc/test/src/string/memory_utils/utils_test.cpp
utils/bazel/llvm-project-overlay/libc/BUILD.bazel
utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel
utils/bazel/llvm-project-overlay/libc/test/src/math/libc_math_test_rules.bzl
Removed:
################################################################################
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 <typename T> struct FPBits {
LIBC_INLINE static constexpr FPBits<T> make_value(UIntType number, int ep) {
FPBits<T> 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 <typename T>
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 <typename T> struct DoubleLength;
-template <> struct DoubleLength<uint16_t> {
- using Type = uint32_t;
-};
+template <> struct DoubleLength<uint16_t> { using Type = uint32_t; };
-template <> struct DoubleLength<uint32_t> {
- using Type = uint64_t;
-};
+template <> struct DoubleLength<uint32_t> { using Type = uint64_t; };
template <> struct DoubleLength<uint64_t> {
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>(double x, double y, double z) {
// Normalize the result.
if (prod_mant != 0) {
uint64_t prod_hi = static_cast<uint64_t>(prod_mant >> 64);
- int lead_zeros =
- prod_hi ? cpp::countl_zero(prod_hi)
- : 64 + cpp::countl_zero(static_cast<uint64_t>(prod_mant));
+ int lead_zeros = prod_hi
+ ? unsafe_clz(prod_hi)
+ : 64 + unsafe_clz(static_cast<uint64_t>(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<long double> {
template <typename T>
LIBC_INLINE void normalize(int &exponent,
typename FPBits<T>::UIntType &mantissa) {
- const int shift = cpp::countl_zero(mantissa) -
+ const int shift = unsafe_clz(mantissa) -
(8 * sizeof(mantissa) - 1 - MantissaWidth<T>::VALUE);
exponent -= shift;
mantissa <<= shift;
@@ -51,9 +52,9 @@ LIBC_INLINE void normalize<long double>(int &exponent, uint64_t &mantissa) {
template <>
LIBC_INLINE void normalize<long double>(int &exponent, UInt128 &mantissa) {
const uint64_t hi_bits = static_cast<uint64_t>(mantissa >> 64);
- const int shift =
- hi_bits ? (cpp::countl_zero(hi_bits) - 15)
- : (cpp::countl_zero(static_cast<uint64_t>(mantissa)) + 49);
+ const int shift = hi_bits
+ ? (unsafe_clz(hi_bits) - 15)
+ : (unsafe_clz(static_cast<uint64_t>(mantissa)) + 49);
exponent -= shift;
mantissa <<= shift;
}
@@ -136,7 +137,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
// We compute one more iteration in order to round correctly.
bool lsb = static_cast<bool>(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<unsigned int>(
- cpp::countl_zero(static_cast<uint64_t>(mantissa)) -
+ unsafe_clz(static_cast<uint64_t>(mantissa)) -
(8 * sizeof(uint64_t) - 1 - MantissaWidth<long double>::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<bool>(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 <stddef.h> // size_t
#include <stdint.h> // uint8_t, uint64_t
@@ -45,7 +45,7 @@ template <typename T, T WORD_MASK, size_t WORD_STRIDE> 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<T>(word) / WORD_STRIDE;
+ return unsafe_ctz<T>(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 <size_t Bits, bool Signed> 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 <typename T> LIBC_INLINE int constexpr correct_zero(T val, int bits) {
+ if (val == T(0))
+ return sizeof(T(0)) * 8;
+ else
+ return bits;
+}
+
+template <typename T> LIBC_INLINE constexpr int clz(T val);
+template <> LIBC_INLINE int clz<unsigned char>(unsigned char val) {
+ return __builtin_clz(static_cast<unsigned int>(val)) -
+ 8 * static_cast<int>(sizeof(unsigned int) - sizeof(unsigned char));
+}
+template <> LIBC_INLINE int clz<unsigned short>(unsigned short val) {
+ return __builtin_clz(static_cast<unsigned int>(val)) -
+ 8 * static_cast<int>(sizeof(unsigned int) - sizeof(unsigned short));
+}
+template <> LIBC_INLINE int clz<unsigned int>(unsigned int val) {
+ return __builtin_clz(val);
+}
+template <>
+LIBC_INLINE constexpr int clz<unsigned long int>(unsigned long int val) {
+ return __builtin_clzl(val);
+}
+template <>
+LIBC_INLINE constexpr int
+clz<unsigned long long int>(unsigned long long int val) {
+ return __builtin_clzll(val);
+}
+
+template <typename T> LIBC_INLINE constexpr int ctz(T val);
+template <> LIBC_INLINE int ctz<unsigned char>(unsigned char val) {
+ return __builtin_ctz(static_cast<unsigned int>(val));
+}
+template <> LIBC_INLINE int ctz<unsigned short>(unsigned short val) {
+ return __builtin_ctz(static_cast<unsigned int>(val));
+}
+template <> LIBC_INLINE int ctz<unsigned int>(unsigned int val) {
+ return __builtin_ctz(val);
+}
+template <>
+LIBC_INLINE constexpr int ctz<unsigned long int>(unsigned long int val) {
+ return __builtin_ctzl(val);
+}
+template <>
+LIBC_INLINE constexpr int
+ctz<unsigned long long int>(unsigned long long int val) {
+ return __builtin_ctzll(val);
+}
+} // namespace __internal
+
+template <typename T> LIBC_INLINE constexpr int safe_ctz(T val) {
+ return __internal::correct_zero(val, __internal::ctz(val));
+}
+
+template <typename T> LIBC_INLINE constexpr int unsafe_ctz(T val) {
+ return __internal::ctz(val);
+}
+
+template <typename T> LIBC_INLINE constexpr int safe_clz(T val) {
+ return __internal::correct_zero(val, __internal::clz(val));
+}
+
+template <typename T> LIBC_INLINE constexpr int unsafe_clz(T val) {
+ return __internal::clz(val);
+}
+
+template <typename T> LIBC_INLINE constexpr T next_power_of_two(T val) {
+ if (val == 0)
+ return 1;
+ T idx = safe_clz(val - 1);
+ return static_cast<T>(1) << ((8ull * sizeof(T)) - idx);
+}
+
+template <typename T> LIBC_INLINE constexpr bool is_power_of_two(T val) {
+ return val != 0 && (val & (val - 1)) == 0;
+}
+
+template <typename T> LIBC_INLINE constexpr T offset_to(T val, T align) {
+ return (-val) & (align - 1);
+}
+
+template <typename T> 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<T>;
+ U v = static_cast<U>(val);
+ U a = static_cast<U>(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 <stdint.h> // 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<size_t>(cpp::numeric_limits<type>::max());
-
LIBC_INLINE explicit SafeMemSize(size_t value)
: value(value <= MAX_MEM_SIZE ? static_cast<type>(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<size_t>(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<size_t>(value, alignment);
if (LIBC_UNLIKELY(offset > static_cast<type>(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 <class T> LIBC_INLINE uint32_t leading_zeroes(T inputNumber) {
template <>
LIBC_INLINE uint32_t leading_zeroes<uint32_t>(uint32_t inputNumber) {
- return cpp::countl_zero(inputNumber);
+ return safe_clz(inputNumber);
}
template <>
LIBC_INLINE uint32_t leading_zeroes<uint64_t>(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<uint32_t>(x);
int x_e = static_cast<int>((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<int>(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<uint32_t>(x);
int x_e = static_cast<int>((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<int>(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 <size_t Size> struct Memset {
#ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE
__builtin_memset_inline(dst, value, Size);
#else
- static_assert(cpp::always_false<decltype(Size)>,
- "Missing __builtin_memset_inline");
+ deferred_static_assert("Missing __builtin_memset_inline");
(void)dst;
(void)value;
#endif
@@ -109,23 +107,22 @@ template <size_t Size> struct Bcmp {
using ME = Bcmp;
static constexpr size_t SIZE = Size;
LIBC_INLINE static BcmpReturnType block(CPtr, CPtr) {
- static_assert(cpp::always_false<decltype(Size)>,
- "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<decltype(Size)>, "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<decltype(Size)>, "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<decltype(Size)>, "Not implemented");
+ deferred_static_assert("Not implemented");
return BcmpReturnType::ZERO();
}
};
@@ -136,23 +133,22 @@ template <size_t Size> struct Memcmp {
using ME = Memcmp;
static constexpr size_t SIZE = Size;
LIBC_INLINE static MemcmpReturnType block(CPtr, CPtr) {
- static_assert(cpp::always_false<decltype(Size)>,
- "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<decltype(Size)>, "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<decltype(Size)>, "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<decltype(Size)>, "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 <bool flag = false>
+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 <size_t alignment>
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<uintptr_t>(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 <size_t alignment>
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<uintptr_t>(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<T>, "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<ValueType, TS...>(value >> shift, dst);
} else {
- static_assert(cpp::always_false<T>, "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<SIZE>(p2, p1, count); // swapping p1 and p2.
else
- static_assert(cpp::always_false<T1>,
- "AlignOn must be either Arg::P1 or Arg::P2");
+ deferred_static_assert("AlignOn must be either Arg::P1 or Arg::P2");
}
template <size_t SIZE> 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<int>(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<bool, 65> 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<bool, 65> 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<size_t, 65> 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<size_t, 65> 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<size_t, 66> 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",
More information about the llvm-branch-commits
mailing list