@@ -21,7 +21,6 @@ BENCHMARK(bm_make_exception_ptr)->ThreadRange(1, 8);
2121void 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);
3029void 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}
3738BENCHMARK (bm_exception_ptr_copy_ctor_null);
3839
39-
4040void 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);
5251void 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}
5960BENCHMARK (bm_exception_ptr_move_ctor_null);
6061
6162void 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);
7272void 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}
8182BENCHMARK (bm_exception_ptr_copy_assign_null);
8283
83-
8484void 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);
9897void 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}
107107BENCHMARK (bm_exception_ptr_move_assign_null);
108108
109109void 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}
118118BENCHMARK (bm_exception_ptr_swap_nonnull);
119119
120120void 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}
129133BENCHMARK (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-
181135BENCHMARK_MAIN ();
0 commit comments