xref: /aosp_15_r20/external/libcxx/benchmarks/function.bench.cpp (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
1*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2*58b9f456SAndroid Build Coastguard Worker //
3*58b9f456SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*58b9f456SAndroid Build Coastguard Worker //
5*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*58b9f456SAndroid Build Coastguard Worker //
8*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*58b9f456SAndroid Build Coastguard Worker 
10*58b9f456SAndroid Build Coastguard Worker #include <cstdint>
11*58b9f456SAndroid Build Coastguard Worker #include <functional>
12*58b9f456SAndroid Build Coastguard Worker #include <memory>
13*58b9f456SAndroid Build Coastguard Worker #include <string>
14*58b9f456SAndroid Build Coastguard Worker 
15*58b9f456SAndroid Build Coastguard Worker #include "CartesianBenchmarks.hpp"
16*58b9f456SAndroid Build Coastguard Worker #include "benchmark/benchmark.h"
17*58b9f456SAndroid Build Coastguard Worker #include "test_macros.h"
18*58b9f456SAndroid Build Coastguard Worker 
19*58b9f456SAndroid Build Coastguard Worker namespace {
20*58b9f456SAndroid Build Coastguard Worker 
21*58b9f456SAndroid Build Coastguard Worker enum class FunctionType {
22*58b9f456SAndroid Build Coastguard Worker   Null,
23*58b9f456SAndroid Build Coastguard Worker   FunctionPointer,
24*58b9f456SAndroid Build Coastguard Worker   MemberFunctionPointer,
25*58b9f456SAndroid Build Coastguard Worker   MemberPointer,
26*58b9f456SAndroid Build Coastguard Worker   SmallTrivialFunctor,
27*58b9f456SAndroid Build Coastguard Worker   SmallNonTrivialFunctor,
28*58b9f456SAndroid Build Coastguard Worker   LargeTrivialFunctor,
29*58b9f456SAndroid Build Coastguard Worker   LargeNonTrivialFunctor
30*58b9f456SAndroid Build Coastguard Worker };
31*58b9f456SAndroid Build Coastguard Worker 
32*58b9f456SAndroid Build Coastguard Worker struct AllFunctionTypes : EnumValuesAsTuple<AllFunctionTypes, FunctionType, 8> {
33*58b9f456SAndroid Build Coastguard Worker   static constexpr const char* Names[] = {"Null",
34*58b9f456SAndroid Build Coastguard Worker                                           "FuncPtr",
35*58b9f456SAndroid Build Coastguard Worker                                           "MemFuncPtr",
36*58b9f456SAndroid Build Coastguard Worker                                           "MemPtr",
37*58b9f456SAndroid Build Coastguard Worker                                           "SmallTrivialFunctor",
38*58b9f456SAndroid Build Coastguard Worker                                           "SmallNonTrivialFunctor",
39*58b9f456SAndroid Build Coastguard Worker                                           "LargeTrivialFunctor",
40*58b9f456SAndroid Build Coastguard Worker                                           "LargeNonTrivialFunctor"};
41*58b9f456SAndroid Build Coastguard Worker };
42*58b9f456SAndroid Build Coastguard Worker 
43*58b9f456SAndroid Build Coastguard Worker enum class Opacity { kOpaque, kTransparent };
44*58b9f456SAndroid Build Coastguard Worker 
45*58b9f456SAndroid Build Coastguard Worker struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {
46*58b9f456SAndroid Build Coastguard Worker   static constexpr const char* Names[] = {"Opaque", "Transparent"};
47*58b9f456SAndroid Build Coastguard Worker };
48*58b9f456SAndroid Build Coastguard Worker 
49*58b9f456SAndroid Build Coastguard Worker struct S {
function__anon681814120111::S50*58b9f456SAndroid Build Coastguard Worker   int function() const { return 0; }
51*58b9f456SAndroid Build Coastguard Worker   int field = 0;
52*58b9f456SAndroid Build Coastguard Worker };
53*58b9f456SAndroid Build Coastguard Worker 
FunctionWithS(const S *)54*58b9f456SAndroid Build Coastguard Worker int FunctionWithS(const S*) { return 0; }
55*58b9f456SAndroid Build Coastguard Worker 
56*58b9f456SAndroid Build Coastguard Worker struct SmallTrivialFunctor {
operator ()__anon681814120111::SmallTrivialFunctor57*58b9f456SAndroid Build Coastguard Worker   int operator()(const S*) const { return 0; }
58*58b9f456SAndroid Build Coastguard Worker };
59*58b9f456SAndroid Build Coastguard Worker struct SmallNonTrivialFunctor {
SmallNonTrivialFunctor__anon681814120111::SmallNonTrivialFunctor60*58b9f456SAndroid Build Coastguard Worker   SmallNonTrivialFunctor() {}
SmallNonTrivialFunctor__anon681814120111::SmallNonTrivialFunctor61*58b9f456SAndroid Build Coastguard Worker   SmallNonTrivialFunctor(const SmallNonTrivialFunctor&) {}
~SmallNonTrivialFunctor__anon681814120111::SmallNonTrivialFunctor62*58b9f456SAndroid Build Coastguard Worker   ~SmallNonTrivialFunctor() {}
operator ()__anon681814120111::SmallNonTrivialFunctor63*58b9f456SAndroid Build Coastguard Worker   int operator()(const S*) const { return 0; }
64*58b9f456SAndroid Build Coastguard Worker };
65*58b9f456SAndroid Build Coastguard Worker struct LargeTrivialFunctor {
LargeTrivialFunctor__anon681814120111::LargeTrivialFunctor66*58b9f456SAndroid Build Coastguard Worker   LargeTrivialFunctor() {
67*58b9f456SAndroid Build Coastguard Worker       // Do not spend time initializing the padding.
68*58b9f456SAndroid Build Coastguard Worker   }
69*58b9f456SAndroid Build Coastguard Worker   int padding[16];
operator ()__anon681814120111::LargeTrivialFunctor70*58b9f456SAndroid Build Coastguard Worker   int operator()(const S*) const { return 0; }
71*58b9f456SAndroid Build Coastguard Worker };
72*58b9f456SAndroid Build Coastguard Worker struct LargeNonTrivialFunctor {
73*58b9f456SAndroid Build Coastguard Worker   int padding[16];
LargeNonTrivialFunctor__anon681814120111::LargeNonTrivialFunctor74*58b9f456SAndroid Build Coastguard Worker   LargeNonTrivialFunctor() {
75*58b9f456SAndroid Build Coastguard Worker       // Do not spend time initializing the padding.
76*58b9f456SAndroid Build Coastguard Worker   }
LargeNonTrivialFunctor__anon681814120111::LargeNonTrivialFunctor77*58b9f456SAndroid Build Coastguard Worker   LargeNonTrivialFunctor(const LargeNonTrivialFunctor&) {}
~LargeNonTrivialFunctor__anon681814120111::LargeNonTrivialFunctor78*58b9f456SAndroid Build Coastguard Worker   ~LargeNonTrivialFunctor() {}
operator ()__anon681814120111::LargeNonTrivialFunctor79*58b9f456SAndroid Build Coastguard Worker   int operator()(const S*) const { return 0; }
80*58b9f456SAndroid Build Coastguard Worker };
81*58b9f456SAndroid Build Coastguard Worker 
82*58b9f456SAndroid Build Coastguard Worker using Function = std::function<int(const S*)>;
83*58b9f456SAndroid Build Coastguard Worker 
84*58b9f456SAndroid Build Coastguard Worker TEST_ALWAYS_INLINE
MakeFunction(FunctionType type,bool opaque=false)85*58b9f456SAndroid Build Coastguard Worker inline Function MakeFunction(FunctionType type, bool opaque = false) {
86*58b9f456SAndroid Build Coastguard Worker   switch (type) {
87*58b9f456SAndroid Build Coastguard Worker     case FunctionType::Null:
88*58b9f456SAndroid Build Coastguard Worker       return nullptr;
89*58b9f456SAndroid Build Coastguard Worker     case FunctionType::FunctionPointer:
90*58b9f456SAndroid Build Coastguard Worker       return maybeOpaque(FunctionWithS, opaque);
91*58b9f456SAndroid Build Coastguard Worker     case FunctionType::MemberFunctionPointer:
92*58b9f456SAndroid Build Coastguard Worker       return maybeOpaque(&S::function, opaque);
93*58b9f456SAndroid Build Coastguard Worker     case FunctionType::MemberPointer:
94*58b9f456SAndroid Build Coastguard Worker       return maybeOpaque(&S::field, opaque);
95*58b9f456SAndroid Build Coastguard Worker     case FunctionType::SmallTrivialFunctor:
96*58b9f456SAndroid Build Coastguard Worker       return maybeOpaque(SmallTrivialFunctor{}, opaque);
97*58b9f456SAndroid Build Coastguard Worker     case FunctionType::SmallNonTrivialFunctor:
98*58b9f456SAndroid Build Coastguard Worker       return maybeOpaque(SmallNonTrivialFunctor{}, opaque);
99*58b9f456SAndroid Build Coastguard Worker     case FunctionType::LargeTrivialFunctor:
100*58b9f456SAndroid Build Coastguard Worker       return maybeOpaque(LargeTrivialFunctor{}, opaque);
101*58b9f456SAndroid Build Coastguard Worker     case FunctionType::LargeNonTrivialFunctor:
102*58b9f456SAndroid Build Coastguard Worker       return maybeOpaque(LargeNonTrivialFunctor{}, opaque);
103*58b9f456SAndroid Build Coastguard Worker   }
104*58b9f456SAndroid Build Coastguard Worker }
105*58b9f456SAndroid Build Coastguard Worker 
106*58b9f456SAndroid Build Coastguard Worker template <class Opacity, class FunctionType>
107*58b9f456SAndroid Build Coastguard Worker struct ConstructAndDestroy {
run__anon681814120111::ConstructAndDestroy108*58b9f456SAndroid Build Coastguard Worker   static void run(benchmark::State& state) {
109*58b9f456SAndroid Build Coastguard Worker     for (auto _ : state) {
110*58b9f456SAndroid Build Coastguard Worker       if (Opacity() == ::Opacity::kOpaque) {
111*58b9f456SAndroid Build Coastguard Worker         benchmark::DoNotOptimize(MakeFunction(FunctionType(), true));
112*58b9f456SAndroid Build Coastguard Worker       } else {
113*58b9f456SAndroid Build Coastguard Worker         MakeFunction(FunctionType());
114*58b9f456SAndroid Build Coastguard Worker       }
115*58b9f456SAndroid Build Coastguard Worker     }
116*58b9f456SAndroid Build Coastguard Worker   }
117*58b9f456SAndroid Build Coastguard Worker 
name__anon681814120111::ConstructAndDestroy118*58b9f456SAndroid Build Coastguard Worker   static std::string name() {
119*58b9f456SAndroid Build Coastguard Worker     return "BM_ConstructAndDestroy" + FunctionType::name() + Opacity::name();
120*58b9f456SAndroid Build Coastguard Worker   }
121*58b9f456SAndroid Build Coastguard Worker };
122*58b9f456SAndroid Build Coastguard Worker 
123*58b9f456SAndroid Build Coastguard Worker template <class FunctionType>
124*58b9f456SAndroid Build Coastguard Worker struct Copy {
run__anon681814120111::Copy125*58b9f456SAndroid Build Coastguard Worker   static void run(benchmark::State& state) {
126*58b9f456SAndroid Build Coastguard Worker     auto value = MakeFunction(FunctionType());
127*58b9f456SAndroid Build Coastguard Worker     for (auto _ : state) {
128*58b9f456SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(value);
129*58b9f456SAndroid Build Coastguard Worker       auto copy = value;  // NOLINT
130*58b9f456SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(copy);
131*58b9f456SAndroid Build Coastguard Worker     }
132*58b9f456SAndroid Build Coastguard Worker   }
133*58b9f456SAndroid Build Coastguard Worker 
name__anon681814120111::Copy134*58b9f456SAndroid Build Coastguard Worker   static std::string name() { return "BM_Copy" + FunctionType::name(); }
135*58b9f456SAndroid Build Coastguard Worker };
136*58b9f456SAndroid Build Coastguard Worker 
137*58b9f456SAndroid Build Coastguard Worker template <class FunctionType>
138*58b9f456SAndroid Build Coastguard Worker struct Move {
run__anon681814120111::Move139*58b9f456SAndroid Build Coastguard Worker   static void run(benchmark::State& state) {
140*58b9f456SAndroid Build Coastguard Worker     Function values[2] = {MakeFunction(FunctionType())};
141*58b9f456SAndroid Build Coastguard Worker     int i = 0;
142*58b9f456SAndroid Build Coastguard Worker     for (auto _ : state) {
143*58b9f456SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(values);
144*58b9f456SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(values[i ^ 1] = std::move(values[i]));
145*58b9f456SAndroid Build Coastguard Worker       i ^= 1;
146*58b9f456SAndroid Build Coastguard Worker     }
147*58b9f456SAndroid Build Coastguard Worker   }
148*58b9f456SAndroid Build Coastguard Worker 
name__anon681814120111::Move149*58b9f456SAndroid Build Coastguard Worker   static std::string name() {
150*58b9f456SAndroid Build Coastguard Worker     return "BM_Move" + FunctionType::name();
151*58b9f456SAndroid Build Coastguard Worker   }
152*58b9f456SAndroid Build Coastguard Worker };
153*58b9f456SAndroid Build Coastguard Worker 
154*58b9f456SAndroid Build Coastguard Worker template <class Function1, class Function2>
155*58b9f456SAndroid Build Coastguard Worker struct Swap {
run__anon681814120111::Swap156*58b9f456SAndroid Build Coastguard Worker   static void run(benchmark::State& state) {
157*58b9f456SAndroid Build Coastguard Worker     Function values[2] = {MakeFunction(Function1()), MakeFunction(Function2())};
158*58b9f456SAndroid Build Coastguard Worker     for (auto _ : state) {
159*58b9f456SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(values);
160*58b9f456SAndroid Build Coastguard Worker       values[0].swap(values[1]);
161*58b9f456SAndroid Build Coastguard Worker     }
162*58b9f456SAndroid Build Coastguard Worker   }
163*58b9f456SAndroid Build Coastguard Worker 
skip__anon681814120111::Swap164*58b9f456SAndroid Build Coastguard Worker   static bool skip() { return Function1() > Function2(); }
165*58b9f456SAndroid Build Coastguard Worker 
name__anon681814120111::Swap166*58b9f456SAndroid Build Coastguard Worker   static std::string name() {
167*58b9f456SAndroid Build Coastguard Worker     return "BM_Swap" + Function1::name() + Function2::name();
168*58b9f456SAndroid Build Coastguard Worker   }
169*58b9f456SAndroid Build Coastguard Worker };
170*58b9f456SAndroid Build Coastguard Worker 
171*58b9f456SAndroid Build Coastguard Worker template <class FunctionType>
172*58b9f456SAndroid Build Coastguard Worker struct OperatorBool {
run__anon681814120111::OperatorBool173*58b9f456SAndroid Build Coastguard Worker   static void run(benchmark::State& state) {
174*58b9f456SAndroid Build Coastguard Worker     auto f = MakeFunction(FunctionType());
175*58b9f456SAndroid Build Coastguard Worker     for (auto _ : state) {
176*58b9f456SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(f);
177*58b9f456SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(static_cast<bool>(f));
178*58b9f456SAndroid Build Coastguard Worker     }
179*58b9f456SAndroid Build Coastguard Worker   }
180*58b9f456SAndroid Build Coastguard Worker 
name__anon681814120111::OperatorBool181*58b9f456SAndroid Build Coastguard Worker   static std::string name() { return "BM_OperatorBool" + FunctionType::name(); }
182*58b9f456SAndroid Build Coastguard Worker };
183*58b9f456SAndroid Build Coastguard Worker 
184*58b9f456SAndroid Build Coastguard Worker template <class FunctionType>
185*58b9f456SAndroid Build Coastguard Worker struct Invoke {
run__anon681814120111::Invoke186*58b9f456SAndroid Build Coastguard Worker   static void run(benchmark::State& state) {
187*58b9f456SAndroid Build Coastguard Worker     S s;
188*58b9f456SAndroid Build Coastguard Worker     const auto value = MakeFunction(FunctionType());
189*58b9f456SAndroid Build Coastguard Worker     for (auto _ : state) {
190*58b9f456SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(value);
191*58b9f456SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(value(&s));
192*58b9f456SAndroid Build Coastguard Worker     }
193*58b9f456SAndroid Build Coastguard Worker   }
194*58b9f456SAndroid Build Coastguard Worker 
skip__anon681814120111::Invoke195*58b9f456SAndroid Build Coastguard Worker   static bool skip() { return FunctionType() == ::FunctionType::Null; }
196*58b9f456SAndroid Build Coastguard Worker 
name__anon681814120111::Invoke197*58b9f456SAndroid Build Coastguard Worker   static std::string name() { return "BM_Invoke" + FunctionType::name(); }
198*58b9f456SAndroid Build Coastguard Worker };
199*58b9f456SAndroid Build Coastguard Worker 
200*58b9f456SAndroid Build Coastguard Worker template <class FunctionType>
201*58b9f456SAndroid Build Coastguard Worker struct InvokeInlined {
run__anon681814120111::InvokeInlined202*58b9f456SAndroid Build Coastguard Worker   static void run(benchmark::State& state) {
203*58b9f456SAndroid Build Coastguard Worker     S s;
204*58b9f456SAndroid Build Coastguard Worker     for (auto _ : state) {
205*58b9f456SAndroid Build Coastguard Worker       MakeFunction(FunctionType())(&s);
206*58b9f456SAndroid Build Coastguard Worker     }
207*58b9f456SAndroid Build Coastguard Worker   }
208*58b9f456SAndroid Build Coastguard Worker 
skip__anon681814120111::InvokeInlined209*58b9f456SAndroid Build Coastguard Worker   static bool skip() { return FunctionType() == ::FunctionType::Null; }
210*58b9f456SAndroid Build Coastguard Worker 
name__anon681814120111::InvokeInlined211*58b9f456SAndroid Build Coastguard Worker   static std::string name() {
212*58b9f456SAndroid Build Coastguard Worker     return "BM_InvokeInlined" + FunctionType::name();
213*58b9f456SAndroid Build Coastguard Worker   }
214*58b9f456SAndroid Build Coastguard Worker };
215*58b9f456SAndroid Build Coastguard Worker 
216*58b9f456SAndroid Build Coastguard Worker }  // namespace
217*58b9f456SAndroid Build Coastguard Worker 
main(int argc,char ** argv)218*58b9f456SAndroid Build Coastguard Worker int main(int argc, char** argv) {
219*58b9f456SAndroid Build Coastguard Worker   benchmark::Initialize(&argc, argv);
220*58b9f456SAndroid Build Coastguard Worker   if (benchmark::ReportUnrecognizedArguments(argc, argv))
221*58b9f456SAndroid Build Coastguard Worker     return 1;
222*58b9f456SAndroid Build Coastguard Worker 
223*58b9f456SAndroid Build Coastguard Worker   makeCartesianProductBenchmark<ConstructAndDestroy, AllOpacity,
224*58b9f456SAndroid Build Coastguard Worker                                 AllFunctionTypes>();
225*58b9f456SAndroid Build Coastguard Worker   makeCartesianProductBenchmark<Copy, AllFunctionTypes>();
226*58b9f456SAndroid Build Coastguard Worker   makeCartesianProductBenchmark<Move, AllFunctionTypes>();
227*58b9f456SAndroid Build Coastguard Worker   makeCartesianProductBenchmark<Swap, AllFunctionTypes, AllFunctionTypes>();
228*58b9f456SAndroid Build Coastguard Worker   makeCartesianProductBenchmark<OperatorBool, AllFunctionTypes>();
229*58b9f456SAndroid Build Coastguard Worker   makeCartesianProductBenchmark<Invoke, AllFunctionTypes>();
230*58b9f456SAndroid Build Coastguard Worker   makeCartesianProductBenchmark<InvokeInlined, AllFunctionTypes>();
231*58b9f456SAndroid Build Coastguard Worker   benchmark::RunSpecifiedBenchmarks();
232*58b9f456SAndroid Build Coastguard Worker }
233