mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-10 10:01:42 +00:00
57b08b0944
to reflect the new license. These used slightly different spellings that defeated my regular expressions. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351648
135 lines
4.5 KiB
C++
135 lines
4.5 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
#include "benchmark/benchmark.h"
|
|
#include "test_macros.h"
|
|
|
|
namespace internal {
|
|
|
|
template <class D, class E, size_t I>
|
|
struct EnumValue : std::integral_constant<E, static_cast<E>(I)> {
|
|
static std::string name() { return std::string("_") + D::Names[I]; }
|
|
};
|
|
|
|
template <class D, class E, size_t ...Idxs>
|
|
constexpr auto makeEnumValueTuple(std::index_sequence<Idxs...>) {
|
|
return std::make_tuple(EnumValue<D, E, Idxs>{}...);
|
|
}
|
|
|
|
template <class B>
|
|
static auto skip(const B& Bench, int) -> decltype(Bench.skip()) {
|
|
return Bench.skip();
|
|
}
|
|
template <class B>
|
|
static auto skip(const B& Bench, char) {
|
|
return false;
|
|
}
|
|
|
|
template <class B, class Args, size_t... Is>
|
|
void makeBenchmarkFromValuesImpl(const Args& A, std::index_sequence<Is...>) {
|
|
for (auto& V : A) {
|
|
B Bench{std::get<Is>(V)...};
|
|
if (!internal::skip(Bench, 0)) {
|
|
benchmark::RegisterBenchmark(Bench.name().c_str(),
|
|
[=](benchmark::State& S) { Bench.run(S); });
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class B, class... Args>
|
|
void makeBenchmarkFromValues(const std::vector<std::tuple<Args...> >& A) {
|
|
makeBenchmarkFromValuesImpl<B>(A, std::index_sequence_for<Args...>());
|
|
}
|
|
|
|
template <template <class...> class B, class Args, class... U>
|
|
void makeBenchmarkImpl(const Args& A, std::tuple<U...> t) {
|
|
makeBenchmarkFromValues<B<U...> >(A);
|
|
}
|
|
|
|
template <template <class...> class B, class Args, class... U,
|
|
class... T, class... Tuples>
|
|
void makeBenchmarkImpl(const Args& A, std::tuple<U...>, std::tuple<T...>,
|
|
Tuples... rest) {
|
|
(internal::makeBenchmarkImpl<B>(A, std::tuple<U..., T>(), rest...), ...);
|
|
}
|
|
|
|
template <class R, class T>
|
|
void allValueCombinations(R& Result, const T& Final) {
|
|
return Result.push_back(Final);
|
|
}
|
|
|
|
template <class R, class T, class V, class... Vs>
|
|
void allValueCombinations(R& Result, const T& Prev, const V& Value,
|
|
const Vs&... Values) {
|
|
for (const auto& E : Value) {
|
|
allValueCombinations(Result, std::tuple_cat(Prev, std::make_tuple(E)),
|
|
Values...);
|
|
}
|
|
}
|
|
|
|
} // namespace internal
|
|
|
|
// CRTP class that enables using enum types as a dimension for
|
|
// makeCartesianProductBenchmark below.
|
|
// The type passed to `B` will be a std::integral_constant<E, e>, with the
|
|
// additional static function `name()` that returns the stringified name of the
|
|
// label.
|
|
//
|
|
// Eg:
|
|
// enum class MyEnum { A, B };
|
|
// struct AllMyEnum : EnumValuesAsTuple<AllMyEnum, MyEnum, 2> {
|
|
// static constexpr absl::string_view Names[] = {"A", "B"};
|
|
// };
|
|
template <class Derived, class EnumType, size_t NumLabels>
|
|
using EnumValuesAsTuple =
|
|
decltype(internal::makeEnumValueTuple<Derived, EnumType>(
|
|
std::make_index_sequence<NumLabels>{}));
|
|
|
|
// Instantiates B<T0, T1, ..., TN> where <Ti...> are the combinations in the
|
|
// cartesian product of `Tuples...`, and pass (arg0, ..., argN) as constructor
|
|
// arguments where `(argi...)` are the combination in the cartesian product of
|
|
// the runtime values of `A...`.
|
|
// B<T...> requires:
|
|
// - std::string name(args...): The name of the benchmark.
|
|
// - void run(benchmark::State&, args...): The body of the benchmark.
|
|
// It can also optionally provide:
|
|
// - bool skip(args...): When `true`, skips the combination. Default is false.
|
|
//
|
|
// Returns int to facilitate registration. The return value is unspecified.
|
|
template <template <class...> class B, class... Tuples, class... Args>
|
|
int makeCartesianProductBenchmark(const Args&... A) {
|
|
std::vector<std::tuple<typename Args::value_type...> > V;
|
|
internal::allValueCombinations(V, std::tuple<>(), A...);
|
|
internal::makeBenchmarkImpl<B>(V, std::tuple<>(), Tuples()...);
|
|
return 0;
|
|
}
|
|
|
|
template <class B, class... Args>
|
|
int makeCartesianProductBenchmark(const Args&... A) {
|
|
std::vector<std::tuple<typename Args::value_type...> > V;
|
|
internal::allValueCombinations(V, std::tuple<>(), A...);
|
|
internal::makeBenchmarkFromValues<B>(V);
|
|
return 0;
|
|
}
|
|
|
|
// When `opaque` is true, this function hides the runtime state of `value` from
|
|
// the optimizer.
|
|
// It returns `value`.
|
|
template <class T>
|
|
TEST_ALWAYS_INLINE inline T maybeOpaque(T value, bool opaque) {
|
|
if (opaque) benchmark::DoNotOptimize(value);
|
|
return value;
|
|
}
|
|
|