1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 #include "benchmark/benchmark.h"
13 template <std::size_t Depth
>
14 struct Chain
: Chain
<Depth
- 1> {};
18 virtual ~Chain() noexcept
= default;
21 template <std::size_t Index
, std::size_t Depth
>
22 struct Dag
: Dag
<Index
, Depth
- 1>, Dag
<Index
+ 1, Depth
- 1> {};
24 template <std::size_t Index
>
25 struct Dag
<Index
, 0> {
26 virtual ~Dag() noexcept
= default;
29 template <std::size_t Depth
>
30 struct VChain
: virtual VChain
<Depth
- 1> {};
34 virtual ~VChain() noexcept
= default;
37 template <std::size_t Index
, std::size_t Depth
>
38 struct VDag
: virtual VDag
<Index
, Depth
- 1>, virtual VDag
<Index
+ 1, Depth
- 1> {};
40 template <std::size_t Index
>
41 struct VDag
<Index
, 0> {
42 virtual ~VDag() noexcept
= default;
45 template <typename Dyn
, typename From
, typename To
= Dyn
>
46 static void DynCast(benchmark::State
& state
) {
48 From
* from_ptr
= &obj
;
49 for (auto _
: state
) {
50 To
* to_ptr
= dynamic_cast<To
*>(from_ptr
);
51 benchmark::DoNotOptimize(to_ptr
);
55 static void StaticCast(benchmark::State
& state
) {
57 Chain
<0>* from_ptr
= &obj
;
58 for (auto _
: state
) {
59 Chain
<9>* to_ptr
= static_cast<Chain
<9>*>(from_ptr
);
60 benchmark::DoNotOptimize(to_ptr
);
64 // Downcast along a chain from base to the most derived type
65 BENCHMARK(DynCast
<Chain
<1>, Chain
<0>>)->Name("Chain, 1 level");
66 BENCHMARK(DynCast
<Chain
<2>, Chain
<0>>)->Name("Chain, 2 levels");
67 BENCHMARK(DynCast
<Chain
<3>, Chain
<0>>)->Name("Chain, 3 levels");
68 BENCHMARK(DynCast
<Chain
<4>, Chain
<0>>)->Name("Chain, 4 levels");
69 BENCHMARK(DynCast
<Chain
<5>, Chain
<0>>)->Name("Chain, 5 levels");
70 BENCHMARK(DynCast
<Chain
<6>, Chain
<0>>)->Name("Chain, 6 levels");
71 BENCHMARK(DynCast
<Chain
<7>, Chain
<0>>)->Name("Chain, 7 levels");
72 BENCHMARK(DynCast
<Chain
<8>, Chain
<0>>)->Name("Chain, 8 levels");
73 BENCHMARK(DynCast
<Chain
<9>, Chain
<0>>)->Name("Chain, 9 levels");
75 // Downcast along a chain from base to the middle of the chain
76 BENCHMARK(DynCast
<Chain
<2>, Chain
<0>, Chain
<1>>)->Name("Chain middle, 1 level");
77 BENCHMARK(DynCast
<Chain
<4>, Chain
<0>, Chain
<2>>)->Name("Chain middle, 2 levels");
78 BENCHMARK(DynCast
<Chain
<6>, Chain
<0>, Chain
<3>>)->Name("Chain middle, 3 levels");
79 BENCHMARK(DynCast
<Chain
<8>, Chain
<0>, Chain
<4>>)->Name("Chain middle, 4 levels");
81 // Downcast along a chain that fails
82 BENCHMARK(DynCast
<Chain
<1>, Chain
<0>, Chain
<9>>)->Name("Chain fail, 1 level");
83 BENCHMARK(DynCast
<Chain
<2>, Chain
<0>, Chain
<9>>)->Name("Chain fail, 2 levels");
84 BENCHMARK(DynCast
<Chain
<3>, Chain
<0>, Chain
<9>>)->Name("Chain fail, 3 levels");
85 BENCHMARK(DynCast
<Chain
<4>, Chain
<0>, Chain
<9>>)->Name("Chain fail, 4 levels");
86 BENCHMARK(DynCast
<Chain
<5>, Chain
<0>, Chain
<9>>)->Name("Chain fail, 5 levels");
87 BENCHMARK(DynCast
<Chain
<6>, Chain
<0>, Chain
<9>>)->Name("Chain fail, 6 levels");
88 BENCHMARK(DynCast
<Chain
<7>, Chain
<0>, Chain
<9>>)->Name("Chain fail, 7 levels");
89 BENCHMARK(DynCast
<Chain
<8>, Chain
<0>, Chain
<9>>)->Name("Chain fail, 8 levels");
91 // Downcast along a virtual inheritance chain from base to the most derived type
92 BENCHMARK(DynCast
<VChain
<1>, VChain
<0>>)->Name("VChain, 1 level");
93 BENCHMARK(DynCast
<VChain
<2>, VChain
<0>>)->Name("VChain, 2 levels");
94 BENCHMARK(DynCast
<VChain
<3>, VChain
<0>>)->Name("VChain, 3 levels");
95 BENCHMARK(DynCast
<VChain
<4>, VChain
<0>>)->Name("VChain, 4 levels");
96 BENCHMARK(DynCast
<VChain
<5>, VChain
<0>>)->Name("VChain, 5 levels");
98 // Downcast along a virtual inheritance chain from base to the middle of the chain
99 BENCHMARK(DynCast
<VChain
<2>, VChain
<0>, VChain
<1>>)->Name("VChain middle, 1 level");
100 BENCHMARK(DynCast
<VChain
<4>, VChain
<0>, VChain
<2>>)->Name("VChain middle, 2 levels");
101 BENCHMARK(DynCast
<VChain
<6>, VChain
<0>, VChain
<3>>)->Name("VChain middle, 3 levels");
102 BENCHMARK(DynCast
<VChain
<8>, VChain
<0>, VChain
<4>>)->Name("VChain middle, 4 levels");
104 // Downcast along a virtual chain that fails
105 BENCHMARK(DynCast
<VChain
<1>, VChain
<0>, VChain
<8>>)->Name("VChain fail, 1 level");
106 BENCHMARK(DynCast
<VChain
<2>, VChain
<0>, VChain
<8>>)->Name("VChain fail, 2 levels");
107 BENCHMARK(DynCast
<VChain
<3>, VChain
<0>, VChain
<8>>)->Name("VChain fail, 3 levels");
108 BENCHMARK(DynCast
<VChain
<4>, VChain
<0>, VChain
<8>>)->Name("VChain fail, 4 levels");
109 BENCHMARK(DynCast
<VChain
<5>, VChain
<0>, VChain
<8>>)->Name("VChain fail, 5 levels");
111 // Downcast along a DAG from base to the most derived type
112 BENCHMARK(DynCast
<Dag
<0, 3>, Dag
<3, 0>>)->Name("DAG rightmost, 3 levels");
113 BENCHMARK(DynCast
<Dag
<0, 4>, Dag
<4, 0>>)->Name("DAG rightmost, 4 levels");
114 BENCHMARK(DynCast
<Dag
<0, 5>, Dag
<5, 0>>)->Name("DAG rightmost, 5 levels");
115 BENCHMARK(DynCast
<Dag
<0, 3>, Dag
<0, 0>>)->Name("DAG leftmost, 3 levels");
116 BENCHMARK(DynCast
<Dag
<0, 4>, Dag
<0, 0>>)->Name("DAG leftmost, 4 levels");
117 BENCHMARK(DynCast
<Dag
<0, 5>, Dag
<0, 0>>)->Name("DAG leftmost, 5 levels");
119 // Downcast along a DAG from base to the middle of the DAG
120 BENCHMARK(DynCast
<Dag
<0, 4>, Dag
<4, 0>, Dag
<3, 1>>)->Name("DAG rightmost middle, 1 level");
121 BENCHMARK(DynCast
<Dag
<0, 4>, Dag
<4, 0>, Dag
<2, 2>>)->Name("DAG rightmost middle, 2 levels");
122 BENCHMARK(DynCast
<Dag
<0, 4>, Dag
<4, 0>, Dag
<1, 3>>)->Name("DAG rightmost middle, 3 levels");
123 BENCHMARK(DynCast
<Dag
<0, 4>, Dag
<0, 0>, Dag
<0, 1>>)->Name("DAG leftmost middle, 1 level");
124 BENCHMARK(DynCast
<Dag
<0, 4>, Dag
<0, 0>, Dag
<0, 2>>)->Name("DAG leftmost middle, 2 levels");
125 BENCHMARK(DynCast
<Dag
<0, 4>, Dag
<0, 0>, Dag
<0, 3>>)->Name("DAG leftmost middle, 3 levels");
127 // Sidecast along a DAG
128 BENCHMARK(DynCast
<Dag
<0, 3>, Dag
<3, 0>, Dag
<0, 0>>)->Name("DAG sidecast, 3 levels");
129 BENCHMARK(DynCast
<Dag
<0, 3>, Dag
<2, 1>, Dag
<0, 1>>)->Name("DAG sidecast, 2 levels");
130 BENCHMARK(DynCast
<Dag
<0, 3>, Dag
<1, 2>, Dag
<0, 2>>)->Name("DAG sidecast, 1 level");
132 // Sidecast along a DAG that fails
133 BENCHMARK(DynCast
<Dag
<0, 3>, Dag
<3, 0>, Dag
<0, 4>>)->Name("DAG sidecast fail, 3 levels");
134 BENCHMARK(DynCast
<Dag
<0, 3>, Dag
<2, 1>, Dag
<0, 4>>)->Name("DAG sidecast fail, 2 levels");
135 BENCHMARK(DynCast
<Dag
<0, 3>, Dag
<1, 2>, Dag
<0, 4>>)->Name("DAG sidecast fail, 1 level");
137 // Downcast along a virtual inheritance DAG from base to the most derived type
138 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<3, 0>>)->Name("VDAG rightmost, 3 levels");
139 BENCHMARK(DynCast
<VDag
<0, 4>, VDag
<4, 0>>)->Name("VDAG rightmost, 4 levels");
140 BENCHMARK(DynCast
<VDag
<0, 5>, VDag
<5, 0>>)->Name("VDAG rightmost, 5 levels");
141 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<0, 0>>)->Name("VDAG leftmost, 3 levels");
142 BENCHMARK(DynCast
<VDag
<0, 4>, VDag
<0, 0>>)->Name("VDAG leftmost, 4 levels");
143 BENCHMARK(DynCast
<VDag
<0, 5>, VDag
<0, 0>>)->Name("VDAG leftmost, 5 levels");
145 // Downcast along a virtual inheritance DAG from base to the middle of the DAG
146 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<3, 0>, VDag
<2, 1>>)->Name("VDAG rightmost middle, 1 level");
147 BENCHMARK(DynCast
<VDag
<0, 4>, VDag
<4, 0>, VDag
<2, 2>>)->Name("VDAG rightmost middle, 2 levels");
148 BENCHMARK(DynCast
<VDag
<0, 5>, VDag
<5, 0>, VDag
<2, 3>>)->Name("VDAG rightmost middle, 3 levels");
149 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<0, 0>, VDag
<0, 1>>)->Name("VDAG leftmost middle, 1 level");
150 BENCHMARK(DynCast
<VDag
<0, 4>, VDag
<0, 0>, VDag
<0, 2>>)->Name("VDAG leftmost middle, 2 levels");
151 BENCHMARK(DynCast
<VDag
<0, 5>, VDag
<0, 0>, VDag
<0, 3>>)->Name("VDAG leftmost middle, 3 levels");
153 // Sidecast along a virtual inheritance DAG
154 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<3, 0>, VDag
<0, 0>>)->Name("VDAG sidecast, 3 levels");
155 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<2, 1>, VDag
<0, 1>>)->Name("VDAG sidecast, 2 levels");
156 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<1, 2>, VDag
<0, 2>>)->Name("VDAG sidecast, 1 level");
158 // Sidecast along a virtual inheritance DAG that fails
159 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<3, 0>, VDag
<0, 4>>)->Name("VDAG sidecast fail, 3 levels");
160 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<2, 1>, VDag
<0, 4>>)->Name("VDAG sidecast fail, 2 levels");
161 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<1, 2>, VDag
<0, 4>>)->Name("VDAG sidecast fail, 1 level");
163 // Cast to complete object pointer
164 BENCHMARK(DynCast
<Chain
<8>, Chain
<0>, void>)->Name("Chain to complete");
165 BENCHMARK(DynCast
<VChain
<5>, VChain
<0>, void>)->Name("VChain to complete");
166 BENCHMARK(DynCast
<Dag
<0, 3>, Dag
<3, 0>, void>)->Name("DAG to complete");
167 BENCHMARK(DynCast
<VDag
<0, 3>, VDag
<3, 0>, void>)->Name("VDAG to complete");
169 // Static cast as the baseline.
170 BENCHMARK(StaticCast
)->Name("Static");