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