1438f7fc0SSiva Chandra Reddy //===-- Benchmark ---------------------------------------------------------===// 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 #include "JSON.h" 10438f7fc0SSiva Chandra Reddy #include "LibcBenchmark.h" 11438f7fc0SSiva Chandra Reddy #include "LibcMemoryBenchmark.h" 12deae7e98SGuillaume Chatelet #include "MemorySizeDistributions.h" 13438f7fc0SSiva Chandra Reddy #include "llvm/Support/CommandLine.h" 14438f7fc0SSiva Chandra Reddy #include "llvm/Support/ErrorHandling.h" 15438f7fc0SSiva Chandra Reddy #include "llvm/Support/FileSystem.h" 16438f7fc0SSiva Chandra Reddy #include "llvm/Support/JSON.h" 17438f7fc0SSiva Chandra Reddy #include "llvm/Support/MemoryBuffer.h" 18438f7fc0SSiva Chandra Reddy #include "llvm/Support/raw_ostream.h" 19438f7fc0SSiva Chandra Reddy 20deae7e98SGuillaume Chatelet namespace __llvm_libc { 21deae7e98SGuillaume Chatelet 22deae7e98SGuillaume Chatelet extern void *memcpy(void *__restrict, const void *__restrict, size_t); 23deae7e98SGuillaume Chatelet extern void *memset(void *, int, size_t); 24deae7e98SGuillaume Chatelet 25deae7e98SGuillaume Chatelet } // namespace __llvm_libc 26438f7fc0SSiva Chandra Reddy 27438f7fc0SSiva Chandra Reddy namespace llvm { 28438f7fc0SSiva Chandra Reddy namespace libc_benchmarks { 29438f7fc0SSiva Chandra Reddy 30deae7e98SGuillaume Chatelet static cl::opt<std::string> 31deae7e98SGuillaume Chatelet StudyName("study-name", cl::desc("The name for this study"), cl::Required); 32deae7e98SGuillaume Chatelet 33deae7e98SGuillaume Chatelet static cl::opt<std::string> 34deae7e98SGuillaume Chatelet SizeDistributionName("size-distribution-name", 35deae7e98SGuillaume Chatelet cl::desc("The name of the distribution to use")); 36deae7e98SGuillaume Chatelet 37deae7e98SGuillaume Chatelet static cl::opt<bool> 38deae7e98SGuillaume Chatelet SweepMode("sweep-mode", 39deae7e98SGuillaume Chatelet cl::desc("If set, benchmark all sizes from 0 to sweep-max-size")); 40deae7e98SGuillaume Chatelet 41deae7e98SGuillaume Chatelet static cl::opt<uint32_t> 42deae7e98SGuillaume Chatelet SweepMaxSize("sweep-max-size", 43deae7e98SGuillaume Chatelet cl::desc("The maximum size to use in sweep-mode"), 44deae7e98SGuillaume Chatelet cl::init(256)); 45deae7e98SGuillaume Chatelet 46deae7e98SGuillaume Chatelet static cl::opt<uint32_t> 47deae7e98SGuillaume Chatelet AlignedAccess("aligned-access", 48deae7e98SGuillaume Chatelet cl::desc("The alignment to use when accessing the buffers\n" 49deae7e98SGuillaume Chatelet "Default is unaligned\n" 50deae7e98SGuillaume Chatelet "Use 0 to disable address randomization"), 51deae7e98SGuillaume Chatelet cl::init(1)); 52deae7e98SGuillaume Chatelet 53deae7e98SGuillaume Chatelet static cl::opt<std::string> Output("output", 54deae7e98SGuillaume Chatelet cl::desc("Specify output filename"), 55438f7fc0SSiva Chandra Reddy cl::value_desc("filename"), cl::init("-")); 56438f7fc0SSiva Chandra Reddy 57deae7e98SGuillaume Chatelet static cl::opt<uint32_t> 58deae7e98SGuillaume Chatelet NumTrials("num-trials", cl::desc("The number of benchmarks run to perform"), 59deae7e98SGuillaume Chatelet cl::init(1)); 60438f7fc0SSiva Chandra Reddy 61deae7e98SGuillaume Chatelet static constexpr int64_t KiB = 1024; 62deae7e98SGuillaume Chatelet static constexpr int64_t ParameterStorageBytes = 4 * KiB; 63deae7e98SGuillaume Chatelet static constexpr int64_t L1LeftAsideBytes = 1 * KiB; 64438f7fc0SSiva Chandra Reddy 65deae7e98SGuillaume Chatelet struct ParameterType { 66deae7e98SGuillaume Chatelet unsigned OffsetBytes : 16; // max : 16 KiB - 1 67deae7e98SGuillaume Chatelet unsigned SizeBytes : 16; // max : 16 KiB - 1 68deae7e98SGuillaume Chatelet }; 69438f7fc0SSiva Chandra Reddy 70*8d64ed85SGuillaume Chatelet #if defined(LIBC_BENCHMARK_FUNCTION_MEMCPY) 71*8d64ed85SGuillaume Chatelet struct Benchmark { 72deae7e98SGuillaume Chatelet static constexpr auto GetDistributions = &getMemcpySizeDistributions; 73deae7e98SGuillaume Chatelet static constexpr size_t BufferCount = 2; 74438f7fc0SSiva Chandra Reddy 75*8d64ed85SGuillaume Chatelet Benchmark(const size_t BufferSize) 76deae7e98SGuillaume Chatelet : SrcBuffer(BufferSize), DstBuffer(BufferSize) {} 77deae7e98SGuillaume Chatelet 78deae7e98SGuillaume Chatelet inline auto functor() { 79deae7e98SGuillaume Chatelet return [this](ParameterType P) { 80deae7e98SGuillaume Chatelet __llvm_libc::memcpy(DstBuffer + P.OffsetBytes, SrcBuffer + P.OffsetBytes, 81deae7e98SGuillaume Chatelet P.SizeBytes); 82deae7e98SGuillaume Chatelet return DstBuffer + P.OffsetBytes; 83deae7e98SGuillaume Chatelet }; 84438f7fc0SSiva Chandra Reddy } 85438f7fc0SSiva Chandra Reddy 86deae7e98SGuillaume Chatelet AlignedBuffer SrcBuffer; 87deae7e98SGuillaume Chatelet AlignedBuffer DstBuffer; 88deae7e98SGuillaume Chatelet }; 89*8d64ed85SGuillaume Chatelet #elif defined(LIBC_BENCHMARK_FUNCTION_MEMSET) 90*8d64ed85SGuillaume Chatelet struct Benchmark { 91deae7e98SGuillaume Chatelet static constexpr auto GetDistributions = &getMemsetSizeDistributions; 92deae7e98SGuillaume Chatelet static constexpr size_t BufferCount = 1; 93deae7e98SGuillaume Chatelet 94*8d64ed85SGuillaume Chatelet Benchmark(const size_t BufferSize) : DstBuffer(BufferSize) {} 95deae7e98SGuillaume Chatelet 96deae7e98SGuillaume Chatelet inline auto functor() { 97deae7e98SGuillaume Chatelet return [this](ParameterType P) { 98deae7e98SGuillaume Chatelet __llvm_libc::memset(DstBuffer + P.OffsetBytes, P.OffsetBytes & 0xFF, 99deae7e98SGuillaume Chatelet P.SizeBytes); 100deae7e98SGuillaume Chatelet return DstBuffer + P.OffsetBytes; 101deae7e98SGuillaume Chatelet }; 102deae7e98SGuillaume Chatelet } 103deae7e98SGuillaume Chatelet 104deae7e98SGuillaume Chatelet AlignedBuffer DstBuffer; 105deae7e98SGuillaume Chatelet }; 106*8d64ed85SGuillaume Chatelet #else 107*8d64ed85SGuillaume Chatelet #error "Missing LIBC_BENCHMARK_FUNCTION_XXX definition" 108*8d64ed85SGuillaume Chatelet #endif 109deae7e98SGuillaume Chatelet 110*8d64ed85SGuillaume Chatelet struct Harness : Benchmark { 111deae7e98SGuillaume Chatelet 112deae7e98SGuillaume Chatelet Harness(const size_t BufferSize, size_t BatchParameterCount, 113deae7e98SGuillaume Chatelet std::function<unsigned()> SizeSampler, 114deae7e98SGuillaume Chatelet std::function<unsigned()> OffsetSampler) 115deae7e98SGuillaume Chatelet : Benchmark(BufferSize), BufferSize(BufferSize), 116deae7e98SGuillaume Chatelet Parameters(BatchParameterCount), SizeSampler(SizeSampler), 117deae7e98SGuillaume Chatelet OffsetSampler(OffsetSampler) {} 118deae7e98SGuillaume Chatelet 119deae7e98SGuillaume Chatelet CircularArrayRef<ParameterType> generateBatch(size_t Iterations) { 120deae7e98SGuillaume Chatelet for (auto &P : Parameters) { 121deae7e98SGuillaume Chatelet P.OffsetBytes = OffsetSampler(); 122deae7e98SGuillaume Chatelet P.SizeBytes = SizeSampler(); 123deae7e98SGuillaume Chatelet if (P.OffsetBytes + P.SizeBytes >= BufferSize) 124deae7e98SGuillaume Chatelet report_fatal_error("Call would result in buffer overflow"); 125deae7e98SGuillaume Chatelet } 126deae7e98SGuillaume Chatelet return cycle(makeArrayRef(Parameters), Iterations); 127deae7e98SGuillaume Chatelet } 128deae7e98SGuillaume Chatelet 129deae7e98SGuillaume Chatelet private: 130deae7e98SGuillaume Chatelet const size_t BufferSize; 131deae7e98SGuillaume Chatelet std::vector<ParameterType> Parameters; 132deae7e98SGuillaume Chatelet std::function<unsigned()> SizeSampler; 133deae7e98SGuillaume Chatelet std::function<unsigned()> OffsetSampler; 134deae7e98SGuillaume Chatelet }; 135deae7e98SGuillaume Chatelet 136deae7e98SGuillaume Chatelet size_t getL1DataCacheSize() { 137deae7e98SGuillaume Chatelet const std::vector<CacheInfo> &CacheInfos = HostState::get().Caches; 138deae7e98SGuillaume Chatelet const auto IsL1DataCache = [](const CacheInfo &CI) { 139deae7e98SGuillaume Chatelet return CI.Type == "Data" && CI.Level == 1; 140deae7e98SGuillaume Chatelet }; 141deae7e98SGuillaume Chatelet const auto CacheIt = find_if(CacheInfos, IsL1DataCache); 142deae7e98SGuillaume Chatelet if (CacheIt != CacheInfos.end()) 143deae7e98SGuillaume Chatelet return CacheIt->Size; 144deae7e98SGuillaume Chatelet report_fatal_error("Unable to read L1 Cache Data Size"); 145deae7e98SGuillaume Chatelet } 146deae7e98SGuillaume Chatelet 147*8d64ed85SGuillaume Chatelet struct MemfunctionBenchmark { 148deae7e98SGuillaume Chatelet MemfunctionBenchmark(int64_t L1Size = getL1DataCacheSize()) 149deae7e98SGuillaume Chatelet : AvailableSize(L1Size - L1LeftAsideBytes - ParameterStorageBytes), 150deae7e98SGuillaume Chatelet BufferSize(AvailableSize / Benchmark::BufferCount), 151deae7e98SGuillaume Chatelet BatchParameterCount(BufferSize / sizeof(ParameterType)) { 152deae7e98SGuillaume Chatelet // Handling command line flags 153deae7e98SGuillaume Chatelet if (AvailableSize <= 0 || BufferSize <= 0 || BatchParameterCount < 100) 154deae7e98SGuillaume Chatelet report_fatal_error("Not enough L1 cache"); 155deae7e98SGuillaume Chatelet 156deae7e98SGuillaume Chatelet if (!isPowerOfTwoOrZero(AlignedAccess)) 157deae7e98SGuillaume Chatelet report_fatal_error(AlignedAccess.ArgStr + 158deae7e98SGuillaume Chatelet Twine(" must be a power of two or zero")); 159deae7e98SGuillaume Chatelet 160deae7e98SGuillaume Chatelet const bool HasDistributionName = !SizeDistributionName.empty(); 161deae7e98SGuillaume Chatelet if (SweepMode && HasDistributionName) 162deae7e98SGuillaume Chatelet report_fatal_error("Select only one of `--" + Twine(SweepMode.ArgStr) + 163deae7e98SGuillaume Chatelet "` or `--" + Twine(SizeDistributionName.ArgStr) + "`"); 164deae7e98SGuillaume Chatelet 165deae7e98SGuillaume Chatelet if (SweepMode) { 166deae7e98SGuillaume Chatelet MaxSizeValue = SweepMaxSize; 167deae7e98SGuillaume Chatelet } else { 168deae7e98SGuillaume Chatelet std::map<StringRef, MemorySizeDistribution> Map; 169deae7e98SGuillaume Chatelet for (MemorySizeDistribution Distribution : Benchmark::GetDistributions()) 170deae7e98SGuillaume Chatelet Map[Distribution.Name] = Distribution; 171deae7e98SGuillaume Chatelet if (Map.count(SizeDistributionName) == 0) { 172deae7e98SGuillaume Chatelet std::string Message; 173deae7e98SGuillaume Chatelet raw_string_ostream Stream(Message); 174deae7e98SGuillaume Chatelet Stream << "Unknown --" << SizeDistributionName.ArgStr << "='" 175deae7e98SGuillaume Chatelet << SizeDistributionName << "', available distributions:\n"; 176deae7e98SGuillaume Chatelet for (const auto &Pair : Map) 177deae7e98SGuillaume Chatelet Stream << "'" << Pair.first << "'\n"; 178deae7e98SGuillaume Chatelet report_fatal_error(Stream.str()); 179deae7e98SGuillaume Chatelet } 180deae7e98SGuillaume Chatelet SizeDistribution = Map[SizeDistributionName]; 181deae7e98SGuillaume Chatelet MaxSizeValue = SizeDistribution.Probabilities.size() - 1; 182deae7e98SGuillaume Chatelet } 183deae7e98SGuillaume Chatelet 184deae7e98SGuillaume Chatelet // Setup study. 185deae7e98SGuillaume Chatelet Study.StudyName = StudyName; 186deae7e98SGuillaume Chatelet Runtime &RI = Study.Runtime; 187deae7e98SGuillaume Chatelet RI.Host = HostState::get(); 188deae7e98SGuillaume Chatelet RI.BufferSize = BufferSize; 189deae7e98SGuillaume Chatelet RI.BatchParameterCount = BatchParameterCount; 190deae7e98SGuillaume Chatelet 191deae7e98SGuillaume Chatelet BenchmarkOptions &BO = RI.BenchmarkOptions; 192deae7e98SGuillaume Chatelet BO.MinDuration = std::chrono::milliseconds(1); 193deae7e98SGuillaume Chatelet BO.MaxDuration = std::chrono::seconds(1); 194deae7e98SGuillaume Chatelet BO.MaxIterations = 10'000'000U; 195deae7e98SGuillaume Chatelet BO.MinSamples = 4; 196deae7e98SGuillaume Chatelet BO.MaxSamples = 1000; 197deae7e98SGuillaume Chatelet BO.Epsilon = 0.01; // 1% 198deae7e98SGuillaume Chatelet BO.ScalingFactor = 1.4; 199deae7e98SGuillaume Chatelet 200deae7e98SGuillaume Chatelet StudyConfiguration &SC = Study.Configuration; 201deae7e98SGuillaume Chatelet SC.NumTrials = NumTrials; 202deae7e98SGuillaume Chatelet SC.IsSweepMode = SweepMode; 203deae7e98SGuillaume Chatelet if (SweepMode) 204deae7e98SGuillaume Chatelet SC.SweepModeMaxSize = SweepMaxSize; 205deae7e98SGuillaume Chatelet else 206deae7e98SGuillaume Chatelet SC.SizeDistributionName = SizeDistributionName; 207deae7e98SGuillaume Chatelet SC.AccessAlignment = MaybeAlign(AlignedAccess); 208*8d64ed85SGuillaume Chatelet SC.Function = LIBC_BENCHMARK_FUNCTION_NAME; 209deae7e98SGuillaume Chatelet } 210deae7e98SGuillaume Chatelet 211*8d64ed85SGuillaume Chatelet Study run() { 212deae7e98SGuillaume Chatelet if (SweepMode) 213deae7e98SGuillaume Chatelet runSweepMode(); 214deae7e98SGuillaume Chatelet else 215deae7e98SGuillaume Chatelet runDistributionMode(); 216deae7e98SGuillaume Chatelet return Study; 217deae7e98SGuillaume Chatelet } 218deae7e98SGuillaume Chatelet 219deae7e98SGuillaume Chatelet private: 220deae7e98SGuillaume Chatelet const int64_t AvailableSize; 221deae7e98SGuillaume Chatelet const int64_t BufferSize; 222deae7e98SGuillaume Chatelet const size_t BatchParameterCount; 223deae7e98SGuillaume Chatelet size_t MaxSizeValue = 0; 224deae7e98SGuillaume Chatelet MemorySizeDistribution SizeDistribution; 225deae7e98SGuillaume Chatelet Study Study; 226deae7e98SGuillaume Chatelet std::mt19937_64 Gen; 227deae7e98SGuillaume Chatelet 228deae7e98SGuillaume Chatelet static constexpr bool isPowerOfTwoOrZero(size_t Value) { 229deae7e98SGuillaume Chatelet return (Value & (Value - 1U)) == 0; 230deae7e98SGuillaume Chatelet } 231deae7e98SGuillaume Chatelet 232deae7e98SGuillaume Chatelet std::function<unsigned()> geOffsetSampler() { 233deae7e98SGuillaume Chatelet return [this]() { 234deae7e98SGuillaume Chatelet static OffsetDistribution OD(BufferSize, MaxSizeValue, 235deae7e98SGuillaume Chatelet Study.Configuration.AccessAlignment); 236deae7e98SGuillaume Chatelet return OD(Gen); 237deae7e98SGuillaume Chatelet }; 238deae7e98SGuillaume Chatelet } 239deae7e98SGuillaume Chatelet 240deae7e98SGuillaume Chatelet std::function<unsigned()> getSizeSampler() { 241deae7e98SGuillaume Chatelet return [this]() { 242deae7e98SGuillaume Chatelet static std::discrete_distribution<unsigned> Distribution( 243deae7e98SGuillaume Chatelet SizeDistribution.Probabilities.begin(), 244deae7e98SGuillaume Chatelet SizeDistribution.Probabilities.end()); 245deae7e98SGuillaume Chatelet return Distribution(Gen); 246deae7e98SGuillaume Chatelet }; 247deae7e98SGuillaume Chatelet } 248deae7e98SGuillaume Chatelet 249ab577807SGuillaume Chatelet void reportProgress() { 250ab577807SGuillaume Chatelet static size_t LastPercent = -1; 251deae7e98SGuillaume Chatelet const size_t TotalSteps = Study.Measurements.capacity(); 252deae7e98SGuillaume Chatelet const size_t Steps = Study.Measurements.size(); 253deae7e98SGuillaume Chatelet const size_t Percent = 100 * Steps / TotalSteps; 254ab577807SGuillaume Chatelet if (Percent == LastPercent) 255ab577807SGuillaume Chatelet return; 256ab577807SGuillaume Chatelet LastPercent = Percent; 257deae7e98SGuillaume Chatelet size_t I = 0; 258deae7e98SGuillaume Chatelet errs() << '['; 259deae7e98SGuillaume Chatelet for (; I <= Percent; ++I) 260deae7e98SGuillaume Chatelet errs() << '#'; 261deae7e98SGuillaume Chatelet for (; I <= 100; ++I) 262deae7e98SGuillaume Chatelet errs() << '_'; 263ab577807SGuillaume Chatelet errs() << "] " << Percent << '%' << '\r'; 264deae7e98SGuillaume Chatelet } 265deae7e98SGuillaume Chatelet 266deae7e98SGuillaume Chatelet void runTrials(const BenchmarkOptions &Options, 267deae7e98SGuillaume Chatelet std::function<unsigned()> SizeSampler, 268deae7e98SGuillaume Chatelet std::function<unsigned()> OffsetSampler) { 269*8d64ed85SGuillaume Chatelet Harness B(BufferSize, BatchParameterCount, SizeSampler, OffsetSampler); 270deae7e98SGuillaume Chatelet for (size_t i = 0; i < NumTrials; ++i) { 271deae7e98SGuillaume Chatelet const BenchmarkResult Result = benchmark(Options, B, B.functor()); 272deae7e98SGuillaume Chatelet Study.Measurements.push_back(Result.BestGuess); 273ab577807SGuillaume Chatelet reportProgress(); 274deae7e98SGuillaume Chatelet } 275deae7e98SGuillaume Chatelet } 276deae7e98SGuillaume Chatelet 277deae7e98SGuillaume Chatelet void runSweepMode() { 278deae7e98SGuillaume Chatelet Study.Measurements.reserve(NumTrials * SweepMaxSize); 279deae7e98SGuillaume Chatelet 280deae7e98SGuillaume Chatelet BenchmarkOptions &BO = Study.Runtime.BenchmarkOptions; 281deae7e98SGuillaume Chatelet BO.MinDuration = std::chrono::milliseconds(1); 282deae7e98SGuillaume Chatelet BO.InitialIterations = 100; 283deae7e98SGuillaume Chatelet 284deae7e98SGuillaume Chatelet for (size_t Size = 0; Size <= SweepMaxSize; ++Size) { 285deae7e98SGuillaume Chatelet const auto SizeSampler = [Size]() { return Size; }; 286deae7e98SGuillaume Chatelet runTrials(BO, SizeSampler, geOffsetSampler()); 287deae7e98SGuillaume Chatelet } 288deae7e98SGuillaume Chatelet } 289deae7e98SGuillaume Chatelet 290deae7e98SGuillaume Chatelet void runDistributionMode() { 291deae7e98SGuillaume Chatelet Study.Measurements.reserve(NumTrials); 292deae7e98SGuillaume Chatelet 293deae7e98SGuillaume Chatelet BenchmarkOptions &BO = Study.Runtime.BenchmarkOptions; 294deae7e98SGuillaume Chatelet BO.MinDuration = std::chrono::milliseconds(10); 295deae7e98SGuillaume Chatelet BO.InitialIterations = BatchParameterCount * 10; 296deae7e98SGuillaume Chatelet 297deae7e98SGuillaume Chatelet runTrials(BO, getSizeSampler(), geOffsetSampler()); 298deae7e98SGuillaume Chatelet } 299deae7e98SGuillaume Chatelet }; 300deae7e98SGuillaume Chatelet 301deae7e98SGuillaume Chatelet void writeStudy(const Study &S) { 302438f7fc0SSiva Chandra Reddy std::error_code EC; 303438f7fc0SSiva Chandra Reddy raw_fd_ostream FOS(Output, EC); 304438f7fc0SSiva Chandra Reddy if (EC) 305438f7fc0SSiva Chandra Reddy report_fatal_error(Twine("Could not open file: ") 306438f7fc0SSiva Chandra Reddy .concat(EC.message()) 307438f7fc0SSiva Chandra Reddy .concat(", ") 308438f7fc0SSiva Chandra Reddy .concat(Output)); 309438f7fc0SSiva Chandra Reddy json::OStream JOS(FOS); 310deae7e98SGuillaume Chatelet serializeToJson(S, JOS); 311ab577807SGuillaume Chatelet FOS << "\n"; 312deae7e98SGuillaume Chatelet } 313deae7e98SGuillaume Chatelet 314deae7e98SGuillaume Chatelet void main() { 315deae7e98SGuillaume Chatelet checkRequirements(); 316*8d64ed85SGuillaume Chatelet MemfunctionBenchmark MB; 317*8d64ed85SGuillaume Chatelet writeStudy(MB.run()); 318438f7fc0SSiva Chandra Reddy } 319438f7fc0SSiva Chandra Reddy 320438f7fc0SSiva Chandra Reddy } // namespace libc_benchmarks 321438f7fc0SSiva Chandra Reddy } // namespace llvm 322438f7fc0SSiva Chandra Reddy 323438f7fc0SSiva Chandra Reddy int main(int argc, char **argv) { 324438f7fc0SSiva Chandra Reddy llvm::cl::ParseCommandLineOptions(argc, argv); 325deae7e98SGuillaume Chatelet #ifndef NDEBUG 326deae7e98SGuillaume Chatelet static_assert( 327deae7e98SGuillaume Chatelet false, 328deae7e98SGuillaume Chatelet "For reproducibility benchmarks should not be compiled in DEBUG mode."); 329deae7e98SGuillaume Chatelet #endif 330deae7e98SGuillaume Chatelet llvm::libc_benchmarks::main(); 331438f7fc0SSiva Chandra Reddy return EXIT_SUCCESS; 332438f7fc0SSiva Chandra Reddy } 333