xref: /openbsd-src/gnu/llvm/llvm/tools/llvm-exegesis/lib/Target.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
1 //===-- Target.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 //===----------------------------------------------------------------------===//
8 #include "Target.h"
9 
10 #include "LatencyBenchmarkRunner.h"
11 #include "ParallelSnippetGenerator.h"
12 #include "SerialSnippetGenerator.h"
13 #include "UopsBenchmarkRunner.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/Support/Error.h"
16 
17 namespace llvm {
18 namespace exegesis {
19 
20 cl::OptionCategory Options("llvm-exegesis options");
21 cl::OptionCategory BenchmarkOptions("llvm-exegesis benchmark options");
22 cl::OptionCategory AnalysisOptions("llvm-exegesis analysis options");
23 
~ExegesisTarget()24 ExegesisTarget::~ExegesisTarget() {} // anchor.
25 
26 static ExegesisTarget *FirstTarget = nullptr;
27 
lookup(Triple TT)28 const ExegesisTarget *ExegesisTarget::lookup(Triple TT) {
29   for (const ExegesisTarget *T = FirstTarget; T != nullptr; T = T->Next) {
30     if (T->matchesArch(TT.getArch()))
31       return T;
32   }
33   return nullptr;
34 }
35 
36 Expected<std::unique_ptr<pfm::Counter>>
createCounter(StringRef CounterName,const LLVMState &) const37 ExegesisTarget::createCounter(StringRef CounterName, const LLVMState &) const {
38   pfm::PerfEvent Event(CounterName);
39   if (!Event.valid())
40     return llvm::make_error<Failure>(
41         llvm::Twine("Unable to create counter with name '")
42             .concat(CounterName)
43             .concat("'"));
44 
45   return std::make_unique<pfm::Counter>(std::move(Event));
46 }
47 
registerTarget(ExegesisTarget * Target)48 void ExegesisTarget::registerTarget(ExegesisTarget *Target) {
49   if (FirstTarget == nullptr) {
50     FirstTarget = Target;
51     return;
52   }
53   if (Target->Next != nullptr)
54     return; // Already registered.
55   Target->Next = FirstTarget;
56   FirstTarget = Target;
57 }
58 
createSnippetGenerator(InstructionBenchmark::ModeE Mode,const LLVMState & State,const SnippetGenerator::Options & Opts) const59 std::unique_ptr<SnippetGenerator> ExegesisTarget::createSnippetGenerator(
60     InstructionBenchmark::ModeE Mode, const LLVMState &State,
61     const SnippetGenerator::Options &Opts) const {
62   switch (Mode) {
63   case InstructionBenchmark::Unknown:
64     return nullptr;
65   case InstructionBenchmark::Latency:
66     return createSerialSnippetGenerator(State, Opts);
67   case InstructionBenchmark::Uops:
68   case InstructionBenchmark::InverseThroughput:
69     return createParallelSnippetGenerator(State, Opts);
70   }
71   return nullptr;
72 }
73 
74 Expected<std::unique_ptr<BenchmarkRunner>>
createBenchmarkRunner(InstructionBenchmark::ModeE Mode,const LLVMState & State,BenchmarkPhaseSelectorE BenchmarkPhaseSelector,InstructionBenchmark::ResultAggregationModeE ResultAggMode) const75 ExegesisTarget::createBenchmarkRunner(
76     InstructionBenchmark::ModeE Mode, const LLVMState &State,
77     BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
78     InstructionBenchmark::ResultAggregationModeE ResultAggMode) const {
79   PfmCountersInfo PfmCounters = State.getPfmCounters();
80   switch (Mode) {
81   case InstructionBenchmark::Unknown:
82     return nullptr;
83   case InstructionBenchmark::Latency:
84   case InstructionBenchmark::InverseThroughput:
85     if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
86         !PfmCounters.CycleCounter) {
87       const char *ModeName = Mode == InstructionBenchmark::Latency
88                                  ? "latency"
89                                  : "inverse_throughput";
90       return make_error<Failure>(
91           Twine("can't run '")
92               .concat(ModeName)
93               .concat(
94                   "' mode, sched model does not define a cycle counter. You "
95                   "can pass --skip-measurements to skip the actual "
96                   "benchmarking."));
97     }
98     return createLatencyBenchmarkRunner(State, Mode, BenchmarkPhaseSelector,
99                                         ResultAggMode);
100   case InstructionBenchmark::Uops:
101     if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
102         !PfmCounters.UopsCounter && !PfmCounters.IssueCounters)
103       return make_error<Failure>(
104           "can't run 'uops' mode, sched model does not define uops or issue "
105           "counters. You can pass --skip-measurements to skip the actual "
106           "benchmarking.");
107     return createUopsBenchmarkRunner(State, BenchmarkPhaseSelector,
108                                      ResultAggMode);
109   }
110   return nullptr;
111 }
112 
createSerialSnippetGenerator(const LLVMState & State,const SnippetGenerator::Options & Opts) const113 std::unique_ptr<SnippetGenerator> ExegesisTarget::createSerialSnippetGenerator(
114     const LLVMState &State, const SnippetGenerator::Options &Opts) const {
115   return std::make_unique<SerialSnippetGenerator>(State, Opts);
116 }
117 
createParallelSnippetGenerator(const LLVMState & State,const SnippetGenerator::Options & Opts) const118 std::unique_ptr<SnippetGenerator> ExegesisTarget::createParallelSnippetGenerator(
119     const LLVMState &State, const SnippetGenerator::Options &Opts) const {
120   return std::make_unique<ParallelSnippetGenerator>(State, Opts);
121 }
122 
createLatencyBenchmarkRunner(const LLVMState & State,InstructionBenchmark::ModeE Mode,BenchmarkPhaseSelectorE BenchmarkPhaseSelector,InstructionBenchmark::ResultAggregationModeE ResultAggMode) const123 std::unique_ptr<BenchmarkRunner> ExegesisTarget::createLatencyBenchmarkRunner(
124     const LLVMState &State, InstructionBenchmark::ModeE Mode,
125     BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
126     InstructionBenchmark::ResultAggregationModeE ResultAggMode) const {
127   return std::make_unique<LatencyBenchmarkRunner>(
128       State, Mode, BenchmarkPhaseSelector, ResultAggMode);
129 }
130 
createUopsBenchmarkRunner(const LLVMState & State,BenchmarkPhaseSelectorE BenchmarkPhaseSelector,InstructionBenchmark::ResultAggregationModeE) const131 std::unique_ptr<BenchmarkRunner> ExegesisTarget::createUopsBenchmarkRunner(
132     const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
133     InstructionBenchmark::ResultAggregationModeE /*unused*/) const {
134   return std::make_unique<UopsBenchmarkRunner>(State, BenchmarkPhaseSelector);
135 }
136 
137 static_assert(std::is_pod<PfmCountersInfo>::value,
138               "We shouldn't have dynamic initialization here");
139 const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
140                                                   0u};
141 
getPfmCounters(StringRef CpuName) const142 const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
143   assert(llvm::is_sorted(
144              CpuPfmCounters,
145              [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
146                return strcmp(LHS.CpuName, RHS.CpuName) < 0;
147              }) &&
148          "CpuPfmCounters table is not sorted");
149 
150   // Find entry
151   auto Found = llvm::lower_bound(CpuPfmCounters, CpuName);
152   if (Found == CpuPfmCounters.end() || StringRef(Found->CpuName) != CpuName) {
153     // Use the default.
154     if (!CpuPfmCounters.empty() && CpuPfmCounters.begin()->CpuName[0] == '\0') {
155       Found = CpuPfmCounters.begin(); // The target specifies a default.
156     } else {
157       return PfmCountersInfo::Default; // No default for the target.
158     }
159   }
160   assert(Found->PCI && "Missing counters");
161   return *Found->PCI;
162 }
163 
~SavedState()164 ExegesisTarget::SavedState::~SavedState() {} // anchor.
165 
166 namespace {
167 
168 // Default implementation.
169 class ExegesisDefaultTarget : public ExegesisTarget {
170 public:
ExegesisDefaultTarget()171   ExegesisDefaultTarget() : ExegesisTarget({}) {}
172 
173 private:
setRegTo(const MCSubtargetInfo & STI,unsigned Reg,const APInt & Value) const174   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
175                                const APInt &Value) const override {
176     llvm_unreachable("Not yet implemented");
177   }
178 
matchesArch(Triple::ArchType Arch) const179   bool matchesArch(Triple::ArchType Arch) const override {
180     llvm_unreachable("never called");
181     return false;
182   }
183 };
184 
185 } // namespace
186 
getDefault()187 const ExegesisTarget &ExegesisTarget::getDefault() {
188   static ExegesisDefaultTarget Target;
189   return Target;
190 }
191 
192 } // namespace exegesis
193 } // namespace llvm
194