Skip to content

Commit 77235c2

Browse files
committed
Rewrite benchmarks and tests to avoid moving/reading a already-moved vector
1 parent d841abe commit 77235c2

File tree

6 files changed

+120
-84
lines changed

6 files changed

+120
-84
lines changed

libcxx/test/benchmarks/algorithms/move.bench.cpp

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,46 +10,61 @@
1010

1111
#include <algorithm>
1212
#include <benchmark/benchmark.h>
13+
#include <ranges>
1314
#include <vector>
1415

15-
static void bm_ranges_move_vb(benchmark::State& state, bool aligned) {
16+
template <bool aligned>
17+
void bm_ranges_move_vb(benchmark::State& state) {
1618
auto n = state.range();
17-
std::vector<bool> in(n, true);
18-
std::vector<bool> out(aligned ? n : n + 8);
19-
benchmark::DoNotOptimize(&in);
20-
auto dst = aligned ? out.begin() : out.begin() + 4;
19+
std::vector<bool> v1(n, true);
20+
std::vector<bool> v2(n, false);
21+
benchmark::DoNotOptimize(v1);
22+
benchmark::DoNotOptimize(v2);
23+
std::vector<bool>* in = &v1;
24+
std::vector<bool>* out = &v2;
2125
for (auto _ : state) {
22-
benchmark::DoNotOptimize(std::ranges::move(in, dst));
23-
benchmark::DoNotOptimize(&out);
26+
if constexpr (aligned) {
27+
benchmark::DoNotOptimize(std::ranges::move(*in, std::ranges::begin(*out)));
28+
} else {
29+
benchmark::DoNotOptimize(std::ranges::move(*in | std::views::drop(4), std::ranges::begin(*out)));
30+
}
31+
std::swap(in, out);
32+
benchmark::DoNotOptimize(in);
33+
benchmark::DoNotOptimize(out);
2434
}
2535
}
2636

27-
static void bm_move_vb(benchmark::State& state, bool aligned) {
37+
template <bool aligned>
38+
void bm_move_vb(benchmark::State& state) {
2839
auto n = state.range();
29-
std::vector<bool> in(n, true);
30-
std::vector<bool> out(aligned ? n : n + 8);
31-
benchmark::DoNotOptimize(&in);
32-
auto beg = in.begin();
33-
auto end = in.end();
34-
auto dst = aligned ? out.begin() : out.begin() + 4;
40+
std::vector<bool> v1(n, true);
41+
std::vector<bool> v2(n, false);
42+
benchmark::DoNotOptimize(v1);
43+
benchmark::DoNotOptimize(v2);
44+
std::vector<bool>* in = &v1;
45+
std::vector<bool>* out = &v2;
3546
for (auto _ : state) {
36-
benchmark::DoNotOptimize(std::move(beg, end, dst));
37-
benchmark::DoNotOptimize(&out);
47+
auto first1 = in->begin();
48+
auto last1 = in->end();
49+
auto first2 = out->begin();
50+
if constexpr (aligned) {
51+
benchmark::DoNotOptimize(std::move(first1, last1, first2));
52+
} else {
53+
benchmark::DoNotOptimize(std::move(first1 + 4, last1, first2));
54+
}
55+
std::swap(in, out);
56+
benchmark::DoNotOptimize(in);
57+
benchmark::DoNotOptimize(out);
3858
}
3959
}
4060

41-
static void bm_ranges_move_vb_aligned(benchmark::State& state) { bm_ranges_move_vb(state, true); }
42-
static void bm_ranges_move_vb_unaligned(benchmark::State& state) { bm_ranges_move_vb(state, false); }
61+
BENCHMARK(bm_ranges_move_vb<true>)
62+
->Name("bm_ranges_move_vb_aligned")
63+
->Range(8, 1 << 16)
64+
->DenseRange(102400, 204800, 4096);
65+
BENCHMARK(bm_ranges_move_vb<false>)->Name("bm_ranges_move_vb_unaligned")->Range(8, 1 << 20);
4366

44-
static void bm_move_vb_aligned(benchmark::State& state) { bm_move_vb(state, true); }
45-
static void bm_move_vb_unaligned(benchmark::State& state) { bm_move_vb(state, false); }
46-
47-
// Test std::ranges::move for vector<bool>::iterator
48-
BENCHMARK(bm_ranges_move_vb_aligned)->Range(8, 1 << 16)->DenseRange(102400, 204800, 4096);
49-
BENCHMARK(bm_ranges_move_vb_unaligned)->Range(8, 1 << 20);
50-
51-
// Test std::move for vector<bool>::iterator
52-
BENCHMARK(bm_move_vb_aligned)->Range(8, 1 << 20);
53-
BENCHMARK(bm_move_vb_unaligned)->Range(8, 1 << 20);
67+
BENCHMARK(bm_move_vb<true>)->Name("bm_move_vb_aligned")->Range(8, 1 << 20);
68+
BENCHMARK(bm_move_vb<false>)->Name("bm_move_vb_unaligned")->Range(8, 1 << 20);
5469

5570
BENCHMARK_MAIN();

libcxx/test/benchmarks/algorithms/move_backward.bench.cpp

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,46 +10,61 @@
1010

1111
#include <algorithm>
1212
#include <benchmark/benchmark.h>
13+
#include <ranges>
1314
#include <vector>
1415

15-
static void bm_ranges_move_backward_vb(benchmark::State& state, bool aligned) {
16+
template <bool aligned>
17+
void bm_ranges_move_backward_vb(benchmark::State& state) {
1618
auto n = state.range();
17-
std::vector<bool> in(n, true);
18-
std::vector<bool> out(aligned ? n : n + 8);
19-
benchmark::DoNotOptimize(&in);
20-
auto dst = aligned ? out.end() : out.end() - 4;
19+
std::vector<bool> v1(n, true);
20+
std::vector<bool> v2(n, false);
21+
benchmark::DoNotOptimize(v1);
22+
benchmark::DoNotOptimize(v2);
23+
std::vector<bool>* in = &v1;
24+
std::vector<bool>* out = &v2;
2125
for (auto _ : state) {
22-
benchmark::DoNotOptimize(std::ranges::move_backward(in, dst));
23-
benchmark::DoNotOptimize(&out);
26+
if constexpr (aligned) {
27+
benchmark::DoNotOptimize(std::ranges::move_backward(*in, std::ranges::end(*out)));
28+
} else {
29+
benchmark::DoNotOptimize(std::ranges::move_backward(*in | std::views::take(n - 4), std::ranges::end(*out)));
30+
}
31+
std::swap(in, out);
32+
benchmark::DoNotOptimize(in);
33+
benchmark::DoNotOptimize(out);
2434
}
2535
}
2636

27-
static void bm_move_backward(benchmark::State& state, bool aligned) {
37+
template <bool aligned>
38+
void bm_move_backward_vb(benchmark::State& state) {
2839
auto n = state.range();
29-
std::vector<bool> in(n, true);
30-
std::vector<bool> out(aligned ? n : n + 8);
31-
benchmark::DoNotOptimize(&in);
32-
auto beg = in.begin();
33-
auto end = in.end();
34-
auto dst = aligned ? out.end() : out.end() - 4;
40+
std::vector<bool> v1(n, true);
41+
std::vector<bool> v2(n, false);
42+
benchmark::DoNotOptimize(v1);
43+
benchmark::DoNotOptimize(v2);
44+
std::vector<bool>* in = &v1;
45+
std::vector<bool>* out = &v2;
3546
for (auto _ : state) {
36-
benchmark::DoNotOptimize(std::move_backward(beg, end, dst));
37-
benchmark::DoNotOptimize(&out);
47+
auto first1 = in->begin();
48+
auto last1 = in->end();
49+
auto last2 = out->end();
50+
if constexpr (aligned) {
51+
benchmark::DoNotOptimize(std::move_backward(first1, last1, last2));
52+
} else {
53+
benchmark::DoNotOptimize(std::move_backward(first1, last1 - 4, last2));
54+
}
55+
std::swap(in, out);
56+
benchmark::DoNotOptimize(in);
57+
benchmark::DoNotOptimize(out);
3858
}
3959
}
4060

41-
static void bm_ranges_move_backward_vb_aligned(benchmark::State& state) { bm_ranges_move_backward_vb(state, true); }
42-
static void bm_ranges_move_backward_vb_unaligned(benchmark::State& state) { bm_ranges_move_backward_vb(state, false); }
61+
BENCHMARK(bm_ranges_move_backward_vb<true>)
62+
->Name("bm_ranges_move_backward_vb_aligned")
63+
->Range(8, 1 << 16)
64+
->DenseRange(102400, 204800, 4096);
65+
BENCHMARK(bm_ranges_move_backward_vb<false>)->Name("bm_ranges_move_backward_vb_unaligned")->Range(8, 1 << 20);
4366

44-
static void bm_move_backward_vb_aligned(benchmark::State& state) { bm_move_backward(state, true); }
45-
static void bm_move_backward_vb_unaligned(benchmark::State& state) { bm_move_backward(state, false); }
46-
47-
// Test std::ranges::move_backward for vector<bool>::iterator
48-
BENCHMARK(bm_ranges_move_backward_vb_aligned)->Range(8, 1 << 16)->DenseRange(102400, 204800, 4096);
49-
BENCHMARK(bm_ranges_move_backward_vb_unaligned)->Range(8, 1 << 20);
50-
51-
// Test std::move_backward for vector<bool>::iterator
52-
BENCHMARK(bm_move_backward_vb_aligned)->Range(8, 1 << 20);
53-
BENCHMARK(bm_move_backward_vb_unaligned)->Range(8, 1 << 20);
67+
BENCHMARK(bm_move_backward_vb<true>)->Name("bm_move_backward_vb_aligned")->Range(8, 1 << 20);
68+
BENCHMARK(bm_move_backward_vb<false>)->Name("bm_move_backward_vb_unaligned")->Range(8, 1 << 20);
5469

5570
BENCHMARK_MAIN();

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,22 @@ struct Test1OutIters {
9494
};
9595

9696
TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
97-
std::vector<bool> in(N, false);
97+
std::vector<bool> v(N, false);
9898
for (std::size_t i = 0; i < N; i += 2)
99-
in[i] = true;
99+
v[i] = true;
100100

101101
{ // Test move with aligned bytes
102+
std::vector<bool> in(v);
102103
std::vector<bool> out(N);
103104
std::move(in.begin(), in.end(), out.begin());
104-
assert(in == out);
105+
assert(out == v);
105106
}
106107
{ // Test move with unaligned bytes
107-
std::vector<bool> out(N + 8);
108-
std::move(in.begin(), in.end(), out.begin() + 4);
109-
for (std::size_t i = 0; i < N; ++i)
110-
assert(out[i + 4] == in[i]);
108+
std::vector<bool> in(v);
109+
std::vector<bool> out(N);
110+
std::move(in.begin() + 4, in.end(), out.begin());
111+
for (std::size_t i = 0; i < N - 4; ++i)
112+
assert(v[i + 4] == out[i]);
111113
}
112114

113115
return true;

libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,20 +90,22 @@ struct Test1OutIters {
9090
};
9191

9292
TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
93-
std::vector<bool> in(N, false);
93+
std::vector<bool> v(N, false);
9494
for (std::size_t i = 0; i < N; i += 2)
95-
in[i] = true;
95+
v[i] = true;
9696

9797
{ // Test move_backward with aligned bytes
98+
std::vector<bool> in(v);
9899
std::vector<bool> out(N);
99100
std::move_backward(in.begin(), in.end(), out.end());
100-
assert(in == out);
101+
assert(out == v);
101102
}
102103
{ // Test move_backward with unaligned bytes
103-
std::vector<bool> out(N + 8);
104-
std::move_backward(in.begin(), in.end(), out.end() - 4);
105-
for (std::size_t i = 0; i < N; ++i)
106-
assert(out[i + 4] == in[i]);
104+
std::vector<bool> in(v);
105+
std::vector<bool> out(N);
106+
std::move_backward(in.begin(), in.end() - 4, out.end());
107+
for (std::size_t i = 0; i < N - 4; ++i)
108+
assert(out[i + 4] == v[i]);
107109
}
108110

109111
return true;

libcxx/test/std/algorithms/alg.modifying.operations/alg.move/ranges.move.pass.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -190,20 +190,21 @@ struct IteratorWithMoveIter {
190190

191191
#if TEST_STD_VER >= 23
192192
constexpr bool test_vector_bool(std::size_t N) {
193-
std::vector<bool> in(N, false);
193+
std::vector<bool> v(N, false);
194194
for (std::size_t i = 0; i < N; i += 2)
195-
in[i] = true;
195+
v[i] = true;
196196

197197
{ // Test move with aligned bytes
198+
std::vector<bool> in{v};
198199
std::vector<bool> out(N);
199200
std::ranges::move(in, out.begin());
200-
assert(in == out);
201+
assert(out == v);
201202
}
202203
{ // Test move with unaligned bytes
203-
std::vector<bool> out(N + 8);
204-
std::ranges::move(in, out.begin() + 4);
205-
for (std::size_t i = 0; i < N; ++i)
206-
assert(out[i + 4] == in[i]);
204+
std::vector<bool> in{v};
205+
std::vector<bool> out(N);
206+
std::ranges::move(in | std::views::drop(4), out.begin());
207+
assert(std::ranges::equal(v | std::views::drop(4), out | std::views::take(N - 4)));
207208
}
208209

209210
return true;

libcxx/test/std/algorithms/alg.modifying.operations/alg.move/ranges.move_backward.pass.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,21 @@ struct IteratorWithMoveIter {
195195

196196
#if TEST_STD_VER >= 23
197197
constexpr bool test_vector_bool(std::size_t N) {
198-
std::vector<bool> in(N, false);
198+
std::vector<bool> v(N, false);
199199
for (std::size_t i = 0; i < N; i += 2)
200-
in[i] = true;
200+
v[i] = true;
201201

202202
{ // Test move_backward with aligned bytes
203+
std::vector<bool> in{v};
203204
std::vector<bool> out(N);
204205
std::ranges::move_backward(in, out.end());
205-
assert(in == out);
206+
assert(out == v);
206207
}
207208
{ // Test move_backward with unaligned bytes
208-
std::vector<bool> out(N + 8);
209-
std::ranges::move_backward(in, out.end() - 4);
210-
for (std::size_t i = 0; i < N; ++i)
211-
assert(out[i + 4] == in[i]);
209+
std::vector<bool> in{v};
210+
std::vector<bool> out(N);
211+
std::ranges::move_backward(in | std::views::take(N - 4), out.end());
212+
assert(std::ranges::equal(v | std::views::take(N - 4), out | std::views::drop(4)));
212213
}
213214

214215
return true;

0 commit comments

Comments
 (0)