[libc-commits] [clang] [libc] [clang-tools-extra] [flang] [compiler-rt] [llvm] [libc][NFC] Remove __support/bit.h and use __support/CPP/bit.h instead (PR #73939)

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Tue Dec 5 02:11:55 PST 2023


https://github.com/gchatelet updated https://github.com/llvm/llvm-project/pull/73939

>From 651cdece9397cf643cfafef7c65f4b8f44148d29 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Thu, 30 Nov 2023 13:53:28 +0000
Subject: [PATCH 1/3] [libc][NFC] Remove __support/bit.h and use
 __support/CPP/bit.h instead

---
 libc/src/__support/CMakeLists.txt             |   8 +-
 libc/src/__support/FPUtil/CMakeLists.txt      |   2 -
 libc/src/__support/FPUtil/FPBits.h            |   3 +-
 libc/src/__support/FPUtil/Hypot.h             |  11 +-
 .../__support/FPUtil/generic/CMakeLists.txt   |   5 +-
 libc/src/__support/FPUtil/generic/FMA.h       |   8 +-
 libc/src/__support/FPUtil/generic/FMod.h      |   8 +-
 libc/src/__support/FPUtil/generic/sqrt.h      |  13 +-
 .../FPUtil/generic/sqrt_80_bit_long_double.h  |   6 +-
 libc/src/__support/HashTable/CMakeLists.txt   |  12 +-
 libc/src/__support/HashTable/bitmask.h        |   4 +-
 libc/src/__support/HashTable/table.h          |   7 +-
 libc/src/__support/UInt.h                     |   4 +-
 libc/src/__support/bit.h                      | 117 ------------------
 libc/src/__support/hash.h                     |   8 +-
 libc/src/__support/integer_utils.h            |   1 -
 libc/src/__support/memory_size.h              |  17 ++-
 libc/src/__support/str_to_float.h             |   5 +-
 libc/src/math/generic/CMakeLists.txt          |   1 -
 libc/src/math/generic/powf.cpp                |   5 +-
 libc/src/string/memory_utils/op_builtin.h     |  22 ++--
 libc/src/string/memory_utils/utils.h          |  47 ++-----
 libc/test/src/__support/CMakeLists.txt        |  13 --
 .../src/__support/HashTable/table_test.cpp    |   3 +-
 libc/test/src/__support/bit_test.cpp          |  67 ----------
 libc/test/src/__support/memory_size_test.cpp  |  11 ++
 libc/test/src/search/hsearch_test.cpp         |   4 +-
 .../src/string/memory_utils/utils_test.cpp    |  60 ---------
 .../llvm-project-overlay/libc/BUILD.bazel     |  19 +--
 .../libc/test/src/__support/BUILD.bazel       |   6 -
 .../test/src/math/libc_math_test_rules.bzl    |   1 -
 31 files changed, 105 insertions(+), 393 deletions(-)
 delete mode 100644 libc/src/__support/bit.h
 delete mode 100644 libc/test/src/__support/bit_test.cpp

diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index a76b22960f5a5..03305a2f06aae 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -140,13 +140,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
 )
 
@@ -194,9 +194,9 @@ add_header_library(
   HDRS
     integer_utils.h
   DEPENDS
-    .bit
     .number_pair
     libc.src.__support.common
+    libc.src.__support.CPP.bit
     libc.src.__support.CPP.type_traits
 )
 
@@ -205,11 +205,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
 )
@@ -236,8 +236,8 @@ add_header_library(
   HDRS
     hash.h
   DEPENDS
-    .bit
     .uint128
+    libc.src.__support.CPP.bit
     libc.src.__support.macros.attributes
 )
 
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 58a182eaa797b..3d6d712fc2058 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -41,7 +41,6 @@ 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(
@@ -146,7 +145,6 @@ 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 76a9fc6d772bf..dba0c7e0745c2 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -11,7 +11,6 @@
 
 #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
 
@@ -222,7 +221,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 = unsafe_clz(number) - FloatProp::EXPONENT_WIDTH;
+    int lz = cpp::countl_zero(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 db2a62fbdf2a1..8a6eb4b920acd 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -16,7 +16,6 @@
 #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 {
@@ -28,7 +27,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 - unsafe_clz(mant);
+    shift_length = (sizeof(mant) * 8) - 1 - cpp::countl_zero(mant);
   }
   return T(1) << shift_length;
 }
@@ -37,9 +36,13 @@ 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 c799d502b47d6..b17f325210473 100644
--- a/libc/src/__support/FPUtil/generic/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt
@@ -11,7 +11,6 @@ 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
 )
 
