[RISCV] Eliminate dead li after emitting VSETVLIs (#65934)
[llvm-project.git] / llvm / tools / llvm-exegesis / lib / LatencyBenchmarkRunner.cpp
blobeda450579a5838c36da535911cd1184634d9791a
1 //===-- LatencyBenchmarkRunner.cpp ------------------------------*- C++ -*-===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "LatencyBenchmarkRunner.h"
11 #include "BenchmarkRunner.h"
12 #include "Target.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/Support/Error.h"
15 #include <algorithm>
16 #include <cmath>
18 namespace llvm {
19 namespace exegesis {
21 LatencyBenchmarkRunner::LatencyBenchmarkRunner(
22 const LLVMState &State, Benchmark::ModeE Mode,
23 BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
24 Benchmark::ResultAggregationModeE ResultAgg, ExecutionModeE ExecutionMode,
25 unsigned BenchmarkRepeatCount)
26 : BenchmarkRunner(State, Mode, BenchmarkPhaseSelector, ExecutionMode) {
27 assert((Mode == Benchmark::Latency || Mode == Benchmark::InverseThroughput) &&
28 "invalid mode");
29 ResultAggMode = ResultAgg;
30 NumMeasurements = BenchmarkRepeatCount;
33 LatencyBenchmarkRunner::~LatencyBenchmarkRunner() = default;
35 static double computeVariance(const llvm::SmallVector<int64_t, 4> &Values) {
36 if (Values.empty())
37 return 0.0;
38 double Sum = std::accumulate(Values.begin(), Values.end(), 0.0);
40 const double Mean = Sum / Values.size();
41 double Ret = 0;
42 for (const auto &V : Values) {
43 double Delta = V - Mean;
44 Ret += Delta * Delta;
46 return Ret / Values.size();
49 static int64_t findMin(const llvm::SmallVector<int64_t, 4> &Values) {
50 if (Values.empty())
51 return 0;
52 return *std::min_element(Values.begin(), Values.end());
55 static int64_t findMax(const llvm::SmallVector<int64_t, 4> &Values) {
56 if (Values.empty())
57 return 0;
58 return *std::max_element(Values.begin(), Values.end());
61 static int64_t findMean(const llvm::SmallVector<int64_t, 4> &Values) {
62 if (Values.empty())
63 return 0;
64 return std::accumulate(Values.begin(), Values.end(), 0.0) /
65 static_cast<double>(Values.size());
68 Expected<std::vector<BenchmarkMeasure>> LatencyBenchmarkRunner::runMeasurements(
69 const FunctionExecutor &Executor) const {
70 // Cycle measurements include some overhead from the kernel. Repeat the
71 // measure several times and return the aggregated value, as specified by
72 // ResultAggMode.
73 llvm::SmallVector<int64_t, 4> AccumulatedValues;
74 double MinVariance = std::numeric_limits<double>::infinity();
75 const char *CounterName = State.getPfmCounters().CycleCounter;
76 // Values count for each run.
77 int ValuesCount = 0;
78 for (size_t I = 0; I < NumMeasurements; ++I) {
79 auto ExpectedCounterValues = Executor.runAndSample(CounterName);
80 if (!ExpectedCounterValues)
81 return ExpectedCounterValues.takeError();
82 ValuesCount = ExpectedCounterValues.get().size();
83 if (ValuesCount == 1)
84 AccumulatedValues.push_back(ExpectedCounterValues.get()[0]);
85 else {
86 // We'll keep the reading with lowest variance (ie., most stable)
87 double Variance = computeVariance(*ExpectedCounterValues);
88 if (MinVariance > Variance) {
89 AccumulatedValues = std::move(ExpectedCounterValues.get());
90 MinVariance = Variance;
95 std::string ModeName;
96 switch (Mode) {
97 case Benchmark::Latency:
98 ModeName = "latency";
99 break;
100 case Benchmark::InverseThroughput:
101 ModeName = "inverse_throughput";
102 break;
103 default:
104 break;
107 switch (ResultAggMode) {
108 case Benchmark::MinVariance: {
109 if (ValuesCount == 1)
110 llvm::errs() << "Each sample only has one value. result-aggregation-mode "
111 "of min-variance is probably non-sensical\n";
112 std::vector<BenchmarkMeasure> Result;
113 Result.reserve(AccumulatedValues.size());
114 for (const int64_t Value : AccumulatedValues)
115 Result.push_back(BenchmarkMeasure::Create(ModeName, Value));
116 return std::move(Result);
118 case Benchmark::Min: {
119 std::vector<BenchmarkMeasure> Result;
120 Result.push_back(
121 BenchmarkMeasure::Create(ModeName, findMin(AccumulatedValues)));
122 return std::move(Result);
124 case Benchmark::Max: {
125 std::vector<BenchmarkMeasure> Result;
126 Result.push_back(
127 BenchmarkMeasure::Create(ModeName, findMax(AccumulatedValues)));
128 return std::move(Result);
130 case Benchmark::Mean: {
131 std::vector<BenchmarkMeasure> Result;
132 Result.push_back(
133 BenchmarkMeasure::Create(ModeName, findMean(AccumulatedValues)));
134 return std::move(Result);
137 return llvm::make_error<Failure>(llvm::Twine("Unexpected benchmark mode(")
138 .concat(std::to_string(Mode))
139 .concat(" and unexpected ResultAggMode ")
140 .concat(std::to_string(ResultAggMode)));
143 } // namespace exegesis
144 } // namespace llvm