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 <type_traits>
14 #include "benchmark/benchmark.h"
15 #include "test_macros.h"
19 template <class D
, class E
, size_t I
>
20 struct EnumValue
: std::integral_constant
<E
, static_cast<E
>(I
)> {
21 static std::string
name() { return std::string("_") + D::Names
[I
]; }
24 template <class D
, class E
, size_t... Idxs
>
25 constexpr auto makeEnumValueTuple(std::index_sequence
<Idxs
...>) {
26 return std::make_tuple(EnumValue
<D
, E
, Idxs
>{}...);
30 static auto skip(const B
& Bench
, int) -> decltype(Bench
.skip()) {
34 static auto skip(const B
& Bench
, char) {
38 template <class B
, class Args
, size_t... Is
>
39 void makeBenchmarkFromValuesImpl(const Args
& A
, std::index_sequence
<Is
...>) {
41 B Bench
{std::get
<Is
>(V
)...};
42 if (!internal::skip(Bench
, 0)) {
43 benchmark::RegisterBenchmark(Bench
.name().c_str(), [=](benchmark::State
& S
) { Bench
.run(S
); });
48 template <class B
, class... Args
>
49 void makeBenchmarkFromValues(const std::vector
<std::tuple
<Args
...> >& A
) {
50 makeBenchmarkFromValuesImpl
<B
>(A
, std::index_sequence_for
<Args
...>());
53 template <template <class...> class B
, class Args
, class... U
>
54 void makeBenchmarkImpl(const Args
& A
, std::tuple
<U
...> t
) {
55 makeBenchmarkFromValues
<B
<U
...> >(A
);
58 template <template <class...> class B
, class Args
, class... U
, class... T
, class... Tuples
>
59 void makeBenchmarkImpl(const Args
& A
, std::tuple
<U
...>, std::tuple
<T
...>, Tuples
... rest
) {
60 (internal::makeBenchmarkImpl
<B
>(A
, std::tuple
<U
..., T
>(), rest
...), ...);
63 template <class R
, class T
>
64 void allValueCombinations(R
& Result
, const T
& Final
) {
65 return Result
.push_back(Final
);
68 template <class R
, class T
, class V
, class... Vs
>
69 void allValueCombinations(R
& Result
, const T
& Prev
, const V
& Value
, const Vs
&... Values
) {
70 for (const auto& E
: Value
) {
71 allValueCombinations(Result
, std::tuple_cat(Prev
, std::make_tuple(E
)), Values
...);
75 } // namespace internal
77 // CRTP class that enables using enum types as a dimension for
78 // makeCartesianProductBenchmark below.
79 // The type passed to `B` will be a std::integral_constant<E, e>, with the
80 // additional static function `name()` that returns the stringified name of the
84 // enum class MyEnum { A, B };
85 // struct AllMyEnum : EnumValuesAsTuple<AllMyEnum, MyEnum, 2> {
86 // static constexpr absl::string_view Names[] = {"A", "B"};
88 template <class Derived
, class EnumType
, size_t NumLabels
>
89 using EnumValuesAsTuple
=
90 decltype(internal::makeEnumValueTuple
<Derived
, EnumType
>(std::make_index_sequence
<NumLabels
>{}));
92 // Instantiates B<T0, T1, ..., TN> where <Ti...> are the combinations in the
93 // cartesian product of `Tuples...`, and pass (arg0, ..., argN) as constructor
94 // arguments where `(argi...)` are the combination in the cartesian product of
95 // the runtime values of `A...`.
97 // - std::string name(args...): The name of the benchmark.
98 // - void run(benchmark::State&, args...): The body of the benchmark.
99 // It can also optionally provide:
100 // - bool skip(args...): When `true`, skips the combination. Default is false.
102 // Returns int to facilitate registration. The return value is unspecified.
103 template <template <class...> class B
, class... Tuples
, class... Args
>
104 int makeCartesianProductBenchmark(const Args
&... A
) {
105 std::vector
<std::tuple
<typename
Args::value_type
...> > V
;
106 internal::allValueCombinations(V
, std::tuple
<>(), A
...);
107 internal::makeBenchmarkImpl
<B
>(V
, std::tuple
<>(), Tuples()...);
111 template <class B
, class... Args
>
112 int makeCartesianProductBenchmark(const Args
&... A
) {
113 std::vector
<std::tuple
<typename
Args::value_type
...> > V
;
114 internal::allValueCombinations(V
, std::tuple
<>(), A
...);
115 internal::makeBenchmarkFromValues
<B
>(V
);
119 // When `opaque` is true, this function hides the runtime state of `value` from
121 // It returns `value`.
123 TEST_ALWAYS_INLINE
inline T
maybeOpaque(T value
, bool opaque
) {
125 benchmark::DoNotOptimize(value
);