Skip to content

Commit 4cedc59

Browse files
committed
Change benchmarks to add test for constant-folded results
1 parent b81d32b commit 4cedc59

File tree

1 file changed

+22
-68
lines changed

1 file changed

+22
-68
lines changed

libcxx/test/benchmarks/exception_ptr.bench.cpp

Lines changed: 22 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ BENCHMARK(bm_make_exception_ptr)->ThreadRange(1, 8);
2121
void bm_exception_ptr_copy_ctor_nonnull(benchmark::State& state) {
2222
std::exception_ptr excptr = std::make_exception_ptr(42);
2323
for (auto _ : state) {
24-
benchmark::DoNotOptimize(excptr);
2524
benchmark::DoNotOptimize(std::exception_ptr(excptr));
2625
}
2726
}
@@ -30,20 +29,20 @@ BENCHMARK(bm_exception_ptr_copy_ctor_nonnull);
3029
void bm_exception_ptr_copy_ctor_null(benchmark::State& state) {
3130
std::exception_ptr excptr = nullptr;
3231
for (auto _ : state) {
33-
benchmark::DoNotOptimize(excptr);
34-
benchmark::DoNotOptimize(std::exception_ptr(excptr));
32+
std::exception_ptr excptr_copy(excptr);
33+
benchmark::DoNotOptimize(excptr_copy);
34+
// The compiler should be able to constant-fold the comparison
35+
benchmark::DoNotOptimize(excptr_copy == nullptr);
3536
}
3637
}
3738
BENCHMARK(bm_exception_ptr_copy_ctor_null);
3839

39-
4040
void bm_exception_ptr_move_ctor_nonnull(benchmark::State& state) {
4141
std::exception_ptr excptr = std::make_exception_ptr(42);
4242
for (auto _ : state) {
4343
// Need to copy, such that the `excptr` is not moved from and
4444
// empty after the first loop iteration.
4545
std::exception_ptr excptr_copy(excptr);
46-
benchmark::DoNotOptimize(excptr_copy);
4746
benchmark::DoNotOptimize(std::exception_ptr(std::move(excptr_copy)));
4847
}
4948
}
@@ -52,16 +51,17 @@ BENCHMARK(bm_exception_ptr_move_ctor_nonnull);
5251
void bm_exception_ptr_move_ctor_null(benchmark::State& state) {
5352
std::exception_ptr excptr = nullptr;
5453
for (auto _ : state) {
55-
benchmark::DoNotOptimize(excptr);
56-
benchmark::DoNotOptimize(std::exception_ptr(std::move(excptr)));
54+
std::exception_ptr new_excptr(std::move(excptr));
55+
benchmark::DoNotOptimize(new_excptr);
56+
// The compiler should be able to constant-fold the comparison
57+
benchmark::DoNotOptimize(new_excptr == nullptr);
5758
}
5859
}
5960
BENCHMARK(bm_exception_ptr_move_ctor_null);
6061

