Skip to content

Commit 6833af8

Browse files
committed
Fix mask and add copy benchmark
1 parent fd82b4e commit 6833af8

File tree

4 files changed

+69
-19
lines changed

4 files changed

+69
-19
lines changed

libcxx/include/__algorithm/copy.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,21 +242,33 @@ struct __copy_impl {
242242
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> >
243243
operator()(__bit_iterator<_Cp, _IsConst> __first,
244244
__bit_iterator<_Cp, _IsConst> __last,
245-
__bit_iterator<_Cp, false> __result) const {
245+
__bit_iterator<_Cp, /* IsConst = */ false> __result) const {
246246
if (__first.__ctz_ == __result.__ctz_)
247247
return std::make_pair(__last, std::__copy_aligned(__first, __last, __result));
248248
return std::make_pair(__last, std::__copy_unaligned(__first, __last, __result));
249249
}
250250

251+
template <class _InIter,
252+
class _OutIter,
253+
class _Cp,
254+
bool _IsConst,
255+
__enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
256+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, __bit_iterator<_Cp, false> >
257+
operator()(_InIter __first, _InIter __last, __bit_iterator<_Cp, /* IsConst = */ false> __result) const {
258+
std::__for_each_segment(__first, __last, _CopySegment<_InIter, __bit_iterator<_Cp, false> >(__result));
259+
return std::make_pair(__last, std::move(__result));
260+
}
261+
251262
template <class _InIter,
252263
class _Sent,
253264
class _Cp,
254-
__enable_if_t<(__has_forward_iterator_category<_InIter>::value ||
255-
__has_iterator_concept_convertible_to<_InIter, forward_iterator_tag>::value) &&
265+
__enable_if_t<!__is_segmented_iterator<_InIter>::value &&
266+
(__has_forward_iterator_category<_InIter>::value ||
267+
__has_iterator_concept_convertible_to<_InIter, forward_iterator_tag>::value) &&
256268
is_convertible<typename iterator_traits<_InIter>::value_type, bool>::value,
257269
int> = 0>
258270
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, __bit_iterator<_Cp, false> >
259-
operator()(_InIter __first, _Sent __last, __bit_iterator<_Cp, false> __result) const {
271+
operator()(_InIter __first, _Sent __last, __bit_iterator<_Cp, /* IsConst = */ false> __result) const {
260272
using _It = __bit_iterator<_Cp, false>;
261273
using __storage_type = typename _It::__storage_type;
262274
#if _LIBCPP_STD_VER >= 20
@@ -272,7 +284,7 @@ struct __copy_impl {
272284
__storage_type __clz = static_cast<__storage_type>(__bits_per_word - __result.__ctz_);
273285
__storage_type __dn = std::min(__clz, __n);
274286
__storage_type __w = *__result.__seg_;
275-
__storage_type __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
287+
__storage_type __m = std::__middle_mask<__storage_type>(__clz - __dn, __result.__ctz_);
276288
__w &= ~__m;
277289
for (__storage_type __i = 0; __i < __dn; ++__i, ++__first)
278290
__w |= static_cast<__storage_type>(*__first) << __result.__ctz_++;
@@ -298,7 +310,7 @@ struct __copy_impl {
298310
__storage_type __w = 0;
299311
for (__storage_type __i = 0; __i < __n; ++__i, ++__first)
300312
__w |= static_cast<__storage_type>(*__first) << __i;
301-
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
313+
__storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
302314
*__result.__seg_ &= ~__m;
303315
*__result.__seg_ |= __w;
304316
__result.__ctz_ = __n;

libcxx/include/__bit_reference

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@
3333
#include <__type_traits/desugars_to.h>
3434
#include <__type_traits/enable_if.h>
3535
#include <__type_traits/is_constant_evaluated.h>
36+
#include <__type_traits/is_convertible.h>
3637
#include <__type_traits/is_same.h>
3738
#include <__type_traits/is_unsigned.h>
38-
#include <__type_traits/is_convertible.h>
3939
#include <__type_traits/void_t.h>
4040
#include <__utility/pair.h>
4141
#include <__utility/swap.h>
@@ -467,8 +467,9 @@ private:
467467
template <class _InIter,
468468
class _Sent,
469469
class _Dp,
470-
__enable_if_t<(__has_forward_iterator_category<_InIter>::value ||
471-
__has_iterator_concept_convertible_to<_InIter, forward_iterator_tag>::value) &&
470+
__enable_if_t<!__is_segmented_iterator<_InIter>::value &&
471+
(__has_forward_iterator_category<_InIter>::value ||
472+
__has_iterator_concept_convertible_to<_InIter, forward_iterator_tag>::value) &&
472473
is_convertible<typename iterator_traits<_InIter>::value_type, bool>::value,
473474
int> >
474475
_LIBCPP_CONSTEXPR_SINCE_CXX14 friend pair<_InIter, __bit_iterator<_Dp, false> >

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

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,23 @@
1818

1919
#include "benchmark/benchmark.h"
2020
#include "../../GenerateInput.h"
21+
#include "test_iterators.h"
2122
#include "test_macros.h"
2223

2324
int main(int argc, char** argv) {
2425
auto std_copy = [](auto first, auto last, auto out) { return std::copy(first, last, out); };
2526

2627
// {std,ranges}::copy(normal container)
2728
{
28-
auto bm = []<class Container>(std::string name, auto copy) {
29+
auto bm = []<class ContainerIn, class ContainerOut = std::vector<typename ContainerIn::value_type>>(
30+
std::string name, auto copy) {
2931
benchmark::RegisterBenchmark(name, [copy](auto& st) {
3032
std::size_t const n = st.range(0);
31-
using ValueType = typename Container::value_type;
32-
Container c;
33+
using ValueType = typename ContainerIn::value_type;
34+
ContainerIn c;
3335
std::generate_n(std::back_inserter(c), n, [] { return Generate<ValueType>::random(); });
3436

35-
std::vector<ValueType> out(n);
37+
ContainerOut out(n);
3638

3739
for ([[maybe_unused]] auto _ : st) {
3840
benchmark::DoNotOptimize(c);
@@ -42,12 +44,21 @@ int main(int argc, char** argv) {
4244
}
4345
})->Range(8, 1 << 20);
4446
};
47+
// Copy from normal containers to vector<int>
4548
bm.operator()<std::vector<int>>("std::copy(vector<int>)", std_copy);
4649
bm.operator()<std::deque<int>>("std::copy(deque<int>)", std_copy);
4750
bm.operator()<std::list<int>>("std::copy(list<int>)", std_copy);
4851
bm.operator()<std::vector<int>>("rng::copy(vector<int>)", std::ranges::copy);
4952
bm.operator()<std::deque<int>>("rng::copy(deque<int>)", std::ranges::copy);
5053
bm.operator()<std::list<int>>("rng::copy(list<int>)", std::ranges::copy);
54+
55+
// Copy from normal containers to vector<bool>
56+
bm.operator()<std::vector<int>, std::vector<bool>>("std::copy(vector<int>, std::vector<bool>)", std_copy);
57+
bm.operator()<std::deque<int>, std::vector<bool>>("std::copy(deque<int>, std::vector<bool>)", std_copy);
58+
bm.operator()<std::list<int>, std::vector<bool>>("std::copy(list<int>, std::vector<bool>)", std_copy);
59+
bm.operator()<std::vector<int>, std::vector<bool>>("rng::copy(vector<int>, std::vector<bool>)", std::ranges::copy);
60+
bm.operator()<std::deque<int>, std::vector<bool>>("rng::copy(deque<int>, std::vector<bool>)", std::ranges::copy);
61+
bm.operator()<std::list<int>, std::vector<bool>>("rng::copy(list<int>, std::vector<bool>)", std::ranges::copy);
5162
}
5263

5364
// {std,ranges}::copy(vector<bool>)
@@ -76,6 +87,32 @@ int main(int argc, char** argv) {
7687
#endif
7788
}
7889

90+
// {std,ranges}::copy(forward_iterator, forward_iterator, vector<bool>)
91+
{
92+
auto bm = []<template <class> class Iter>(std::string name, auto copy) {
93+
benchmark::RegisterBenchmark(name, [copy](auto& st) {
94+
std::size_t const n = st.range(0);
95+
std::vector<int> in(n, 1);
96+
std::vector<bool> out(n);
97+
auto first = Iter(in.begin());
98+
auto last = Iter(in.end());
99+
auto dst = out.begin();
100+
for ([[maybe_unused]] auto _ : st) {
101+
benchmark::DoNotOptimize(in);
102+
benchmark::DoNotOptimize(out);
103+
auto result = copy(first, last, dst);
104+
benchmark::DoNotOptimize(result);
105+
}
106+
})->Range(64, 1 << 20);
107+
};
108+
bm.operator()<forward_iterator>("std::copy(forward_iterator, vector<bool>)", std_copy);
109+
bm.operator()<random_access_iterator>("std::copy(random_access_iterator, vector<bool>)", std_copy);
110+
#if TEST_STD_VER >= 23 // vector<bool>::iterator is not an output_iterator before C++23
111+
bm.operator()<forward_iterator>("rng::copy(forward_iterator, vector<bool>)", std::ranges::copy);
112+
bm.operator()<random_access_iterator>("rng::copy(random_access_iterator, vector<bool>)", std::ranges::copy);
113+
#endif
114+
}
115+
79116
benchmark::Initialize(&argc, argv);
80117
benchmark::RunSpecifiedBenchmarks();
81118
benchmark::Shutdown();

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ struct TestInIters {
6666
};
6767

6868
template <std::size_t N>
69-
struct TestFwdIterInBitIterOut {
69+
struct CopyFromForwardIterToBitIter {
7070
std::array<bool, N> in = {};
7171
template <class FwdIter>
7272
TEST_CONSTEXPR_CXX20 void operator()() {
@@ -285,11 +285,11 @@ TEST_CONSTEXPR_CXX20 bool test() {
285285
}
286286

287287
{ // Test std::copy() with forward_iterator-pair inputs and vector<bool>::iterator output
288-
types::for_each(types::forward_iterator_list<bool*>(), TestFwdIterInBitIterOut<8>());
289-
types::for_each(types::forward_iterator_list<bool*>(), TestFwdIterInBitIterOut<19>());
290-
types::for_each(types::forward_iterator_list<bool*>(), TestFwdIterInBitIterOut<32>());
291-
types::for_each(types::forward_iterator_list<bool*>(), TestFwdIterInBitIterOut<64>());
292-
types::for_each(types::forward_iterator_list<bool*>(), TestFwdIterInBitIterOut<299>());
288+
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<8>());
289+
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<19>());
290+
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<32>());
291+
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<64>());
292+
types::for_each(types::forward_iterator_list<bool*>(), CopyFromForwardIterToBitIter<299>());
293293
}
294294

295295
return true;

0 commit comments

Comments
 (0)