Skip to content

Commit 8dd5a73

Browse files
committed
Optimize random-access-iterator input
1 parent e0db8c9 commit 8dd5a73

File tree

8 files changed

+144
-104
lines changed

8 files changed

+144
-104
lines changed

libcxx/include/__algorithm/copy.h

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <__algorithm/min.h>
1515
#include <__config>
1616
#include <__fwd/bit_reference.h>
17-
#include <__iterator/distance.h>
1817
#include <__iterator/iterator_traits.h>
1918
#include <__iterator/segmented_iterator.h>
2019
#include <__memory/pointer_traits.h>
@@ -156,25 +155,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> _
156155
return __result;
157156
}
158157

159-
template <class _InIter,
160-
class _Sent,
161-
__enable_if_t<__has_input_iterator_category<_InIter>::value &&
162-
!__has_random_access_iterator_category<_InIter>::value,
163-
int> = 0>
164-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_InIter>::difference_type
165-
__iter_sent_distance(_InIter __first, _Sent __last) {
166-
typename iterator_traits<_InIter>::difference_type __r(0);
167-
for (; __first != __last; ++__first)
168-
++__r;
169-
return __r;
170-
}
171-
172-
template <class _InIter, class _Sent, __enable_if_t<__has_random_access_iterator_category<_InIter>::value, int> = 0>
173-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_InIter>::difference_type
174-
__iter_sent_distance(_InIter __first, _Sent __last) {
175-
return static_cast<typename iterator_traits<_InIter>::difference_type>(__last - __first);
176-
}
177-
178158
struct __copy_impl {
179159
template <class _InIter, class _Sent, class _OutIter>
180160
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
@@ -248,31 +228,19 @@ struct __copy_impl {
248228
return std::make_pair(__last, std::__copy_unaligned(__first, __last, __result));
249229
}
250230

251-
template <class _InIter, class _Cp, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
231+
template < class _InIter,
232+
class _Cp,
233+
__enable_if_t<!__is_segmented_iterator<_InIter>::value &&
234+
(__has_random_access_iterator_category<_InIter>::value ||
235+
__has_iterator_concept_convertible_to<_InIter, random_access_iterator_tag>::value) &&
236+
is_convertible<typename iterator_traits<_InIter>::value_type, bool>::value,
237+
int> = 0>
252238
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, __bit_iterator<_Cp, false> >
253239
operator()(_InIter __first, _InIter __last, __bit_iterator<_Cp, /* IsConst = */ false> __result) const {
254-
std::__for_each_segment(__first, __last, _CopySegment<_InIter, __bit_iterator<_Cp, false> >(__result));
255-
return std::make_pair(__last, std::move(__result));
256-
}
257-
258-
template <class _InIter,
259-
class _Sent,
260-
class _Cp,
261-
__enable_if_t<!__is_segmented_iterator<_InIter>::value &&
262-
(__has_forward_iterator_category<_InIter>::value ||
263-
__has_iterator_concept_convertible_to<_InIter, forward_iterator_tag>::value) &&
264-
is_convertible<typename iterator_traits<_InIter>::value_type, bool>::value,
265-
int> = 0>
266-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, __bit_iterator<_Cp, false> >
267-
operator()(_InIter __first, _Sent __last, __bit_iterator<_Cp, /* IsConst = */ false> __result) const {
268-
using _It = __bit_iterator<_Cp, false>;
269-
using __storage_type = typename _It::__storage_type;
270-
#if _LIBCPP_STD_VER >= 20
271-
__storage_type __n = static_cast<__storage_type>(std::ranges::distance(__first, __last));
272-
#else
273-
__storage_type __n = static_cast<__storage_type>(std::__iter_sent_distance(__first, __last));
274-
#endif
240+
using _It = __bit_iterator<_Cp, false>;
241+
using __storage_type = typename _It::__storage_type;
275242
const unsigned __bits_per_word = _It::__bits_per_word;
243+
__storage_type __n = static_cast<__storage_type>(__last - __first);
276244

277245
if (__first != __last) {
278246
// do first partial word, if present

libcxx/include/__bit_reference

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,12 @@
2727
#include <__functional/identity.h>
2828
#include <__fwd/bit_reference.h>
2929
#include <__iterator/iterator_traits.h>
30-
#include <__iterator/segmented_iterator.h>
3130
#include <__memory/construct_at.h>
3231
#include <__memory/pointer_traits.h>
3332
#include <__type_traits/conditional.h>
3433
#include <__type_traits/desugars_to.h>
3534
#include <__type_traits/enable_if.h>
3635
#include <__type_traits/is_constant_evaluated.h>
37-
#include <__type_traits/is_convertible.h>
3836
#include <__type_traits/is_same.h>
3937
#include <__type_traits/is_unsigned.h>
4038
#include <__type_traits/void_t.h>
@@ -469,17 +467,6 @@ private:
469467
template <class _Dp>
470468
friend struct __bit_array;
471469

472-
template <class _InIter,
473-
class _Sent,
474-
class _Dp,
475-
__enable_if_t<!__is_segmented_iterator<_InIter>::value &&
476-
(__has_forward_iterator_category<_InIter>::value ||
477-
__has_iterator_concept_convertible_to<_InIter, forward_iterator_tag>::value) &&
478-
is_convertible<typename iterator_traits<_InIter>::value_type, bool>::value,
479-
int> >
480-
_LIBCPP_CONSTEXPR_SINCE_CXX14 friend pair<_InIter, __bit_iterator<_Dp, false> >
481-
__copy_impl::operator()(_InIter __first, _Sent __last, __bit_iterator<_Dp, false> __result) const;
482-
483470
template <bool _FillVal, class _Dp>
484471
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend void
485472
__fill_n_bool(__bit_iterator<_Dp, false> __first, typename __size_difference_type_traits<_Dp>::size_type __n);
@@ -490,10 +477,7 @@ private:
490477
template <class _Dp, bool _IC>
491478
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_unaligned(
492479
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
493-
template <class _Dp, bool _IC>
494-
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend pair<__bit_iterator<_Dp, _IC>, __bit_iterator<_Dp, false> >
495-
__copy_impl::operator()(
496-
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result) const;
480+
friend struct __copy_impl;
497481
template <class _Dp, bool _IC>
498482
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_aligned(
499483
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);

libcxx/include/__vector/vector_bool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class vector<bool, _Allocator> {
174174
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
175175
auto __n = static_cast<size_type>(ranges::distance(__range));
176176
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
177+
177178
} else {
178179
__init_with_sentinel(ranges::begin(__range), ranges::end(__range));
179180
}

libcxx/test/benchmarks/algorithms/modifying/copy.bench.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ int main(int argc, char** argv) {
5252
bm.operator()<std::deque<int>>("rng::copy(deque<int>)", std::ranges::copy);
5353
bm.operator()<std::list<int>>("rng::copy(list<int>)", std::ranges::copy);
5454

55-
#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
5655
// Copy from normal containers to vector<bool>
56+
// Note: vector<bool>::iterator is not an output_iterator before C++23
57+
#if TEST_STD_VER >= 23
5758
bm.operator()<std::vector<int>, std::vector<bool>>("std::copy(vector<int>, std::vector<bool>)", std_copy);
5859
bm.operator()<std::deque<int>, std::vector<bool>>("std::copy(deque<int>, std::vector<bool>)", std_copy);
5960
bm.operator()<std::list<int>, std::vector<bool>>("std::copy(list<int>, std::vector<bool>)", std_copy);
@@ -89,7 +90,7 @@ int main(int argc, char** argv) {
8990
#endif
9091
}
9192

92-
// {std,ranges}::copy(forward_iterator, forward_iterator, vector<bool>)
93+
// {std,ranges}::copy(random_access_iterator, random_access_iterator, vector<bool>)
9394
{
9495
auto bm = []<template <class> class Iter>(std::string name, auto copy) {
9596
benchmark::RegisterBenchmark(name, [copy](auto& st) {
@@ -107,10 +108,8 @@ int main(int argc, char** argv) {
107108
}
108109
})->Range(64, 1 << 20);
109110
};
110-
bm.operator()<forward_iterator>("std::copy(forward_iterator, vector<bool>)", std_copy);
111111
bm.operator()<random_access_iterator>("std::copy(random_access_iterator, vector<bool>)", std_copy);
112112
#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
113-
bm.operator()<forward_iterator>("rng::copy(forward_iterator, vector<bool>)", std::ranges::copy);
114113
bm.operator()<random_access_iterator>("rng::copy(random_access_iterator, vector<bool>)", std::ranges::copy);
115114
#endif
116115
}

libcxx/test/benchmarks/containers/sequence/sequence_container_benchmarks.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,6 @@ void sequence_container_benchmarks(std::string container) {
481481
}
482482
});
483483
};
484-
bm.template operator()<forward_iterator>("fwd_iter");
485484
bm.template operator()<random_access_iterator>("ra_iter");
486485
}
487486
{ // iterator-pair assignment
@@ -505,7 +504,6 @@ void sequence_container_benchmarks(std::string container) {
505504
}
506505
});
507506
};
508-
bm.template operator()<forward_iterator>("fwd_iter");
509507
bm.template operator()<random_access_iterator>("ra_iter");
510508
}
511509
{ // Iterator-pair insertion
@@ -527,7 +525,6 @@ void sequence_container_benchmarks(std::string container) {
527525
}
528526
});
529527
};
530-
bm.template operator()<forward_iterator>("fwd_iter");
531528
bm.template operator()<random_access_iterator>("ra_iter");
532529
}
533530

