@@ -18,4 +18,49 @@ void bm_make_exception_ptr(benchmark::State& state) {
1818}
1919BENCHMARK (bm_make_exception_ptr)->ThreadRange(1 , 8 );
2020
21+ static bool exception_ptr_moves_copies_swap (std::exception_ptr p1) {
22+ // Taken from https://github.com/llvm/llvm-project/issues/44892
23+ std::exception_ptr p2 (p1); // Copy constructor
24+ std::exception_ptr p3 (std::move (p2)); // Move constructor
25+ p2 = std::move (p1); // Move assignment
26+ p1 = p2; // Copy assignment
27+ swap (p1, p2); // Swap
28+ // Comparisons against nullptr. The overhead from creating temporary `exception_ptr`
29+ // instances should be optimized out.
30+ bool is_null = p1 == nullptr && nullptr == p2;
31+ bool is_equal = p1 == p2; // Comparison
32+ return is_null && is_equal;
33+ }
34+
35+ void bm_nonnull_exception_ptr (benchmark::State& state) {
36+ std::exception_ptr excptr = std::make_exception_ptr (42 );
37+ for (auto _ : state) {
38+ benchmark::DoNotOptimize (excptr);
39+ benchmark::DoNotOptimize (exception_ptr_moves_copies_swap (excptr));
40+ }
41+ }
42+ BENCHMARK (bm_nonnull_exception_ptr);
43+
44+ void bm_null_exception_ptr (benchmark::State& state) {
45+ std::exception_ptr excptr;
46+ for (auto _ : state) {
47+ // All of the `exception_ptr_noops` are no-ops but the optimizer
48+ // cannot optimize them away, because the `DoNotOptimize` calls
49+ // prevent the optimizer from doing so.
50+ benchmark::DoNotOptimize (excptr);
51+ benchmark::DoNotOptimize (exception_ptr_moves_copies_swap (excptr));
52+ }
53+ }
54+ BENCHMARK (bm_null_exception_ptr);
55+
56+ void bm_optimized_null_exception_ptr (benchmark::State& state) {
57+ for (auto _ : state) {
58+ // All of the `exception_ptr_noops` are no-ops because
59+ // the exception_ptr is empty. Hence, the compiler should
60+ // be able to optimize them very aggressively.
61+ benchmark::DoNotOptimize (exception_ptr_moves_copies_swap (std::exception_ptr{nullptr }));
62+ }
63+ }
64+ BENCHMARK (bm_optimized_null_exception_ptr);
65+
2166BENCHMARK_MAIN ();
0 commit comments