Mercurial > hg > CbC > CbC_llvm
comparison libcxx/benchmarks/CartesianBenchmarks.h @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 1f2b6ac9f198 |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 //===----------------------------------------------------------------------===// | |
2 // | |
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 | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 | |
9 | |
10 #include <string> | |
11 #include <tuple> | |
12 #include <type_traits> | |
13 #include <vector> | |
14 | |
15 #include "benchmark/benchmark.h" | |
16 #include "test_macros.h" | |
17 | |
18 namespace internal { | |
19 | |
20 template <class D, class E, size_t I> | |
21 struct EnumValue : std::integral_constant<E, static_cast<E>(I)> { | |
22 static std::string name() { return std::string("_") + D::Names[I]; } | |
23 }; | |
24 | |
25 template <class D, class E, size_t ...Idxs> | |
26 constexpr auto makeEnumValueTuple(std::index_sequence<Idxs...>) { | |
27 return std::make_tuple(EnumValue<D, E, Idxs>{}...); | |
28 } | |
29 | |
30 template <class B> | |
31 static auto skip(const B& Bench, int) -> decltype(Bench.skip()) { | |
32 return Bench.skip(); | |
33 } | |
34 template <class B> | |
35 static auto skip(const B& Bench, char) { | |
36 return false; | |
37 } | |
38 | |
39 template <class B, class Args, size_t... Is> | |
40 void makeBenchmarkFromValuesImpl(const Args& A, std::index_sequence<Is...>) { | |
41 for (auto& V : A) { | |
42 B Bench{std::get<Is>(V)...}; | |
43 if (!internal::skip(Bench, 0)) { | |
44 benchmark::RegisterBenchmark(Bench.name().c_str(), | |
45 [=](benchmark::State& S) { Bench.run(S); }); | |
46 } | |
47 } | |
48 } | |
49 | |
50 template <class B, class... Args> | |
51 void makeBenchmarkFromValues(const std::vector<std::tuple<Args...> >& A) { | |
52 makeBenchmarkFromValuesImpl<B>(A, std::index_sequence_for<Args...>()); | |
53 } | |
54 | |
55 template <template <class...> class B, class Args, class... U> | |
56 void makeBenchmarkImpl(const Args& A, std::tuple<U...> t) { | |
57 makeBenchmarkFromValues<B<U...> >(A); | |
58 } | |
59 | |
60 template <template <class...> class B, class Args, class... U, | |
61 class... T, class... Tuples> | |
62 void makeBenchmarkImpl(const Args& A, std::tuple<U...>, std::tuple<T...>, | |
63 Tuples... rest) { | |
64 (internal::makeBenchmarkImpl<B>(A, std::tuple<U..., T>(), rest...), ...); | |
65 } | |
66 | |
67 template <class R, class T> | |
68 void allValueCombinations(R& Result, const T& Final) { | |
69 return Result.push_back(Final); | |
70 } | |
71 | |
72 template <class R, class T, class V, class... Vs> | |
73 void allValueCombinations(R& Result, const T& Prev, const V& Value, | |
74 const Vs&... Values) { | |
75 for (const auto& E : Value) { | |
76 allValueCombinations(Result, std::tuple_cat(Prev, std::make_tuple(E)), | |
77 Values...); | |
78 } | |
79 } | |
80 | |
81 } // namespace internal | |
82 | |
83 // CRTP class that enables using enum types as a dimension for | |
84 // makeCartesianProductBenchmark below. | |
85 // The type passed to `B` will be a std::integral_constant<E, e>, with the | |
86 // additional static function `name()` that returns the stringified name of the | |
87 // label. | |
88 // | |
89 // Eg: | |
90 // enum class MyEnum { A, B }; | |
91 // struct AllMyEnum : EnumValuesAsTuple<AllMyEnum, MyEnum, 2> { | |
92 // static constexpr absl::string_view Names[] = {"A", "B"}; | |
93 // }; | |
94 template <class Derived, class EnumType, size_t NumLabels> | |
95 using EnumValuesAsTuple = | |
96 decltype(internal::makeEnumValueTuple<Derived, EnumType>( | |
97 std::make_index_sequence<NumLabels>{})); | |
98 | |
99 // Instantiates B<T0, T1, ..., TN> where <Ti...> are the combinations in the | |
100 // cartesian product of `Tuples...`, and pass (arg0, ..., argN) as constructor | |
101 // arguments where `(argi...)` are the combination in the cartesian product of | |
102 // the runtime values of `A...`. | |
103 // B<T...> requires: | |
104 // - std::string name(args...): The name of the benchmark. | |
105 // - void run(benchmark::State&, args...): The body of the benchmark. | |
106 // It can also optionally provide: | |
107 // - bool skip(args...): When `true`, skips the combination. Default is false. | |
108 // | |
109 // Returns int to facilitate registration. The return value is unspecified. | |
110 template <template <class...> class B, class... Tuples, class... Args> | |
111 int makeCartesianProductBenchmark(const Args&... A) { | |
112 std::vector<std::tuple<typename Args::value_type...> > V; | |
113 internal::allValueCombinations(V, std::tuple<>(), A...); | |
114 internal::makeBenchmarkImpl<B>(V, std::tuple<>(), Tuples()...); | |
115 return 0; | |
116 } | |
117 | |
118 template <class B, class... Args> | |
119 int makeCartesianProductBenchmark(const Args&... A) { | |
120 std::vector<std::tuple<typename Args::value_type...> > V; | |
121 internal::allValueCombinations(V, std::tuple<>(), A...); | |
122 internal::makeBenchmarkFromValues<B>(V); | |
123 return 0; | |
124 } | |
125 | |
126 // When `opaque` is true, this function hides the runtime state of `value` from | |
127 // the optimizer. | |
128 // It returns `value`. | |
129 template <class T> | |
130 TEST_ALWAYS_INLINE inline T maybeOpaque(T value, bool opaque) { | |
131 if (opaque) benchmark::DoNotOptimize(value); | |
132 return value; | |
133 } |