@@ -548,7 +545,6 @@ void sequence_container_benchmarks(std::string container) {
548545
}
549546
});
550547
};
551-
bm.template operator()<forward_range_wrapper>("fwd_range");
552548
bm.template operator()<random_access_range_wrapper>("ra_range");
553549
}
554550
{ // Range-assignment
@@ -574,7 +570,6 @@ void sequence_container_benchmarks(std::string container) {
574570
}
575571
});
576572
};
577-
bm.template operator()<forward_range_wrapper>("fwd_range");
578573
bm.template operator()<random_access_range_wrapper>("ra_range");
579574
}
580575
{ // Range-insertion
@@ -597,7 +592,6 @@ void sequence_container_benchmarks(std::string container) {
597592
}
598593
});
599594
};
600-
bm.template operator()<forward_range_wrapper>("fwd_range");
601595
bm.template operator()<random_access_range_wrapper>("ra_range");
602596
}
603597
{ // Range-append
@@ -618,7 +612,6 @@ void sequence_container_benchmarks(std::string container) {
618612
}
619613
});
620614
};
621-
bm.template operator()<forward_range_wrapper>("fwd_range");
622615
bm.template operator()<random_access_range_wrapper>("ra_range");
623616
}
624617
#endif

libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -88,31 +88,32 @@ TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
8888
}
8989