6162
void bm_exception_ptr_copy_assign_nonnull(benchmark::State& state) {
6263
std::exception_ptr excptr = std::make_exception_ptr(42);
6364
for (auto _ : state) {
64-
benchmark::DoNotOptimize(excptr);
6565
std::exception_ptr new_excptr;
6666
new_excptr = excptr;
6767
benchmark::DoNotOptimize(new_excptr);
@@ -72,22 +72,21 @@ BENCHMARK(bm_exception_ptr_copy_assign_nonnull);
7272
void bm_exception_ptr_copy_assign_null(benchmark::State& state) {
7373
std::exception_ptr excptr = nullptr;
7474
for (auto _ : state) {
75-
benchmark::DoNotOptimize(excptr);
7675
std::exception_ptr new_excptr;
7776
new_excptr = excptr;
7877
benchmark::DoNotOptimize(new_excptr);
78+
// The compiler should be able to constant-fold the comparison
79+
benchmark::DoNotOptimize(new_excptr == nullptr);
7980
}
8081
}
8182
BENCHMARK(bm_exception_ptr_copy_assign_null);
8283

83-
8484
void bm_exception_ptr_move_assign_nonnull(benchmark::State& state) {
8585
std::exception_ptr excptr = std::make_exception_ptr(42);
8686
for (auto _ : state) {
8787
// Need to copy, such that the `excptr` is not moved from and
8888
// empty after the first loop iteration.
8989
std::exception_ptr excptr_copy(excptr);
90-
benchmark::DoNotOptimize(excptr_copy);
9190
std::exception_ptr new_excptr;
9291
new_excptr = std::move(excptr_copy);
9392
benchmark::DoNotOptimize(new_excptr);
@@ -98,84 +97,39 @@ BENCHMARK(bm_exception_ptr_move_assign_nonnull);
9897
void bm_exception_ptr_move_assign_null(benchmark::State& state) {
9998
std::exception_ptr excptr = nullptr;
10099
for (auto _ : state) {
101-
benchmark::DoNotOptimize(excptr);
102100
std::exception_ptr new_excptr;
103101
new_excptr = std::move(excptr);
104102
benchmark::DoNotOptimize(new_excptr);
103+
// The compiler should be able to constant-fold the comparison
104+
benchmark::DoNotOptimize(new_excptr == nullptr);
105105
}
106106
}
107107
BENCHMARK(bm_exception_ptr_move_assign_null);
108108

109109
void bm_exception_ptr_swap_nonnull(benchmark::State& state) {
110-
std::exception_ptr excptr = std::make_exception_ptr(41);
110+
std::exception_ptr excptr1 = std::make_exception_ptr(41);
111111
std::exception_ptr excptr2 = std::make_exception_ptr(42);
112112
for (auto _ : state) {
113-
swap(excptr, excptr2);
114-
benchmark::DoNotOptimize(excptr);
113+
swap(excptr1, excptr2);
114+
benchmark::DoNotOptimize(excptr1);
115115
benchmark::DoNotOptimize(excptr2);
116116
}
117117
}
118118
BENCHMARK(bm_exception_ptr_swap_nonnull);
119119

120120
void bm_exception_ptr_swap_null(benchmark::State& state) {
121-
std::exception_ptr excptr = nullptr;
121+
std::exception_ptr excptr1 = nullptr;
122122
std::exception_ptr excptr2 = nullptr;
123123
for (auto _ : state) {
124-
benchmark::DoNotOptimize(excptr);
125-
swap(excptr, excptr2);
124+
swap(excptr1, excptr2);
125+
benchmark::DoNotOptimize(excptr1);
126126
benchmark::DoNotOptimize(excptr2);
127+
// The compiler should be able to constant-fold those comparisons
128+
benchmark::DoNotOptimize(excptr1 == nullptr);
129+
benchmark::DoNotOptimize(excptr2 == nullptr);
130+
benchmark::DoNotOptimize(excptr1 == excptr2);
127131
}
128132
}
129133
BENCHMARK(bm_exception_ptr_swap_null);
130134

131-
// A chain of moves, copies and swaps.
132-
// In contrast to the previous benchmarks of individual operations,
133-
// this benchmark performs a chain of operations. It thereby
134-
// specifically stresses the information available to the compiler
135-
// for optimizations from the header itself.
136-
static bool exception_ptr_move_copy_swap(std::exception_ptr p1) {
137-
// Taken from https://llvm.org/PR45547
138-
std::exception_ptr p2(p1);
139-
std::exception_ptr p3(std::move(p2));
140-
p2 = std::move(p1);
141-
p1 = p2;
142-
swap(p1, p2);
143-
// Comparisons against nullptr. The overhead from creating temporary `exception_ptr`
144-
// instances should be optimized out.
145-
bool is_null = p1 == nullptr && nullptr == p2;
146-
bool is_equal = p1 == p2;
147-
return is_null && is_equal;
148-
}
149-
150-
// Benchmark copies, moves and comparisons of a non-null exception_ptr.
151-
void bm_exception_ptr_move_copy_swap_nonnull(benchmark::State& state) {
152-
std::exception_ptr excptr = std::make_exception_ptr(42);
153-
for (auto _ : state) {
154-
benchmark::DoNotOptimize(excptr);
155-
benchmark::DoNotOptimize(exception_ptr_move_copy_swap(excptr));
156-
}
157-
}
158-
BENCHMARK(bm_exception_ptr_move_copy_swap_nonnull);
159-
160-
// Benchmark copies, moves and comparisons of a nullptr exception_ptr
161-
// where the compiler cannot prove that the exception_ptr is always
162-
// a nullptr and needs to emit runtime checks.
163-
void bm_exception_ptr_move_copy_swap_null(benchmark::State& state) {
164-
std::exception_ptr excptr;
165-
for (auto _ : state) {
166-
benchmark::DoNotOptimize(excptr);
167-
benchmark::DoNotOptimize(exception_ptr_move_copy_swap(excptr));
168-
}
169-
}
170-
BENCHMARK(bm_exception_ptr_move_copy_swap_null);
171-
172-
// Benchmark copies, moves and comparisons of a nullptr exception_ptr
173-
// where the compiler can proof that the exception_ptr is always a nullptr.
174-
void bm_exception_ptr_move_copy_swap_null_optimized(benchmark::State& state) {
175-
for (auto _ : state) {
176-
benchmark::DoNotOptimize(exception_ptr_move_copy_swap(std::exception_ptr{nullptr}));
177-
}
178-
}
179-
BENCHMARK(bm_exception_ptr_move_copy_swap_null_optimized);
180-
181135
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)