@@ -21,13 +20,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
 )
 
@@ -37,12 +36,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 5a856d1447330..4a825f2f4942c 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
-                         ? unsafe_clz(prod_hi)
-                         : 64 + unsafe_clz(static_cast<uint64_t>(prod_mant));
+    int lead_zeros =
+        prod_hi ? cpp::countl_zero(prod_hi)
+                : 64 + cpp::countl_zero(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 6f934cd4a87bd..0e71b039d5c06 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 = unsafe_clz(m_y);
+      lead_zeros_m_y = cpp::countl_zero(m_y);
     }
 
     // Assume hy != 0
-    int tail_zeros_m_y = unsafe_ctz(m_y);
+    int tail_zeros_m_y = cpp::countr_zero(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 63e8329b06607..6cc80a1a337d0 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -10,13 +10,12 @@
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GENERIC_SQRT_H
 
 #include "sqrt_80_bit_long_double.h"
-#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/bit.h" // countl_zero
 #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 {
@@ -37,7 +36,7 @@ template <> struct SpecialLongDouble<long double> {
 template <typename T>
 LIBC_INLINE void normalize(int &exponent,
                            typename FPBits<T>::UIntType &mantissa) {
-  const int shift = unsafe_clz(mantissa) -
+  const int shift = cpp::countl_zero(mantissa) -
                     (8 * sizeof(mantissa) - 1 - MantissaWidth<T>::VALUE);
   exponent -= shift;
   mantissa <<= shift;
@@ -52,9 +51,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
-                        ? (unsafe_clz(hi_bits) - 15)
-                        : (unsafe_clz(static_cast<uint64_t>(mantissa)) + 49);
+  const int shift =
+      hi_bits ? (cpp::countl_zero(hi_bits) - 15)
+              : (cpp::countl_zero(static_cast<uint64_t>(mantissa)) + 49);
   exponent -= shift;
   mantissa <<= shift;
 }
@@ -137,7 +136,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 713c338905109..34c6f46b5050d 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>(
-      unsafe_clz(static_cast<uint64_t>(mantissa)) -
+      cpp::countl_zero(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 e9b4aa31290a1..920ba194badd9 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.bit
+    libc.src.__support.CPP.bit
     libc.src.__support.macros.properties.cpu_features
 )
 
@@ -25,17 +25,17 @@ add_header_library(
     table.h
   DEPENDS
     .bitmask
-    libc.src.__support.memory_size
-    libc.src.__support.bit
-    libc.src.__support.CPP.type_traits
+    libc.include.llvm-libc-types.ENTRY
+    libc.src.__support.CPP.bit
     libc.src.__support.CPP.new
+    libc.src.__support.CPP.type_traits
+    libc.src.__support.hash
     libc.src.__support.macros.attributes
     libc.src.__support.macros.optimization
-    libc.src.__support.hash
+    libc.src.__support.memory_size
     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 8247161c449bd..ee4682ca70f7e 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/bit.h"
+#include "src/__support/CPP/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 unsafe_ctz<T>(word) / WORD_STRIDE;
+    return cpp::countr_zero<T>(word) / WORD_STRIDE;
   }
 };
 
diff --git a/libc/src/__support/HashTable/table.h b/libc/src/__support/HashTable/table.h
index ec0ec78869ad5..305fe59792d5a 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 next_power_of_two(cap * 8 / 7);
+  return cpp::bit_ceil(cap * 8 / 7);
 }
 
 // The heap memory layout for N buckets HashTable is as follows:
@@ -98,7 +98,8 @@ struct HashTable {
 
   LIBC_INLINE size_t offset_from_entries() const {
     size_t entries_size = num_of_entries() * sizeof(ENTRY);
-    return entries_size + offset_to(entries_size, table_alignment());
+    return entries_size +
+           SafeMemSize::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 dbedfbc4c197e..1edec0387e632 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
@@ -556,7 +556,7 @@ template <size_t Bits, bool Signed> struct BigInt {
       if (val[i - 1] == 0) {
         leading_zeroes += sizeof(uint64_t) * 8;
       } else {
-        leading_zeroes += unsafe_clz(val[i - 1]);
+        leading_zeroes += countl_zero(val[i - 1]);
         break;
       }
     }
diff --git a/libc/src/__support/bit.h b/libc/src/__support/bit.h
deleted file mode 100644
index ba7fc31de1227..0000000000000
--- a/libc/src/__support/bit.h
+++ /dev/null
@@ -1,117 +0,0 @@
-//===-- 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 ad12cf79e8d2c..e44a6b36f6715 100644
--- a/libc/src/__support/hash.h
+++ b/libc/src/__support/hash.h
@@ -9,8 +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/UInt128.h"           // UInt128
-#include "src/__support/bit.h"               // rotate_left
 #include "src/__support/macros/attributes.h" // LIBC_INLINE
 #include <stdint.h>                          // For uint64_t
 
@@ -103,7 +103,7 @@ class HashState {
     uint64_t combined =
         folded_multiply(low ^ extra_keys[0], high ^ extra_keys[1]);
     buffer = (buffer + pad) ^ combined;
-    buffer = rotate_left(buffer, ROTATE);
+    buffer = cpp::rotl(buffer, ROTATE);
   }
   LIBC_INLINE static uint64_t mix(uint64_t seed) {
     HashState mixer{RANDOMNESS[0][0], RANDOMNESS[0][1], RANDOMNESS[0][2],
@@ -152,9 +152,9 @@ class HashState {
     }
   }
   LIBC_INLINE uint64_t finish() {
-    uint64_t rot = buffer & 63;
+    int rot = buffer & 63;
     uint64_t folded = folded_multiply(buffer, pad);
-    return rotate_left(folded, rot);
+    return cpp::rotl(folded, rot);
   }
 };
 
diff --git a/libc/src/__support/integer_utils.h b/libc/src/__support/integer_utils.h
index 433e99227bcfd..9adcd35d99489 100644
--- a/libc/src/__support/integer_utils.h
+++ b/libc/src/__support/integer_utils.h
@@ -12,7 +12,6 @@
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/common.h"
 
-#include "bit.h"
 #include "number_pair.h"
 
 #include <stdint.h>
diff --git a/libc/src/__support/memory_size.h b/libc/src/__support/memory_size.h
index df179a6604714..4c7d2079553e8 100644
--- a/libc/src/__support/memory_size.h
+++ b/libc/src/__support/memory_size.h
@@ -6,11 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#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 {
@@ -37,10 +38,18 @@ 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))
@@ -48,6 +57,7 @@ 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))
@@ -56,11 +66,12 @@ class SafeMemSize {
       result = -1;
     return SafeMemSize{result};
   }
