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 //===----------------------------------------------------------------------===//
12 #include <type_traits>
15 #include "benchmark/benchmark.h"
16 #include "test_macros.h"
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
]; }
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
>{}...);
31 static auto skip(const B
& Bench
, int) -> decltype(Bench
.skip()) {
35 static auto skip(const B
& Bench
, char) {
39 template <class B
, class Args
, size_t... Is
>
40 void makeBenchmarkFromValuesImpl(const Args
& A
, std::index_sequence
<Is
...>) {
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
); });
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
...>());
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
);
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
...>,
64 (internal::makeBenchmarkImpl
<B
>(A
, std::tuple
<U
..., T
>(), rest
...), ...);
67 template <class R
, class T
>
68 void allValueCombinations(R
& Result
, const T
& Final
) {
69 return Result
.push_back(Final
);
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
)),
81 } // namespace internal
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
90 // enum class MyEnum { A, B };
91 // struct AllMyEnum : EnumValuesAsTuple<AllMyEnum, MyEnum, 2> {
92 // static constexpr absl::string_view Names[] = {"A", "B"};
94 template <class Derived
, class EnumType
, size_t NumLabels
>
95 using EnumValuesAsTuple
=
96 decltype(internal::makeEnumValueTuple
<Derived
, EnumType
>(
97 std::make_index_sequence
<NumLabels
>{}));
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...`.
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.
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()...);
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
);
126 // When `opaque` is true, this function hides the runtime state of `value` from
128 // It returns `value`.
130 TEST_ALWAYS_INLINE
inline T
maybeOpaque(T value
, bool opaque
) {
131 if (opaque
) benchmark::DoNotOptimize(value
);