brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.4 KiB · e607162 Raw
228 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 11#include <cstdint>12#include <functional>13#include <memory>14#include <string>15#include <utility>16 17#include "CartesianBenchmarks.h"18#include "benchmark/benchmark.h"19#include "test_macros.h"20 21namespace {22 23enum class FunctionType {24  Null,25  FunctionPointer,26  MemberFunctionPointer,27  MemberPointer,28  SmallTrivialFunctor,29  SmallNonTrivialFunctor,30  LargeTrivialFunctor,31  LargeNonTrivialFunctor32};33 34struct AllFunctionTypes : EnumValuesAsTuple<AllFunctionTypes, FunctionType, 8> {35  static constexpr const char* Names[] = {36      "Null",37      "FuncPtr",38      "MemFuncPtr",39      "MemPtr",40      "SmallTrivialFunctor",41      "SmallNonTrivialFunctor",42      "LargeTrivialFunctor",43      "LargeNonTrivialFunctor"};44};45 46enum class Opacity { kOpaque, kTransparent };47 48struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {49  static constexpr const char* Names[] = {"Opaque", "Transparent"};50};51 52struct S {53  int function() const { return 0; }54  int field = 0;55};56 57int FunctionWithS(const S*) { return 0; }58 59struct SmallTrivialFunctor {60  int operator()(const S*) const { return 0; }61};62struct SmallNonTrivialFunctor {63  SmallNonTrivialFunctor() {}64  SmallNonTrivialFunctor(const SmallNonTrivialFunctor&) {}65  ~SmallNonTrivialFunctor() {}66  int operator()(const S*) const { return 0; }67};68struct LargeTrivialFunctor {69  LargeTrivialFunctor() {70    // Do not spend time initializing the padding.71  }72  int padding[16];73  int operator()(const S*) const { return 0; }74};75struct LargeNonTrivialFunctor {76  int padding[16];77  LargeNonTrivialFunctor() {78    // Do not spend time initializing the padding.79  }80  LargeNonTrivialFunctor(const LargeNonTrivialFunctor&) {}81  ~LargeNonTrivialFunctor() {}82  int operator()(const S*) const { return 0; }83};84 85using Function = std::function<int(const S*)>;86 87TEST_ALWAYS_INLINE88inline Function MakeFunction(FunctionType type, bool opaque = false) {89  switch (type) {90  case FunctionType::Null:91    return nullptr;92  case FunctionType::FunctionPointer:93    return maybeOpaque(FunctionWithS, opaque);94  case FunctionType::MemberFunctionPointer:95    return maybeOpaque(&S::function, opaque);96  case FunctionType::MemberPointer:97    return maybeOpaque(&S::field, opaque);98  case FunctionType::SmallTrivialFunctor:99    return maybeOpaque(SmallTrivialFunctor{}, opaque);100  case FunctionType::SmallNonTrivialFunctor:101    return maybeOpaque(SmallNonTrivialFunctor{}, opaque);102  case FunctionType::LargeTrivialFunctor:103    return maybeOpaque(LargeTrivialFunctor{}, opaque);104  case FunctionType::LargeNonTrivialFunctor:105    return maybeOpaque(LargeNonTrivialFunctor{}, opaque);106  }107  std::unreachable();108}109 110template <class Opacity, class FunctionType>111struct ConstructAndDestroy {112  static void run(benchmark::State& state) {113    for (auto _ : state) {114      if (Opacity() == ::Opacity::kOpaque) {115        benchmark::DoNotOptimize(MakeFunction(FunctionType(), true));116      } else {117        MakeFunction(FunctionType());118      }119    }120  }121 122  static std::string name() { return "BM_ConstructAndDestroy" + FunctionType::name() + Opacity::name(); }123};124 125template <class FunctionType>126struct Copy {127  static void run(benchmark::State& state) {128    auto value = MakeFunction(FunctionType());129    for (auto _ : state) {130      benchmark::DoNotOptimize(value);131      auto copy = value; // NOLINT132      benchmark::DoNotOptimize(copy);133    }134  }135 136  static std::string name() { return "BM_Copy" + FunctionType::name(); }137};138 139template <class FunctionType>140struct Move {141  static void run(benchmark::State& state) {142    Function values[2] = {MakeFunction(FunctionType())};143    int i              = 0;144    for (auto _ : state) {145      benchmark::DoNotOptimize(values);146      benchmark::DoNotOptimize(values[i ^ 1] = std::move(values[i]));147      i ^= 1;148    }149  }150 151  static std::string name() { return "BM_Move" + FunctionType::name(); }152};153 154template <class Function1, class Function2>155struct Swap {156  static void run(benchmark::State& state) {157    Function values[2] = {MakeFunction(Function1()), MakeFunction(Function2())};158    for (auto _ : state) {159      benchmark::DoNotOptimize(values);160      values[0].swap(values[1]);161    }162  }163 164  static bool skip() { return Function1() > Function2(); }165 166  static std::string name() { return "BM_Swap" + Function1::name() + Function2::name(); }167};168 169template <class FunctionType>170struct OperatorBool {171  static void run(benchmark::State& state) {172    auto f = MakeFunction(FunctionType());173    for (auto _ : state) {174      benchmark::DoNotOptimize(f);175      benchmark::DoNotOptimize(static_cast<bool>(f));176    }177  }178 179  static std::string name() { return "BM_OperatorBool" + FunctionType::name(); }180};181 182template <class FunctionType>183struct Invoke {184  static void run(benchmark::State& state) {185    S s;186    auto value = MakeFunction(FunctionType());187    for (auto _ : state) {188      benchmark::DoNotOptimize(value);189      benchmark::DoNotOptimize(value(&s));190    }191  }192 193  static bool skip() { return FunctionType() == ::FunctionType::Null; }194 195  static std::string name() { return "BM_Invoke" + FunctionType::name(); }196};197 198template <class FunctionType>199struct InvokeInlined {200  static void run(benchmark::State& state) {201    S s;202    for (auto _ : state) {203      MakeFunction(FunctionType())(&s);204    }205  }206 207  static bool skip() { return FunctionType() == ::FunctionType::Null; }208 209  static std::string name() { return "BM_InvokeInlined" + FunctionType::name(); }210};211 212} // namespace213 214int main(int argc, char** argv) {215  benchmark::Initialize(&argc, argv);216  if (benchmark::ReportUnrecognizedArguments(argc, argv))217    return 1;218 219  makeCartesianProductBenchmark<ConstructAndDestroy, AllOpacity, AllFunctionTypes>();220  makeCartesianProductBenchmark<Copy, AllFunctionTypes>();221  makeCartesianProductBenchmark<Move, AllFunctionTypes>();222  makeCartesianProductBenchmark<Swap, AllFunctionTypes, AllFunctionTypes>();223  makeCartesianProductBenchmark<OperatorBool, AllFunctionTypes>();224  makeCartesianProductBenchmark<Invoke, AllFunctionTypes>();225  makeCartesianProductBenchmark<InvokeInlined, AllFunctionTypes>();226  benchmark::RunSpecifiedBenchmarks();227}228