9090
template <std::size_t N>
91-
struct CopyFromForwardIterToBitIter {
91+
struct CopyFromIterToBitIter {
9292
std::array<bool, N> in;
9393

94-
template <class FwdIter>
94+
template <class Iter>
9595
TEST_CONSTEXPR_CXX20 void operator()() {
9696
for (std::size_t i = 0; i < in.size(); i += 2)
9797
in[i] = true;
9898

9999
{ // Aligned
100100
std::vector<bool> out(N);
101-
std::copy(FwdIter(in.data()), FwdIter(in.data() + N), out.begin());
101+
std::copy(Iter(in.data()), Iter(in.data() + N), out.begin());
102102
for (std::size_t i = 0; i < N; ++i)
103103
assert(out[i] == static_cast<bool>(in[i]));
104104
}
105105
{ // Unaligned
106106
std::vector<bool> out(N + 8);
107-
std::copy(FwdIter(in.data()), FwdIter(in.data() + N), out.begin() + 4);
107+
std::copy(Iter(in.data()), Iter(in.data() + N), out.begin() + 4);
108108
for (std::size_t i = 0; i < N; ++i)
109109
assert(out[i + 4] == static_cast<bool>(in[i]));
110110
}
111111
}
112112
};
113113

114114
// Test std::copy with segmented iterators: deque<T>::iterator, join_view::iterator
115-
void test_segmented_iterator() { // TODO: Mark this test as TEST_CONSTEXPR_CXX23 when std::deque is constexpr
115+
/*TEST_CONSTEXPR_CXX26*/ void
116+
test_segmented_iterator() { // TODO: Mark as TEST_CONSTEXPR_CXX26 once std::deque is constexpr
116117
// std::deque iterator
117118
{ // Copy from segmented input to contiguous output (deque<int> to vector<int>)
118119
std::deque<int> in(20);
@@ -157,7 +158,7 @@ void test_segmented_iterator() { // TODO: Mark this test as TEST_CONSTEXPR_CXX23
157158

158159
#if TEST_STD_VER >= 20
159160
// join_view iterator
160-
{ // Copy from segmented input to contiguous output (join_viw to vector<int>)
161+
{ // Copy from segmented input to contiguous output (join_view to vector<int>)
161162
std::vector<std::vector<int>> v{{1, 2}, {1, 2, 3}, {0, 0}, {3, 4, 5}, {6}, {7, 8, 9, 6}, {0, 1, 2, 3, 0, 1, 2}};
162163
auto jv = std::ranges::join_view(v);
163164
std::vector<int> expected(jv.begin(), jv.end());
@@ -359,15 +360,15 @@ TEST_CONSTEXPR_CXX20 bool test() {
359360
}
360361
}
361362

362-
{ // Test std::copy when copying from forward_iterators (and above) to vector<bool> iterator
363-
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<8>());
364-
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<19>());
365-
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<32>());
366-
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<64>());
367-
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<299>());
363+
{ // Test std::copy when copying from input_iterators (and above) to vector<bool> iterator
364+
types::for_each(types::cpp17_input_iterator_list<bool*>(), CopyFromIterToBitIter<8>());
365+
types::for_each(types::cpp17_input_iterator_list<bool*>(), CopyFromIterToBitIter<19>());
366+
types::for_each(types::cpp17_input_iterator_list<bool*>(), CopyFromIterToBitIter<32>());
367+
types::for_each(types::cpp17_input_iterator_list<bool*>(), CopyFromIterToBitIter<64>());
368+
types::for_each(types::cpp17_input_iterator_list<bool*>(), CopyFromIterToBitIter<299>());
368369
}
369370

370-
if (!TEST_IS_CONSTANT_EVALUATED) // TODO: Use TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED when std::deque is made constexpr
371+
if (!TEST_IS_CONSTANT_EVALUATED) // TODO: Use TEST_STD_AT_LEAST_26_OR_RUNTIME_EVALUATED when std::deque is made constexpr
371372
test_segmented_iterator();
372373

373374
return true;

0 commit comments

Comments
 (0)