1438f7fc0SSiva Chandra Reddy //===-- Benchmark function --------------------------------------*- C++ -*-===// 2438f7fc0SSiva Chandra Reddy // 3438f7fc0SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4438f7fc0SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 5438f7fc0SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6438f7fc0SSiva Chandra Reddy // 7438f7fc0SSiva Chandra Reddy //===----------------------------------------------------------------------===// 8438f7fc0SSiva Chandra Reddy 9438f7fc0SSiva Chandra Reddy // This file mainly defines a `Benchmark` function. 10438f7fc0SSiva Chandra Reddy // 11438f7fc0SSiva Chandra Reddy // The benchmarking process is as follows: 12438f7fc0SSiva Chandra Reddy // - We start by measuring the time it takes to run the function 13438f7fc0SSiva Chandra Reddy // `InitialIterations` times. This is called a Sample. From this we can derive 14438f7fc0SSiva Chandra Reddy // the time it took to run a single iteration. 15438f7fc0SSiva Chandra Reddy // 16438f7fc0SSiva Chandra Reddy // - We repeat the previous step with a greater number of iterations to lower 17438f7fc0SSiva Chandra Reddy // the impact of the measurement. We can derive a more precise estimation of the 18438f7fc0SSiva Chandra Reddy // runtime for a single iteration. 19438f7fc0SSiva Chandra Reddy // 20438f7fc0SSiva Chandra Reddy // - Each sample gives a more accurate estimation of the runtime for a single 21438f7fc0SSiva Chandra Reddy // iteration but also takes more time to run. We stop the process when: 22438f7fc0SSiva Chandra Reddy // * The measure stabilize under a certain precision (Epsilon), 23438f7fc0SSiva Chandra Reddy // * The overall benchmarking time is greater than MaxDuration, 24438f7fc0SSiva Chandra Reddy // * The overall sample count is greater than MaxSamples, 25438f7fc0SSiva Chandra Reddy // * The last sample used more than MaxIterations iterations. 26438f7fc0SSiva Chandra Reddy // 27438f7fc0SSiva Chandra Reddy // - We also makes sure that the benchmark doesn't run for a too short period of 28438f7fc0SSiva Chandra Reddy // time by defining MinDuration and MinSamples. 29438f7fc0SSiva Chandra Reddy 30438f7fc0SSiva Chandra Reddy #ifndef LLVM_LIBC_UTILS_BENCHMARK_BENCHMARK_H 31438f7fc0SSiva Chandra Reddy #define LLVM_LIBC_UTILS_BENCHMARK_BENCHMARK_H 32438f7fc0SSiva Chandra Reddy 33438f7fc0SSiva Chandra Reddy #include "benchmark/benchmark.h" 34438f7fc0SSiva Chandra Reddy #include "llvm/ADT/ArrayRef.h" 35438f7fc0SSiva Chandra Reddy #include "llvm/ADT/SmallVector.h" 36438f7fc0SSiva Chandra Reddy #include <array> 37438f7fc0SSiva Chandra Reddy #include <chrono> 38c2ab3d2cSSimon Pilgrim #include <cmath> 39438f7fc0SSiva Chandra Reddy #include <cstdint> 40b5516be0SKazu Hirata #include <optional> 41438f7fc0SSiva Chandra Reddy 42438f7fc0SSiva Chandra Reddy namespace llvm { 43438f7fc0SSiva Chandra Reddy namespace libc_benchmarks { 44438f7fc0SSiva Chandra Reddy 45438f7fc0SSiva Chandra Reddy using Duration = std::chrono::duration<double>; 46438f7fc0SSiva Chandra Reddy 47438f7fc0SSiva Chandra Reddy enum class BenchmarkLog { 48438f7fc0SSiva Chandra Reddy None, // Don't keep the internal state of the benchmark. 49438f7fc0SSiva Chandra Reddy Last, // Keep only the last batch. 50438f7fc0SSiva Chandra Reddy Full // Keep all iterations states, useful for testing or debugging. 51438f7fc0SSiva Chandra Reddy }; 52438f7fc0SSiva Chandra Reddy 53438f7fc0SSiva Chandra Reddy // An object to configure the benchmark stopping conditions. 54438f7fc0SSiva Chandra Reddy // See documentation at the beginning of the file for the overall algorithm and 55438f7fc0SSiva Chandra Reddy // meaning of each field. 56438f7fc0SSiva Chandra Reddy struct BenchmarkOptions { 57438f7fc0SSiva Chandra Reddy // The minimum time for which the benchmark is running. 58438f7fc0SSiva Chandra Reddy Duration MinDuration = std::chrono::seconds(0); 59438f7fc0SSiva Chandra Reddy // The maximum time for which the benchmark is running. 60438f7fc0SSiva Chandra Reddy Duration MaxDuration = std::chrono::seconds(10); 61438f7fc0SSiva Chandra Reddy // The number of iterations in the first sample. 62438f7fc0SSiva Chandra Reddy uint32_t InitialIterations = 1; 63438f7fc0SSiva Chandra Reddy // The maximum number of iterations for any given sample. 64438f7fc0SSiva Chandra Reddy uint32_t MaxIterations = 10000000; 65438f7fc0SSiva Chandra Reddy // The minimum number of samples. 66438f7fc0SSiva Chandra Reddy uint32_t MinSamples = 4; 67438f7fc0SSiva Chandra Reddy // The maximum number of samples. 68438f7fc0SSiva Chandra Reddy uint32_t MaxSamples = 1000; 69d28f6729SChris Gyurgyik // The benchmark will stop if the relative difference between the current and 70438f7fc0SSiva Chandra Reddy // the last estimation is less than epsilon. This is 1% by default. 71438f7fc0SSiva Chandra Reddy double Epsilon = 0.01; 72438f7fc0SSiva Chandra Reddy // The number of iterations grows exponentially between each sample. 73438f7fc0SSiva Chandra Reddy // Must be greater or equal to 1. 74438f7fc0SSiva Chandra Reddy double ScalingFactor = 1.4; 75438f7fc0SSiva Chandra Reddy BenchmarkLog Log = BenchmarkLog::None; 76438f7fc0SSiva Chandra Reddy }; 77438f7fc0SSiva Chandra Reddy 78438f7fc0SSiva Chandra Reddy // The state of a benchmark. 79438f7fc0SSiva Chandra Reddy enum class BenchmarkStatus { 80438f7fc0SSiva Chandra Reddy Running, 81438f7fc0SSiva Chandra Reddy MaxDurationReached, 82438f7fc0SSiva Chandra Reddy MaxIterationsReached, 83438f7fc0SSiva Chandra Reddy MaxSamplesReached, 84438f7fc0SSiva Chandra Reddy PrecisionReached, 85438f7fc0SSiva Chandra Reddy }; 86438f7fc0SSiva Chandra Reddy 87438f7fc0SSiva Chandra Reddy // The internal state of the benchmark, useful to debug, test or report 88438f7fc0SSiva Chandra Reddy // statistics. 89438f7fc0SSiva Chandra Reddy struct BenchmarkState { 90438f7fc0SSiva Chandra Reddy size_t LastSampleIterations; 91438f7fc0SSiva Chandra Reddy Duration LastBatchElapsed; 92438f7fc0SSiva Chandra Reddy BenchmarkStatus CurrentStatus; 93438f7fc0SSiva Chandra Reddy Duration CurrentBestGuess; // The time estimation for a single run of `foo`. 94438f7fc0SSiva Chandra Reddy double ChangeRatio; // The change in time estimation between previous and 95438f7fc0SSiva Chandra Reddy // current samples. 96438f7fc0SSiva Chandra Reddy }; 97438f7fc0SSiva Chandra Reddy 98438f7fc0SSiva Chandra Reddy // A lightweight result for a benchmark. 99438f7fc0SSiva Chandra Reddy struct BenchmarkResult { 100438f7fc0SSiva Chandra Reddy BenchmarkStatus TerminationStatus = BenchmarkStatus::Running; 101438f7fc0SSiva Chandra Reddy Duration BestGuess = {}; 102e1cdda57SKazu Hirata std::optional<llvm::SmallVector<BenchmarkState, 16>> MaybeBenchmarkLog; 103438f7fc0SSiva Chandra Reddy }; 104438f7fc0SSiva Chandra Reddy 105438f7fc0SSiva Chandra Reddy // Stores information about a cache in the host memory system. 106438f7fc0SSiva Chandra Reddy struct CacheInfo { 107438f7fc0SSiva Chandra Reddy std::string Type; // e.g. "Instruction", "Data", "Unified". 108438f7fc0SSiva Chandra Reddy int Level; // 0 is closest to processing unit. 109438f7fc0SSiva Chandra Reddy int Size; // In bytes. 110438f7fc0SSiva Chandra Reddy int NumSharing; // The number of processing units (Hyper-Threading Thread) 111438f7fc0SSiva Chandra Reddy // with which this cache is shared. 112438f7fc0SSiva Chandra Reddy }; 113438f7fc0SSiva Chandra Reddy 114438f7fc0SSiva Chandra Reddy // Stores information about the host. 115438f7fc0SSiva Chandra Reddy struct HostState { 116438f7fc0SSiva Chandra Reddy std::string CpuName; // returns a string compatible with the -march option. 117438f7fc0SSiva Chandra Reddy double CpuFrequency; // in Hertz. 118438f7fc0SSiva Chandra Reddy std::vector<CacheInfo> Caches; 119438f7fc0SSiva Chandra Reddy 120438f7fc0SSiva Chandra Reddy static HostState get(); 121438f7fc0SSiva Chandra Reddy }; 122438f7fc0SSiva Chandra Reddy 123438f7fc0SSiva Chandra Reddy namespace internal { 124438f7fc0SSiva Chandra Reddy 125438f7fc0SSiva Chandra Reddy struct Measurement { 126438f7fc0SSiva Chandra Reddy size_t Iterations = 0; 127438f7fc0SSiva Chandra Reddy Duration Elapsed = {}; 128438f7fc0SSiva Chandra Reddy }; 129438f7fc0SSiva Chandra Reddy 130438f7fc0SSiva Chandra Reddy // Updates the estimation of the elapsed time for a single iteration. 131438f7fc0SSiva Chandra Reddy class RefinableRuntimeEstimation { 132438f7fc0SSiva Chandra Reddy Duration TotalTime = {}; 133438f7fc0SSiva Chandra Reddy size_t TotalIterations = 0; 134438f7fc0SSiva Chandra Reddy 135438f7fc0SSiva Chandra Reddy public: 136438f7fc0SSiva Chandra Reddy Duration update(const Measurement &M) { 137438f7fc0SSiva Chandra Reddy assert(M.Iterations > 0); 138438f7fc0SSiva Chandra Reddy // Duration is encoded as a double (see definition). 139438f7fc0SSiva Chandra Reddy // `TotalTime` and `M.Elapsed` are of the same magnitude so we don't expect 140438f7fc0SSiva Chandra Reddy // loss of precision due to radically different scales. 141438f7fc0SSiva Chandra Reddy TotalTime += M.Elapsed; 142438f7fc0SSiva Chandra Reddy TotalIterations += M.Iterations; 143438f7fc0SSiva Chandra Reddy return TotalTime / TotalIterations; 144438f7fc0SSiva Chandra Reddy } 145438f7fc0SSiva Chandra Reddy }; 146438f7fc0SSiva Chandra Reddy 147438f7fc0SSiva Chandra Reddy // This class tracks the progression of the runtime estimation. 148438f7fc0SSiva Chandra Reddy class RuntimeEstimationProgression { 149438f7fc0SSiva Chandra Reddy RefinableRuntimeEstimation RRE; 150438f7fc0SSiva Chandra Reddy 151438f7fc0SSiva Chandra Reddy public: 152438f7fc0SSiva Chandra Reddy Duration CurrentEstimation = {}; 153438f7fc0SSiva Chandra Reddy 154438f7fc0SSiva Chandra Reddy // Returns the change ratio between our best guess so far and the one from the 155438f7fc0SSiva Chandra Reddy // new measurement. 156438f7fc0SSiva Chandra Reddy double computeImprovement(const Measurement &M) { 157438f7fc0SSiva Chandra Reddy const Duration NewEstimation = RRE.update(M); 158438f7fc0SSiva Chandra Reddy const double Ratio = fabs(((CurrentEstimation / NewEstimation) - 1.0)); 159438f7fc0SSiva Chandra Reddy CurrentEstimation = NewEstimation; 160438f7fc0SSiva Chandra Reddy return Ratio; 161438f7fc0SSiva Chandra Reddy } 162438f7fc0SSiva Chandra Reddy }; 163438f7fc0SSiva Chandra Reddy 164438f7fc0SSiva Chandra Reddy } // namespace internal 165438f7fc0SSiva Chandra Reddy 166438f7fc0SSiva Chandra Reddy // Measures the runtime of `foo` until conditions defined by `Options` are met. 167438f7fc0SSiva Chandra Reddy // 168438f7fc0SSiva Chandra Reddy // To avoid measurement's imprecisions we measure batches of `foo`. 169438f7fc0SSiva Chandra Reddy // The batch size is growing by `ScalingFactor` to minimize the effect of 170438f7fc0SSiva Chandra Reddy // measuring. 171438f7fc0SSiva Chandra Reddy // 172438f7fc0SSiva Chandra Reddy // Note: The benchmark is not responsible for serializing the executions of 173438f7fc0SSiva Chandra Reddy // `foo`. It is not suitable for measuring, very small & side effect free 174438f7fc0SSiva Chandra Reddy // functions, as the processor is free to execute several executions in 175438f7fc0SSiva Chandra Reddy // parallel. 176438f7fc0SSiva Chandra Reddy // 177438f7fc0SSiva Chandra Reddy // - Options: A set of parameters controlling the stopping conditions for the 178438f7fc0SSiva Chandra Reddy // benchmark. 179438f7fc0SSiva Chandra Reddy // - foo: The function under test. It takes one value and returns one value. 180438f7fc0SSiva Chandra Reddy // The input value is used to randomize the execution of `foo` as part of a 181438f7fc0SSiva Chandra Reddy // batch to mitigate the effect of the branch predictor. Signature: 182438f7fc0SSiva Chandra Reddy // `ProductType foo(ParameterProvider::value_type value);` 183438f7fc0SSiva Chandra Reddy // The output value is a product of the execution of `foo` and prevents the 184438f7fc0SSiva Chandra Reddy // compiler from optimizing out foo's body. 185438f7fc0SSiva Chandra Reddy // - ParameterProvider: An object responsible for providing a range of 186438f7fc0SSiva Chandra Reddy // `Iterations` values to use as input for `foo`. The `value_type` of the 187438f7fc0SSiva Chandra Reddy // returned container has to be compatible with `foo` argument. 188438f7fc0SSiva Chandra Reddy // Must implement one of: 189438f7fc0SSiva Chandra Reddy // `Container<ParameterType> generateBatch(size_t Iterations);` 190438f7fc0SSiva Chandra Reddy // `const Container<ParameterType>& generateBatch(size_t Iterations);` 191438f7fc0SSiva Chandra Reddy // - Clock: An object providing the current time. Must implement: 192438f7fc0SSiva Chandra Reddy // `std::chrono::time_point now();` 193438f7fc0SSiva Chandra Reddy template <typename Function, typename ParameterProvider, 194438f7fc0SSiva Chandra Reddy typename BenchmarkClock = const std::chrono::high_resolution_clock> 195438f7fc0SSiva Chandra Reddy BenchmarkResult benchmark(const BenchmarkOptions &Options, 196438f7fc0SSiva Chandra Reddy ParameterProvider &PP, Function foo, 197438f7fc0SSiva Chandra Reddy BenchmarkClock &Clock = BenchmarkClock()) { 198438f7fc0SSiva Chandra Reddy BenchmarkResult Result; 199438f7fc0SSiva Chandra Reddy internal::RuntimeEstimationProgression REP; 200438f7fc0SSiva Chandra Reddy Duration TotalBenchmarkDuration = {}; 201438f7fc0SSiva Chandra Reddy size_t Iterations = std::max(Options.InitialIterations, uint32_t(1)); 202438f7fc0SSiva Chandra Reddy size_t Samples = 0; 203438f7fc0SSiva Chandra Reddy if (Options.ScalingFactor < 1.0) 204438f7fc0SSiva Chandra Reddy report_fatal_error("ScalingFactor should be >= 1"); 205438f7fc0SSiva Chandra Reddy if (Options.Log != BenchmarkLog::None) 206438f7fc0SSiva Chandra Reddy Result.MaybeBenchmarkLog.emplace(); 207438f7fc0SSiva Chandra Reddy for (;;) { 208438f7fc0SSiva Chandra Reddy // Request a new Batch of size `Iterations`. 209438f7fc0SSiva Chandra Reddy const auto &Batch = PP.generateBatch(Iterations); 210438f7fc0SSiva Chandra Reddy 211438f7fc0SSiva Chandra Reddy // Measuring this Batch. 212438f7fc0SSiva Chandra Reddy const auto StartTime = Clock.now(); 213438f7fc0SSiva Chandra Reddy for (const auto Parameter : Batch) { 214*081a80f2SDavid Peixotto auto Production = foo(Parameter); 215438f7fc0SSiva Chandra Reddy benchmark::DoNotOptimize(Production); 216438f7fc0SSiva Chandra Reddy } 217438f7fc0SSiva Chandra Reddy const auto EndTime = Clock.now(); 218438f7fc0SSiva Chandra Reddy const Duration Elapsed = EndTime - StartTime; 219438f7fc0SSiva Chandra Reddy 220438f7fc0SSiva Chandra Reddy // Updating statistics. 221438f7fc0SSiva Chandra Reddy ++Samples; 222438f7fc0SSiva Chandra Reddy TotalBenchmarkDuration += Elapsed; 223438f7fc0SSiva Chandra Reddy const double ChangeRatio = REP.computeImprovement({Iterations, Elapsed}); 224438f7fc0SSiva Chandra Reddy Result.BestGuess = REP.CurrentEstimation; 225438f7fc0SSiva Chandra Reddy 226438f7fc0SSiva Chandra Reddy // Stopping condition. 227438f7fc0SSiva Chandra Reddy if (TotalBenchmarkDuration >= Options.MinDuration && 228438f7fc0SSiva Chandra Reddy Samples >= Options.MinSamples && ChangeRatio < Options.Epsilon) 229438f7fc0SSiva Chandra Reddy Result.TerminationStatus = BenchmarkStatus::PrecisionReached; 230438f7fc0SSiva Chandra Reddy else if (Samples >= Options.MaxSamples) 231438f7fc0SSiva Chandra Reddy Result.TerminationStatus = BenchmarkStatus::MaxSamplesReached; 232438f7fc0SSiva Chandra Reddy else if (TotalBenchmarkDuration >= Options.MaxDuration) 233438f7fc0SSiva Chandra Reddy Result.TerminationStatus = BenchmarkStatus::MaxDurationReached; 234438f7fc0SSiva Chandra Reddy else if (Iterations >= Options.MaxIterations) 235438f7fc0SSiva Chandra Reddy Result.TerminationStatus = BenchmarkStatus::MaxIterationsReached; 236438f7fc0SSiva Chandra Reddy 237438f7fc0SSiva Chandra Reddy if (Result.MaybeBenchmarkLog) { 238438f7fc0SSiva Chandra Reddy auto &BenchmarkLog = *Result.MaybeBenchmarkLog; 239438f7fc0SSiva Chandra Reddy if (Options.Log == BenchmarkLog::Last && !BenchmarkLog.empty()) 240438f7fc0SSiva Chandra Reddy BenchmarkLog.pop_back(); 241438f7fc0SSiva Chandra Reddy BenchmarkState BS; 242438f7fc0SSiva Chandra Reddy BS.LastSampleIterations = Iterations; 243438f7fc0SSiva Chandra Reddy BS.LastBatchElapsed = Elapsed; 244438f7fc0SSiva Chandra Reddy BS.CurrentStatus = Result.TerminationStatus; 245438f7fc0SSiva Chandra Reddy BS.CurrentBestGuess = Result.BestGuess; 246438f7fc0SSiva Chandra Reddy BS.ChangeRatio = ChangeRatio; 247438f7fc0SSiva Chandra Reddy BenchmarkLog.push_back(BS); 248438f7fc0SSiva Chandra Reddy } 249438f7fc0SSiva Chandra Reddy 250438f7fc0SSiva Chandra Reddy if (Result.TerminationStatus != BenchmarkStatus::Running) 251438f7fc0SSiva Chandra Reddy return Result; 252438f7fc0SSiva Chandra Reddy 253438f7fc0SSiva Chandra Reddy if (Options.ScalingFactor > 1 && 254438f7fc0SSiva Chandra Reddy Iterations * Options.ScalingFactor == Iterations) 255438f7fc0SSiva Chandra Reddy report_fatal_error( 256438f7fc0SSiva Chandra Reddy "`Iterations *= ScalingFactor` is idempotent, increase ScalingFactor " 257438f7fc0SSiva Chandra Reddy "or InitialIterations."); 258438f7fc0SSiva Chandra Reddy 259438f7fc0SSiva Chandra Reddy Iterations *= Options.ScalingFactor; 260438f7fc0SSiva Chandra Reddy } 261438f7fc0SSiva Chandra Reddy } 262438f7fc0SSiva Chandra Reddy 263438f7fc0SSiva Chandra Reddy // Interprets `Array` as a circular buffer of `Size` elements. 264438f7fc0SSiva Chandra Reddy template <typename T> class CircularArrayRef { 265438f7fc0SSiva Chandra Reddy llvm::ArrayRef<T> Array; 266438f7fc0SSiva Chandra Reddy size_t Size; 267438f7fc0SSiva Chandra Reddy 268438f7fc0SSiva Chandra Reddy public: 269438f7fc0SSiva Chandra Reddy using value_type = T; 270438f7fc0SSiva Chandra Reddy using reference = T &; 271438f7fc0SSiva Chandra Reddy using const_reference = const T &; 272438f7fc0SSiva Chandra Reddy using difference_type = ssize_t; 273438f7fc0SSiva Chandra Reddy using size_type = size_t; 274438f7fc0SSiva Chandra Reddy 27512c62a67SSchrodinger ZHU Yifan class const_iterator { 27612c62a67SSchrodinger ZHU Yifan using iterator_category = std::input_iterator_tag; 277438f7fc0SSiva Chandra Reddy llvm::ArrayRef<T> Array; 278438f7fc0SSiva Chandra Reddy size_t Index; 279223a6f94SGuillaume Chatelet size_t Offset; 280438f7fc0SSiva Chandra Reddy 281438f7fc0SSiva Chandra Reddy public: 282438f7fc0SSiva Chandra Reddy explicit const_iterator(llvm::ArrayRef<T> Array, size_t Index = 0) 283223a6f94SGuillaume Chatelet : Array(Array), Index(Index), Offset(Index % Array.size()) {} 284438f7fc0SSiva Chandra Reddy const_iterator &operator++() { 285438f7fc0SSiva Chandra Reddy ++Index; 286223a6f94SGuillaume Chatelet ++Offset; 287223a6f94SGuillaume Chatelet if (Offset == Array.size()) 288223a6f94SGuillaume Chatelet Offset = 0; 289438f7fc0SSiva Chandra Reddy return *this; 290438f7fc0SSiva Chandra Reddy } 291438f7fc0SSiva Chandra Reddy bool operator==(const_iterator Other) const { return Index == Other.Index; } 292438f7fc0SSiva Chandra Reddy bool operator!=(const_iterator Other) const { return !(*this == Other); } 293223a6f94SGuillaume Chatelet const T &operator*() const { return Array[Offset]; } 294438f7fc0SSiva Chandra Reddy }; 295438f7fc0SSiva Chandra Reddy 296438f7fc0SSiva Chandra Reddy CircularArrayRef(llvm::ArrayRef<T> Array, size_t Size) 297438f7fc0SSiva Chandra Reddy : Array(Array), Size(Size) { 298438f7fc0SSiva Chandra Reddy assert(Array.size() > 0); 299438f7fc0SSiva Chandra Reddy } 300438f7fc0SSiva Chandra Reddy 301438f7fc0SSiva Chandra Reddy const_iterator begin() const { return const_iterator(Array); } 302438f7fc0SSiva Chandra Reddy const_iterator end() const { return const_iterator(Array, Size); } 303438f7fc0SSiva Chandra Reddy }; 304438f7fc0SSiva Chandra Reddy 305438f7fc0SSiva Chandra Reddy // A convenient helper to produce a CircularArrayRef from an ArrayRef. 306438f7fc0SSiva Chandra Reddy template <typename T> 307438f7fc0SSiva Chandra Reddy CircularArrayRef<T> cycle(llvm::ArrayRef<T> Array, size_t Size) { 308438f7fc0SSiva Chandra Reddy return {Array, Size}; 309438f7fc0SSiva Chandra Reddy } 310438f7fc0SSiva Chandra Reddy 311438f7fc0SSiva Chandra Reddy // Creates an std::array which storage size is constrained under `Bytes`. 312438f7fc0SSiva Chandra Reddy template <typename T, size_t Bytes> 313438f7fc0SSiva Chandra Reddy using ByteConstrainedArray = std::array<T, Bytes / sizeof(T)>; 314438f7fc0SSiva Chandra Reddy 315438f7fc0SSiva Chandra Reddy // A convenient helper to produce a CircularArrayRef from a 316438f7fc0SSiva Chandra Reddy // ByteConstrainedArray. 317438f7fc0SSiva Chandra Reddy template <typename T, size_t N> 318438f7fc0SSiva Chandra Reddy CircularArrayRef<T> cycle(const std::array<T, N> &Container, size_t Size) { 319438f7fc0SSiva Chandra Reddy return {llvm::ArrayRef<T>(Container.cbegin(), Container.cend()), Size}; 320438f7fc0SSiva Chandra Reddy } 321438f7fc0SSiva Chandra Reddy 322deae7e98SGuillaume Chatelet // Makes sure the binary was compiled in release mode and that frequency 323deae7e98SGuillaume Chatelet // governor is set on performance. 324deae7e98SGuillaume Chatelet void checkRequirements(); 325deae7e98SGuillaume Chatelet 326438f7fc0SSiva Chandra Reddy } // namespace libc_benchmarks 327438f7fc0SSiva Chandra Reddy } // namespace llvm 328438f7fc0SSiva Chandra Reddy 329438f7fc0SSiva Chandra Reddy #endif // LLVM_LIBC_UTILS_BENCHMARK_BENCHMARK_H 330