[libcxx-commits] [libcxx] 07ad928 - [libc++] Introduce __specialized_algorithms (#167295)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Nov 25 04:46:23 PST 2025


Author: Nikolas Klauser
Date: 2025-11-25T13:46:19+01:00
New Revision: 07ad928d92eac995e8d2fc48b0aafde511e9f3a0

URL: https://github.com/llvm/llvm-project/commit/07ad928d92eac995e8d2fc48b0aafde511e9f3a0
DIFF: https://github.com/llvm/llvm-project/commit/07ad928d92eac995e8d2fc48b0aafde511e9f3a0.diff

LOG: [libc++] Introduce __specialized_algorithms (#167295)

Added: 
    libcxx/include/__algorithm/specialized_algorithms.h

Modified: 
    libcxx/include/CMakeLists.txt
    libcxx/include/__algorithm/fill_n.h
    libcxx/include/__bit_reference
    libcxx/include/module.modulemap.in

Removed: 
    


################################################################################
diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index a6bd3eacc095c..85a2f8ac8ec4b 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -194,6 +194,7 @@ set(files
   __algorithm/simd_utils.h
   __algorithm/sort.h
   __algorithm/sort_heap.h
+  __algorithm/specialized_algorithms.h
   __algorithm/stable_partition.h
   __algorithm/stable_sort.h
   __algorithm/swap_ranges.h

diff  --git a/libcxx/include/__algorithm/fill_n.h b/libcxx/include/__algorithm/fill_n.h
index 426fe228bdabb..3d06ea4f080fe 100644
--- a/libcxx/include/__algorithm/fill_n.h
+++ b/libcxx/include/__algorithm/fill_n.h
@@ -10,13 +10,13 @@
 #define _LIBCPP___ALGORITHM_FILL_N_H
 
 #include <__algorithm/for_each_n_segment.h>
-#include <__algorithm/min.h>
+#include <__algorithm/specialized_algorithms.h>
 #include <__config>
-#include <__fwd/bit_reference.h>
 #include <__iterator/iterator_traits.h>
 #include <__iterator/segmented_iterator.h>
-#include <__memory/pointer_traits.h>
+#include <__type_traits/enable_if.h>
 #include <__utility/convert_to_integral.h>
+#include <__utility/move.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -29,7 +29,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 // fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
 
-template <class _OutputIterator, class _Size, class _Tp>
+template <
+    class _OutputIterator,
+    class _Size,
+    class _Tp,
+    __enable_if_t<!__specialized_algorithm<_Algorithm::__fill_n, __single_iterator<_OutputIterator> >::__has_algorithm,
+                  int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
 __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
 #ifndef _LIBCPP_CXX03_LANG
@@ -47,42 +52,14 @@ __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) {
   return __first;
 }
 
-template <bool _FillVal, class _Cp>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
-__fill_n_bool(__bit_iterator<_Cp, false> __first, typename __size_
diff erence_type_traits<_Cp>::size_type __n) {
-  using _It            = __bit_iterator<_Cp, false>;
-  using __storage_type = typename _It::__storage_type;
-
-  const int __bits_per_word = _It::__bits_per_word;
-  // do first partial word
-  if (__first.__ctz_ != 0) {
-    __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
-    __storage_type __dn    = std::min(__clz_f, __n);
-    std::__fill_masked_range(std::__to_address(__first.__seg_), __clz_f - __dn, __first.__ctz_, _FillVal);
-    __n -= __dn;
-    ++__first.__seg_;
-  }
-  // do middle whole words
-  __storage_type __nw = __n / __bits_per_word;
-  std::__fill_n(std::__to_address(__first.__seg_), __nw, _FillVal ? static_cast<__storage_type>(-1) : 0);
-  __n -= __nw * __bits_per_word;
-  // do last partial word
-  if (__n > 0) {
-    __first.__seg_ += __nw;
-    std::__fill_masked_range(std::__to_address(__first.__seg_), __bits_per_word - __n, 0u, _FillVal);
-  }
-}
-
-template <class _Cp, class _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false>
-__fill_n(__bit_iterator<_Cp, false> __first, _Size __n, const bool& __value) {
-  if (__n > 0) {
-    if (__value)
-      std::__fill_n_bool<true>(__first, __n);
-    else
-      std::__fill_n_bool<false>(__first, __n);
-  }
-  return __first + __n;
+template <class _OutIter,
+          class _Size,
+          class _Tp,
+          __enable_if_t<__specialized_algorithm<_Algorithm::__fill_n, __single_iterator<_OutIter> >::__has_algorithm,
+                        int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutIter __fill_n(_OutIter __first, _Size __n, const _Tp& __value) {
+  return __specialized_algorithm<_Algorithm::__fill_n, __single_iterator<_OutIter> >()(
+      std::move(__first), __n, __value);
 }
 
 template <class _OutputIterator, class _Size, class _Tp>

diff  --git a/libcxx/include/__algorithm/specialized_algorithms.h b/libcxx/include/__algorithm/specialized_algorithms.h
new file mode 100644
index 0000000000000..a2ffd36f0c87d
--- /dev/null
+++ b/libcxx/include/__algorithm/specialized_algorithms.h
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 _LIBCPP___ALGORITHM_SPECIALIZED_ALGORITHMS_H
+#define _LIBCPP___ALGORITHM_SPECIALIZED_ALGORITHMS_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace _Algorithm {
+struct __fill_n {};
+} // namespace _Algorithm
+
+template <class>
+struct __single_iterator;
+
+// This struct allows specializing algorithms for specific arguments. This is useful when we know a more efficient
+// algorithm implementation for e.g. library-defined iterators. _Alg is one of tags defined inside the _Algorithm
+// namespace above. _Ranges is an essentially arbitrary subset of the arguments to the algorithm that are used for
+// dispatching. This set is specific to the algorithm: look at each algorithm to see which arguments they use for
+// dispatching to specialized algorithms.
+//
+// A specialization of `__specialized_algorithm` has to define `__has_algorithm` to true for the specialized algorithm
+// to be used. This is intended for cases where iterators can do generic unwrapping and forward to a 
diff erent
+// specialization of `__specialized_algorithm`.
+//
+// If __has_algorithm is true, there has to be an operator() which will get called with the actual arguments to the
+// algorithm.
+template <class _Alg, class... _Ranges>
+struct __specialized_algorithm {
+  static const bool __has_algorithm = false;
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___ALGORITHM_SPECIALIZED_ALGORITHMS_H

diff  --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference
index a3e6defd405f8..20e5bc7d5695b 100644
--- a/libcxx/include/__bit_reference
+++ b/libcxx/include/__bit_reference
@@ -15,8 +15,10 @@
 #include <__algorithm/copy_backward.h>
 #include <__algorithm/copy_n.h>
 #include <__algorithm/equal.h>
+#include <__algorithm/fill_n.h>
 #include <__algorithm/min.h>
 #include <__algorithm/rotate.h>
+#include <__algorithm/specialized_algorithms.h>
 #include <__algorithm/swap_ranges.h>
 #include <__assert>
 #include <__bit/countr.h>
@@ -467,10 +469,6 @@ private:
   template <class _Dp>
   friend struct __bit_array;
 
-  template <bool _FillVal, class _Dp>
-  _LIBCPP_CONSTEXPR_SINCE_CXX20 friend void
-  __fill_n_bool(__bit_iterator<_Dp, false> __first, typename __size_
diff erence_type_traits<_Dp>::size_type __n);
-
   template <class _Dp, bool _IC>
   _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_aligned(
       __bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
@@ -537,6 +535,52 @@ private:
   template <bool _ToCount, class _Dp, bool _IC>
   friend typename __bit_iterator<_Dp, _IC>::
diff erence_type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
   __count_bool(__bit_iterator<_Dp, _IC>, typename __size_
diff erence_type_traits<_Dp>::size_type);
+
+  template <class, class...>
+  friend struct __specialized_algorithm;
+};
+
+template <class _Cp>
+struct __specialized_algorithm<_Algorithm::__fill_n, __single_iterator<__bit_iterator<_Cp, false> > > {
+  static const bool __has_algorithm = true;
+
+  template <bool _FillVal>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void
+  __impl(__bit_iterator<_Cp, false> __first, typename __size_
diff erence_type_traits<_Cp>::size_type __n) {
+    using _It            = __bit_iterator<_Cp, false>;
+    using __storage_type = typename _It::__storage_type;
+
+    const int __bits_per_word = _It::__bits_per_word;
+    // do first partial word
+    if (__first.__ctz_ != 0) {
+      __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
+      __storage_type __dn    = std::min(__clz_f, __n);
+      std::__fill_masked_range(std::__to_address(__first.__seg_), __clz_f - __dn, __first.__ctz_, _FillVal);
+      __n -= __dn;
+      ++__first.__seg_;
+    }
+    // do middle whole words
+    __storage_type __nw = __n / __bits_per_word;
+    std::__fill_n(std::__to_address(__first.__seg_), __nw, _FillVal ? static_cast<__storage_type>(-1) : 0);
+    __n -= __nw * __bits_per_word;
+    // do last partial word
+    if (__n > 0) {
+      __first.__seg_ += __nw;
+      std::__fill_masked_range(std::__to_address(__first.__seg_), __bits_per_word - __n, 0u, _FillVal);
+    }
+  }
+
+  template <class _Size, class _Tp>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static __bit_iterator<_Cp, false>
+  operator()(__bit_iterator<_Cp, false> __first, _Size __n, const _Tp& __value) {
+    if (__n > 0) {
+      if (__value)
+        __impl<true>(__first, __n);
+      else
+        __impl<false>(__first, __n);
+    }
+    return __first + __n;
+  }
 };
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 1ee418b0b4337..0ac5a1ade817f 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -829,6 +829,7 @@ module std [system] {
     module simd_utils                             { header "__algorithm/simd_utils.h" }
     module sort_heap                              { header "__algorithm/sort_heap.h" }
     module sort                                   { header "__algorithm/sort.h" }
+    module specialized_algorithms                 { header "__algorithm/specialized_algorithms.h" }
     module stable_partition                       { header "__algorithm/stable_partition.h" }
     module stable_sort {
       header "__algorithm/stable_sort.h"


        


More information about the libcxx-commits mailing list