159198d06SGuillaume Chatelet #include "LibcBenchmark.h"
259198d06SGuillaume Chatelet #include "LibcMemoryBenchmark.h"
359198d06SGuillaume Chatelet #include "MemorySizeDistributions.h"
459198d06SGuillaume Chatelet #include "benchmark/benchmark.h"
5e4dee762SGuillaume Chatelet #include "llvm/ADT/ArrayRef.h"
6e4dee762SGuillaume Chatelet #include "llvm/ADT/Twine.h"
7e4dee762SGuillaume Chatelet #include <chrono>
859198d06SGuillaume Chatelet #include <cstdint>
959198d06SGuillaume Chatelet #include <random>
1059198d06SGuillaume Chatelet #include <vector>
1159198d06SGuillaume Chatelet
12e4dee762SGuillaume Chatelet using llvm::Align;
13e4dee762SGuillaume Chatelet using llvm::ArrayRef;
14e4dee762SGuillaume Chatelet using llvm::Twine;
15e4dee762SGuillaume Chatelet using llvm::libc_benchmarks::BzeroConfiguration;
16e4dee762SGuillaume Chatelet using llvm::libc_benchmarks::ComparisonSetup;
17e4dee762SGuillaume Chatelet using llvm::libc_benchmarks::CopySetup;
184a9bcb60SGuillaume Chatelet using llvm::libc_benchmarks::MemcmpOrBcmpConfiguration;
19e4dee762SGuillaume Chatelet using llvm::libc_benchmarks::MemcpyConfiguration;
20de21f346SGuillaume Chatelet using llvm::libc_benchmarks::MemmoveConfiguration;
21e4dee762SGuillaume Chatelet using llvm::libc_benchmarks::MemorySizeDistribution;
22e4dee762SGuillaume Chatelet using llvm::libc_benchmarks::MemsetConfiguration;
23de21f346SGuillaume Chatelet using llvm::libc_benchmarks::MoveSetup;
24e4dee762SGuillaume Chatelet using llvm::libc_benchmarks::OffsetDistribution;
25e4dee762SGuillaume Chatelet using llvm::libc_benchmarks::SetSetup;
26e4dee762SGuillaume Chatelet
27e4dee762SGuillaume Chatelet // Alignment to use for when accessing the buffers.
2859198d06SGuillaume Chatelet static constexpr Align kBenchmarkAlignment = Align::Constant<1>();
2959198d06SGuillaume Chatelet
getGenerator()30e4dee762SGuillaume Chatelet static std::mt19937_64 &getGenerator() {
31e4dee762SGuillaume Chatelet static std::mt19937_64 Generator(
32e4dee762SGuillaume Chatelet std::chrono::system_clock::now().time_since_epoch().count());
33e4dee762SGuillaume Chatelet return Generator;
34e4dee762SGuillaume Chatelet }
35e4dee762SGuillaume Chatelet
36e4dee762SGuillaume Chatelet template <typename SetupType, typename ConfigurationType> struct Runner {
RunnerRunner37e4dee762SGuillaume Chatelet Runner(benchmark::State &S, llvm::ArrayRef<ConfigurationType> Configurations)
38e4dee762SGuillaume Chatelet : State(S), Distribution(SetupType::getDistributions()[State.range(0)]),
3959198d06SGuillaume Chatelet Probabilities(Distribution.Probabilities),
4059198d06SGuillaume Chatelet SizeSampler(Probabilities.begin(), Probabilities.end()),
41e4dee762SGuillaume Chatelet OffsetSampler(Setup.BufferSize, Probabilities.size() - 1,
42e4dee762SGuillaume Chatelet kBenchmarkAlignment),
43e4dee762SGuillaume Chatelet Configuration(Configurations[State.range(1)]) {
44e4dee762SGuillaume Chatelet for (auto &P : Setup.Parameters) {
45e4dee762SGuillaume Chatelet P.OffsetBytes = OffsetSampler(getGenerator());
46e4dee762SGuillaume Chatelet P.SizeBytes = SizeSampler(getGenerator());
47e4dee762SGuillaume Chatelet Setup.checkValid(P);
4859198d06SGuillaume Chatelet }
4959198d06SGuillaume Chatelet }
5059198d06SGuillaume Chatelet
~RunnerRunner51e4dee762SGuillaume Chatelet ~Runner() {
52*bcf394c4SGuillaume Chatelet const size_t TotalBytes =
53*bcf394c4SGuillaume Chatelet (State.iterations() * Setup.getBatchBytes()) / Setup.BatchSize;
5459198d06SGuillaume Chatelet State.SetBytesProcessed(TotalBytes);
55e4dee762SGuillaume Chatelet State.SetItemsProcessed(State.iterations());
56e4dee762SGuillaume Chatelet State.SetLabel((Twine(Configuration.Name) + "," + Distribution.Name).str());
5759198d06SGuillaume Chatelet State.counters["bytes_per_cycle"] = benchmark::Counter(
5859198d06SGuillaume Chatelet TotalBytes / benchmark::CPUInfo::Get().cycles_per_second,
5959198d06SGuillaume Chatelet benchmark::Counter::kIsRate);
6059198d06SGuillaume Chatelet }
6159198d06SGuillaume Chatelet
runBatchRunner62e4dee762SGuillaume Chatelet inline void runBatch() {
63e4dee762SGuillaume Chatelet for (const auto &P : Setup.Parameters)
64e4dee762SGuillaume Chatelet benchmark::DoNotOptimize(Setup.Call(P, Configuration.Function));
6559198d06SGuillaume Chatelet }
6659198d06SGuillaume Chatelet
getBatchSizeRunner67e4dee762SGuillaume Chatelet size_t getBatchSize() const { return Setup.BatchSize; }
68e4dee762SGuillaume Chatelet
6959198d06SGuillaume Chatelet private:
70e4dee762SGuillaume Chatelet SetupType Setup;
7159198d06SGuillaume Chatelet benchmark::State &State;
7259198d06SGuillaume Chatelet MemorySizeDistribution Distribution;
7359198d06SGuillaume Chatelet ArrayRef<double> Probabilities;
7459198d06SGuillaume Chatelet std::discrete_distribution<unsigned> SizeSampler;
7559198d06SGuillaume Chatelet OffsetDistribution OffsetSampler;
76e4dee762SGuillaume Chatelet ConfigurationType Configuration;
7759198d06SGuillaume Chatelet };
7859198d06SGuillaume Chatelet
79e4dee762SGuillaume Chatelet #define BENCHMARK_MEMORY_FUNCTION(BM_NAME, SETUP, CONFIGURATION_TYPE, \
80e4dee762SGuillaume Chatelet CONFIGURATION_ARRAY_REF) \
81e4dee762SGuillaume Chatelet void BM_NAME(benchmark::State &State) { \
82e4dee762SGuillaume Chatelet Runner<SETUP, CONFIGURATION_TYPE> Setup(State, CONFIGURATION_ARRAY_REF); \
83e4dee762SGuillaume Chatelet const size_t BatchSize = Setup.getBatchSize(); \
84e4dee762SGuillaume Chatelet while (State.KeepRunningBatch(BatchSize)) \
85e4dee762SGuillaume Chatelet Setup.runBatch(); \
86e4dee762SGuillaume Chatelet } \
87e4dee762SGuillaume Chatelet BENCHMARK(BM_NAME)->Apply([](benchmark::internal::Benchmark *benchmark) { \
88e4dee762SGuillaume Chatelet const int64_t DistributionSize = SETUP::getDistributions().size(); \
89e4dee762SGuillaume Chatelet const int64_t ConfigurationSize = CONFIGURATION_ARRAY_REF.size(); \
90e4dee762SGuillaume Chatelet for (int64_t DistIndex = 0; DistIndex < DistributionSize; ++DistIndex) \
91e4dee762SGuillaume Chatelet for (int64_t ConfIndex = 0; ConfIndex < ConfigurationSize; ++ConfIndex) \
92e4dee762SGuillaume Chatelet benchmark->Args({DistIndex, ConfIndex}); \
93e4dee762SGuillaume Chatelet })
9459198d06SGuillaume Chatelet
95adc18ad6SGuillaume Chatelet extern llvm::ArrayRef<MemcpyConfiguration> getMemcpyConfigurations();
96e4dee762SGuillaume Chatelet BENCHMARK_MEMORY_FUNCTION(BM_Memcpy, CopySetup, MemcpyConfiguration,
97adc18ad6SGuillaume Chatelet getMemcpyConfigurations());
98adc18ad6SGuillaume Chatelet
99de21f346SGuillaume Chatelet extern llvm::ArrayRef<MemmoveConfiguration> getMemmoveConfigurations();
100de21f346SGuillaume Chatelet BENCHMARK_MEMORY_FUNCTION(BM_Memmove, MoveSetup, MemmoveConfiguration,
101de21f346SGuillaume Chatelet getMemmoveConfigurations());
102de21f346SGuillaume Chatelet
1034a9bcb60SGuillaume Chatelet extern llvm::ArrayRef<MemcmpOrBcmpConfiguration> getMemcmpConfigurations();
1044a9bcb60SGuillaume Chatelet BENCHMARK_MEMORY_FUNCTION(BM_Memcmp, ComparisonSetup, MemcmpOrBcmpConfiguration,
105adc18ad6SGuillaume Chatelet getMemcmpConfigurations());
106adc18ad6SGuillaume Chatelet
1074a9bcb60SGuillaume Chatelet extern llvm::ArrayRef<MemcmpOrBcmpConfiguration> getBcmpConfigurations();
1084a9bcb60SGuillaume Chatelet BENCHMARK_MEMORY_FUNCTION(BM_Bcmp, ComparisonSetup, MemcmpOrBcmpConfiguration,
109adc18ad6SGuillaume Chatelet getBcmpConfigurations());
110adc18ad6SGuillaume Chatelet
111adc18ad6SGuillaume Chatelet extern llvm::ArrayRef<MemsetConfiguration> getMemsetConfigurations();
112e4dee762SGuillaume Chatelet BENCHMARK_MEMORY_FUNCTION(BM_Memset, SetSetup, MemsetConfiguration,
113adc18ad6SGuillaume Chatelet getMemsetConfigurations());
114adc18ad6SGuillaume Chatelet
115adc18ad6SGuillaume Chatelet extern llvm::ArrayRef<BzeroConfiguration> getBzeroConfigurations();
116e4dee762SGuillaume Chatelet BENCHMARK_MEMORY_FUNCTION(BM_Bzero, SetSetup, BzeroConfiguration,
117adc18ad6SGuillaume Chatelet getBzeroConfigurations());
118