1*438f7fc0SSiva Chandra Reddy //===-- Benchmark ---------------------------------------------------------===//
2*438f7fc0SSiva Chandra Reddy //
3*438f7fc0SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*438f7fc0SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5*438f7fc0SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*438f7fc0SSiva Chandra Reddy //
7*438f7fc0SSiva Chandra Reddy //===----------------------------------------------------------------------===//
8*438f7fc0SSiva Chandra Reddy 
9*438f7fc0SSiva Chandra Reddy #include "LibcMemoryBenchmarkMain.h"
10*438f7fc0SSiva Chandra Reddy #include "JSON.h"
11*438f7fc0SSiva Chandra Reddy #include "LibcBenchmark.h"
12*438f7fc0SSiva Chandra Reddy #include "LibcMemoryBenchmark.h"
13*438f7fc0SSiva Chandra Reddy #include "llvm/Support/CommandLine.h"
14*438f7fc0SSiva Chandra Reddy #include "llvm/Support/ErrorHandling.h"
15*438f7fc0SSiva Chandra Reddy #include "llvm/Support/FileSystem.h"
16*438f7fc0SSiva Chandra Reddy #include "llvm/Support/JSON.h"
17*438f7fc0SSiva Chandra Reddy #include "llvm/Support/MemoryBuffer.h"
18*438f7fc0SSiva Chandra Reddy #include "llvm/Support/raw_ostream.h"
19*438f7fc0SSiva Chandra Reddy 
20*438f7fc0SSiva Chandra Reddy #include <string>
21*438f7fc0SSiva Chandra Reddy 
22*438f7fc0SSiva Chandra Reddy namespace llvm {
23*438f7fc0SSiva Chandra Reddy namespace libc_benchmarks {
24*438f7fc0SSiva Chandra Reddy 
25*438f7fc0SSiva Chandra Reddy static cl::opt<std::string>
26*438f7fc0SSiva Chandra Reddy     Configuration("conf", cl::desc("Specify configuration filename"),
27*438f7fc0SSiva Chandra Reddy                   cl::value_desc("filename"), cl::init(""));
28*438f7fc0SSiva Chandra Reddy 
29*438f7fc0SSiva Chandra Reddy static cl::opt<std::string> Output("o", cl::desc("Specify output filename"),
30*438f7fc0SSiva Chandra Reddy                                    cl::value_desc("filename"), cl::init("-"));
31*438f7fc0SSiva Chandra Reddy 
32*438f7fc0SSiva Chandra Reddy extern std::unique_ptr<BenchmarkRunner>
33*438f7fc0SSiva Chandra Reddy getRunner(const StudyConfiguration &Conf);
34*438f7fc0SSiva Chandra Reddy 
35*438f7fc0SSiva Chandra Reddy void Main() {
36*438f7fc0SSiva Chandra Reddy #ifndef NDEBUG
37*438f7fc0SSiva Chandra Reddy   static_assert(
38*438f7fc0SSiva Chandra Reddy       false,
39*438f7fc0SSiva Chandra Reddy       "For reproducibility benchmarks should not be compiled in DEBUG mode.");
40*438f7fc0SSiva Chandra Reddy #endif
41*438f7fc0SSiva Chandra Reddy   checkRequirements();
42*438f7fc0SSiva Chandra Reddy   ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
43*438f7fc0SSiva Chandra Reddy       MemoryBuffer::getFileOrSTDIN(Configuration);
44*438f7fc0SSiva Chandra Reddy   if (!MB)
45*438f7fc0SSiva Chandra Reddy     report_fatal_error(
46*438f7fc0SSiva Chandra Reddy         Twine("Could not open configuration file: ").concat(Configuration));
47*438f7fc0SSiva Chandra Reddy   auto ErrorOrStudy = ParseJsonStudy((*MB)->getBuffer());
48*438f7fc0SSiva Chandra Reddy   if (!ErrorOrStudy)
49*438f7fc0SSiva Chandra Reddy     report_fatal_error(ErrorOrStudy.takeError());
50*438f7fc0SSiva Chandra Reddy 
51*438f7fc0SSiva Chandra Reddy   const auto StudyPrototype = *ErrorOrStudy;
52*438f7fc0SSiva Chandra Reddy 
53*438f7fc0SSiva Chandra Reddy   Study S;
54*438f7fc0SSiva Chandra Reddy   S.Host = HostState::get();
55*438f7fc0SSiva Chandra Reddy   S.Options = StudyPrototype.Options;
56*438f7fc0SSiva Chandra Reddy   S.Configuration = StudyPrototype.Configuration;
57*438f7fc0SSiva Chandra Reddy 
58*438f7fc0SSiva Chandra Reddy   const auto Runs = S.Configuration.Runs;
59*438f7fc0SSiva Chandra Reddy   const auto &SR = S.Configuration.Size;
60*438f7fc0SSiva Chandra Reddy   std::unique_ptr<BenchmarkRunner> Runner = getRunner(S.Configuration);
61*438f7fc0SSiva Chandra Reddy   const size_t TotalSteps =
62*438f7fc0SSiva Chandra Reddy       Runner->getFunctionNames().size() * Runs * ((SR.To - SR.From) / SR.Step);
63*438f7fc0SSiva Chandra Reddy   size_t Steps = 0;
64*438f7fc0SSiva Chandra Reddy   for (auto FunctionName : Runner->getFunctionNames()) {
65*438f7fc0SSiva Chandra Reddy     FunctionMeasurements FM;
66*438f7fc0SSiva Chandra Reddy     FM.Name = std::string(FunctionName);
67*438f7fc0SSiva Chandra Reddy     for (size_t Run = 0; Run < Runs; ++Run) {
68*438f7fc0SSiva Chandra Reddy       for (uint32_t Size = SR.From; Size <= SR.To; Size += SR.Step) {
69*438f7fc0SSiva Chandra Reddy         const auto Result = Runner->benchmark(S.Options, FunctionName, Size);
70*438f7fc0SSiva Chandra Reddy         Measurement Measurement;
71*438f7fc0SSiva Chandra Reddy         Measurement.Runtime = Result.BestGuess;
72*438f7fc0SSiva Chandra Reddy         Measurement.Size = Size;
73*438f7fc0SSiva Chandra Reddy         FM.Measurements.push_back(Measurement);
74*438f7fc0SSiva Chandra Reddy         outs() << format("%3d%% run: %2d / %2d size: %5d ",
75*438f7fc0SSiva Chandra Reddy                          (Steps * 100 / TotalSteps), Run, Runs, Size)
76*438f7fc0SSiva Chandra Reddy                << FunctionName
77*438f7fc0SSiva Chandra Reddy                << "                                                  \r";
78*438f7fc0SSiva Chandra Reddy         ++Steps;
79*438f7fc0SSiva Chandra Reddy       }
80*438f7fc0SSiva Chandra Reddy     }
81*438f7fc0SSiva Chandra Reddy     S.Functions.push_back(std::move(FM));
82*438f7fc0SSiva Chandra Reddy   }
83*438f7fc0SSiva Chandra Reddy 
84*438f7fc0SSiva Chandra Reddy   std::error_code EC;
85*438f7fc0SSiva Chandra Reddy   raw_fd_ostream FOS(Output, EC);
86*438f7fc0SSiva Chandra Reddy   if (EC)
87*438f7fc0SSiva Chandra Reddy     report_fatal_error(Twine("Could not open file: ")
88*438f7fc0SSiva Chandra Reddy                            .concat(EC.message())
89*438f7fc0SSiva Chandra Reddy                            .concat(", ")
90*438f7fc0SSiva Chandra Reddy                            .concat(Output));
91*438f7fc0SSiva Chandra Reddy   json::OStream JOS(FOS);
92*438f7fc0SSiva Chandra Reddy   SerializeToJson(S, JOS);
93*438f7fc0SSiva Chandra Reddy }
94*438f7fc0SSiva Chandra Reddy 
95*438f7fc0SSiva Chandra Reddy } // namespace libc_benchmarks
96*438f7fc0SSiva Chandra Reddy } // namespace llvm
97*438f7fc0SSiva Chandra Reddy 
98*438f7fc0SSiva Chandra Reddy int main(int argc, char **argv) {
99*438f7fc0SSiva Chandra Reddy   llvm::cl::ParseCommandLineOptions(argc, argv);
100*438f7fc0SSiva Chandra Reddy   llvm::libc_benchmarks::Main();
101*438f7fc0SSiva Chandra Reddy   return EXIT_SUCCESS;
102*438f7fc0SSiva Chandra Reddy }
103