+
   LIBC_INLINE SafeMemSize align_up(size_t alignment) {
-    if (!is_power_of_two(alignment) || alignment > MAX_MEM_SIZE || !valid())
+    if (!cpp::has_single_bit(alignment) || alignment > MAX_MEM_SIZE || !valid())
       return SafeMemSize{type{-1}};
 
-    type offset = LIBC_NAMESPACE::offset_to<size_t>(value, alignment);
+    type offset = offset_to(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 81ab36dbf9471..b27ca04ef04f0 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -16,7 +16,6 @@
 #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"
@@ -69,12 +68,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 safe_clz(inputNumber);
+  return cpp::countl_zero(inputNumber);
 }
 
 template <>
 LIBC_INLINE uint32_t leading_zeroes<uint64_t>(uint64_t inputNumber) {
-  return safe_clz(inputNumber);
+  return cpp::countl_zero(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 5380502210828..214d57842d93b 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -780,7 +780,6 @@ 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 2de8e76b04b5a..5f2e95b44e528 100644
--- a/libc/src/math/generic/powf.cpp
+++ b/libc/src/math/generic/powf.cpp
@@ -18,7 +18,6 @@
 #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
 
@@ -392,7 +391,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 = unsafe_ctz(x_u | FloatProp::EXPONENT_MASK);
+  int lsb = cpp::countr_zero(x_u | FloatProp::EXPONENT_MASK);
   constexpr int UNIT_EXPONENT =
       static_cast<int>(FloatProp::EXPONENT_BIAS + FloatProp::MANTISSA_WIDTH);
   return (x_e + lsb == UNIT_EXPONENT);
@@ -403,7 +402,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 = unsafe_ctz(x_u | FloatProp::EXPONENT_MASK);
+  int lsb = cpp::countr_zero(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 cfa58e43d7455..16c9f519c37e3 100644
--- a/libc/src/string/memory_utils/op_builtin.h
+++ b/libc/src/string/memory_utils/op_builtin.h
@@ -15,6 +15,7 @@
 #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 {
@@ -75,7 +76,8 @@ template <size_t Size> struct Memset {
 #ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE
     __builtin_memset_inline(dst, value, Size);
 #else
-    deferred_static_assert("Missing __builtin_memset_inline");
+    static_assert(cpp::always_false<decltype(Size)>,
+                  "Missing __builtin_memset_inline");
     (void)dst;
     (void)value;
 #endif
@@ -107,22 +109,23 @@ template <size_t Size> struct Bcmp {
   using ME = Bcmp;
   static constexpr size_t SIZE = Size;
   LIBC_INLINE static BcmpReturnType block(CPtr, CPtr) {
-    deferred_static_assert("Missing __builtin_memcmp_inline");
+    static_assert(cpp::always_false<decltype(Size)>,
+                  "Missing __builtin_memcmp_inline");
     return BcmpReturnType::ZERO();
   }
 
   LIBC_INLINE static BcmpReturnType tail(CPtr, CPtr, size_t) {
-    deferred_static_assert("Not implemented");
+    static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
     return BcmpReturnType::ZERO();
   }
 
   LIBC_INLINE static BcmpReturnType head_tail(CPtr, CPtr, size_t) {
-    deferred_static_assert("Not implemented");
+    static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
     return BcmpReturnType::ZERO();
   }
 
   LIBC_INLINE static BcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {
-    deferred_static_assert("Not implemented");
+    static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
     return BcmpReturnType::ZERO();
   }
 };
@@ -133,22 +136,23 @@ template <size_t Size> struct Memcmp {
   using ME = Memcmp;
   static constexpr size_t SIZE = Size;
   LIBC_INLINE static MemcmpReturnType block(CPtr, CPtr) {
-    deferred_static_assert("Missing __builtin_memcmp_inline");
+    static_assert(cpp::always_false<decltype(Size)>,
+                  "Missing __builtin_memcmp_inline");
     return MemcmpReturnType::ZERO();
   }
 
   LIBC_INLINE static MemcmpReturnType tail(CPtr, CPtr, size_t) {
-    deferred_static_assert("Not implemented");
+    static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
     return MemcmpReturnType::ZERO();
   }
 
   LIBC_INLINE static MemcmpReturnType head_tail(CPtr, CPtr, size_t) {
-    deferred_static_assert("Not implemented");
+    static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
     return MemcmpReturnType::ZERO();
   }
 
   LIBC_INLINE static MemcmpReturnType loop_and_tail(CPtr, CPtr, size_t) {
-    deferred_static_assert("Not implemented");
+    static_assert(cpp::always_false<decltype(Size)>, "Not implemented");
     return MemcmpReturnType::ZERO();
   }
 };
diff --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h
index f70880ee853d3..e46b6f4b6c604 100644
--- a/libc/src/string/memory_utils/utils.h
+++ b/libc/src/string/memory_utils/utils.h
@@ -22,45 +22,12 @@
 
 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(is_power2(alignment), "alignment must be a power of 2");
+  static_assert(cpp::has_single_bit(alignment),
+                "alignment must be a power of 2");
   return reinterpret_cast<uintptr_t>(ptr) & (alignment - 1U);
 }
 
@@ -68,7 +35,8 @@ 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(is_power2(alignment), "alignment must be a power of 2");
+  static_assert(cpp::has_single_bit(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);
@@ -265,7 +233,7 @@ LIBC_INLINE ValueType load_aligned(CPtr src) {
     else if constexpr (Endian::IS_BIG)
       return (value << shift) | next;
     else
-      deferred_static_assert("Invalid endianness");
+      static_assert(cpp::always_false<T>, "Invalid endianness");
   } else {
     return value;
   }
@@ -302,7 +270,7 @@ LIBC_INLINE void store_aligned(ValueType value, Ptr dst) {
     if constexpr (sizeof...(TS) > 0)
       store_aligned<ValueType, TS...>(value >> shift, dst);
   } else {
-    deferred_static_assert("Invalid endianness");
+    static_assert(cpp::always_false<T>, "Invalid endianness");
   }
 }
 
@@ -360,7 +328,8 @@ 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
-    deferred_static_assert("AlignOn must be either Arg::P1 or Arg::P2");
+    static_assert(cpp::always_false<T1>,
+                  "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 2b9fa93bb548e..740209bc83d75 100644
--- a/libc/test/src/__support/CMakeLists.txt
+++ b/libc/test/src/__support/CMakeLists.txt
@@ -23,18 +23,6 @@ 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
@@ -45,7 +33,6 @@ 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 f0aa82f2d5c76..715bd6588d237 100644
--- a/libc/test/src/__support/HashTable/table_test.cpp
+++ b/libc/test/src/__support/HashTable/table_test.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#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"
@@ -37,7 +38,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 = next_power_of_two((sizeof(Group) + 1) * 8 / 7) / 8 * 7;
+  constexpr size_t CAP = cpp::bit_ceil((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
deleted file mode 100644
index e585735394e2c..0000000000000
--- a/libc/test/src/__support/bit_test.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-//===-- 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 98b6a613e62fb..3cfddeb499d48 100644
--- a/libc/test/src/__support/memory_size_test.cpp
+++ b/libc/test/src/__support/memory_size_test.cpp
@@ -81,5 +81,16 @@ 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 bc9dea748758a..d6fdeec5714a4 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::next_power_of_two((GROUP_SIZE + 1) * 8 / 7) / 8 * 7;
+    LIBC_NAMESPACE::cpp::bit_ceil((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 8e9052de56f1b..5ed35b08cdffd 100644
--- a/libc/test/src/string/memory_utils/utils_test.cpp
+++ b/libc/test/src/string/memory_utils/utils_test.cpp
@@ -12,66 +12,6 @@
 
 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 a0a6a4366ea75..f434beb509f7f 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -439,7 +439,6 @@ libc_support_library(
     name = "__support_integer_utils",
     hdrs = ["src/__support/integer_utils.h"],
     deps = [
-        ":__support_bit",
         ":__support_common",
         ":__support_cpp_type_traits",
         ":__support_number_pair",
@@ -450,7 +449,6 @@ libc_support_library(
     name = "__support_uint",
     hdrs = ["src/__support/UInt.h"],
     deps = [
-        ":__support_bit",
         ":__support_cpp_array",
         ":__support_cpp_limits",
         ":__support_cpp_optional",
@@ -537,8 +535,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",
@@ -592,15 +590,6 @@ libc_support_library(
     hdrs = ["src/__support/named_pair.h"],
 )
 
-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"],
@@ -616,8 +605,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",
@@ -689,7 +678,6 @@ 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",
@@ -717,7 +705,6 @@ 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",
@@ -788,7 +775,6 @@ libc_support_library(
     name = "__support_fputil_sqrt",
     hdrs = sqrt_hdrs,
     deps = [
-        ":__support_bit",
         ":__support_common",
         ":__support_cpp_bit",
         ":__support_cpp_type_traits",
@@ -816,7 +802,6 @@ 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 23071c292b827..a973e6541da01 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,12 +10,6 @@ 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 2843270d414a7..1dffafdd53949 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,7 +25,6 @@ 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",

>From a198132082751ac068e37561e823c938907671a4 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Fri, 1 Dec 2023 09:26:59 +0000
Subject: [PATCH 2/3] Use numeric_limits::digit

---
 libc/src/__support/CMakeLists.txt | 1 +
 libc/src/__support/hash.h         | 6 ++++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index 03305a2f06aae..deba02b91d056 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -238,6 +238,7 @@ add_header_library(
   DEPENDS
     .uint128
     libc.src.__support.CPP.bit
+    libc.src.__support.CPP.limits
     libc.src.__support.macros.attributes
 )
 
diff --git a/libc/src/__support/hash.h b/libc/src/__support/hash.h
index e44a6b36f6715..cb3244bcd008d 100644
--- a/libc/src/__support/hash.h
+++ b/libc/src/__support/hash.h
@@ -10,6 +10,7 @@
 #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/macros/attributes.h" // LIBC_INLINE
 #include <stdint.h>                          // For uint64_t
@@ -152,8 +153,9 @@ class HashState {
     }
   }
   LIBC_INLINE uint64_t finish() {
-    int rot = buffer & 63;
-    uint64_t folded = folded_multiply(buffer, pad);
+    const uint64_t folded = folded_multiply(buffer, pad);
+    // Only keep the bottom bits of buffer that fits in an int.
+    const int rot = buffer & cpp::numeric_limits<int>::digits;
     return cpp::rotl(folded, rot);
   }
 };

>From 4defecc0e2901364f26cfc8bf75ed00a256f4537 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Tue, 5 Dec 2023 10:08:14 +0000
Subject: [PATCH 3/3] revert rot fix

---
 libc/src/__support/hash.h | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/libc/src/__support/hash.h b/libc/src/__support/hash.h
index cb3244bcd008d..6b362ba831891 100644
--- a/libc/src/__support/hash.h
+++ b/libc/src/__support/hash.h
@@ -153,9 +153,8 @@ class HashState {
     }
   }
   LIBC_INLINE uint64_t finish() {
-    const uint64_t folded = folded_multiply(buffer, pad);
-    // Only keep the bottom bits of buffer that fits in an int.
-    const int rot = buffer & cpp::numeric_limits<int>::digits;
+    int rot = buffer & 63;
+    uint64_t folded = folded_multiply(buffer, pad);
     return cpp::rotl(folded, rot);
   }
 };



More information about the libc-commits mailing list