[libcxx-commits] [libcxx] [libc++] Optimize ranges::copy for random_accsess_iterator and segmented_iterator (PR #120134)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jun 18 10:13:06 PDT 2025
================
@@ -221,12 +222,66 @@ struct __copy_impl {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> >
operator()(__bit_iterator<_Cp, _IsConst> __first,
__bit_iterator<_Cp, _IsConst> __last,
- __bit_iterator<_Cp, false> __result) const {
+ __bit_iterator<_Cp, /* IsConst = */ false> __result) const {
if (__first.__ctz_ == __result.__ctz_)
return std::make_pair(__last, std::__copy_aligned(__first, __last, __result));
return std::make_pair(__last, std::__copy_unaligned(__first, __last, __result));
}
+ template < class _InIter,
+ class _Cp,
+ __enable_if_t<!__is_segmented_iterator<_InIter>::value &&
+ (__has_random_access_iterator_category<_InIter>::value ||
+ __has_iterator_concept_convertible_to<_InIter, random_access_iterator_tag>::value) &&
+ is_convertible<typename iterator_traits<_InIter>::value_type, bool>::value,
+ int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, __bit_iterator<_Cp, false> >
+ operator()(_InIter __first, _InIter __last, __bit_iterator<_Cp, /* IsConst = */ false> __result) const {
+ using _It = __bit_iterator<_Cp, false>;
+ using __storage_type = typename _It::__storage_type;
+ const unsigned __bits_per_word = _It::__bits_per_word;
+ __storage_type __n = static_cast<__storage_type>(__last - __first);
+
+ if (__first != __last) {
+ // do first partial word, if present
+ if (__result.__ctz_ != 0) {
+ __storage_type __clz = static_cast<__storage_type>(__bits_per_word - __result.__ctz_);
+ __storage_type __dn = std::min(__clz, __n);
+ __storage_type __w = *__result.__seg_;
+ __storage_type __m = std::__middle_mask<__storage_type>(__clz - __dn, __result.__ctz_);
+ __w &= ~__m;
+ for (__storage_type __i = 0; __i < __dn; ++__i, ++__first)
+ __w |= static_cast<__storage_type>(*__first) << __result.__ctz_++;
----------------
ldionne wrote:
Here you're static casting from e.g. `int*` to the storage type directly and you're shifting. When we copy from a sequence of `int`s to a `vector<bool>`, we should be performing a conversion of each integer to `bool`, and then setting the appropriate bit to either 0 or 1. I might be misunderstanding something here, but I don't see that that's what's happening.
I think what I am misunderstanding is how this happens:
> the optimization first assembles the input data into storage words
Could you please explain?
https://github.com/llvm/llvm-project/pull/120134
More information about the libcxx-commits
mailing list