Allow SymbolUserOpInterface operators to be used in RemoveDeadValues Pass (#117405)
[llvm-project.git] / llvm / tools / llvm-exegesis / lib / Target.cpp
blob29e58692f0e92b02b90e8316f6e0f4f4d0d6ce43
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"
10 #include "LatencyBenchmarkRunner.h"
11 #include "ParallelSnippetGenerator.h"
12 #include "PerfHelper.h"
13 #include "SerialSnippetGenerator.h"
14 #include "UopsBenchmarkRunner.h"
15 #include "llvm/ADT/Twine.h"
16 #include "llvm/Support/Error.h"
17 #include "llvm/TargetParser/SubtargetFeature.h"
19 namespace llvm {
20 namespace exegesis {
22 cl::OptionCategory Options("llvm-exegesis options");
23 cl::OptionCategory BenchmarkOptions("llvm-exegesis benchmark options");
24 cl::OptionCategory AnalysisOptions("llvm-exegesis analysis options");
26 ExegesisTarget::~ExegesisTarget() {} // anchor.
28 static ExegesisTarget *FirstTarget = nullptr;
30 const ExegesisTarget *ExegesisTarget::lookup(Triple TT) {
31 for (const ExegesisTarget *T = FirstTarget; T != nullptr; T = T->Next) {
32 if (T->matchesArch(TT.getArch()))
33 return T;
35 return nullptr;
38 Expected<std::unique_ptr<pfm::CounterGroup>>
39 ExegesisTarget::createCounter(StringRef CounterName, const LLVMState &,
40 ArrayRef<const char *> ValidationCounters,
41 const pid_t ProcessID) const {
42 pfm::PerfEvent Event(CounterName);
43 if (!Event.valid())
44 return make_error<Failure>(Twine("Unable to create counter with name '")
45 .concat(CounterName)
46 .concat("'"));
48 std::vector<pfm::PerfEvent> ValidationEvents;
49 for (const char *ValCounterName : ValidationCounters) {
50 ValidationEvents.emplace_back(ValCounterName);
51 if (!ValidationEvents.back().valid())
52 return make_error<Failure>(
53 Twine("Unable to create validation counter with name '")
54 .concat(ValCounterName)
55 .concat("'"));
58 return std::make_unique<pfm::CounterGroup>(
59 std::move(Event), std::move(ValidationEvents), ProcessID);
62 void ExegesisTarget::registerTarget(ExegesisTarget *Target) {
63 if (FirstTarget == nullptr) {
64 FirstTarget = Target;
65 return;
67 if (Target->Next != nullptr)
68 return; // Already registered.
69 Target->Next = FirstTarget;
70 FirstTarget = Target;
73 std::unique_ptr<SnippetGenerator> ExegesisTarget::createSnippetGenerator(
74 Benchmark::ModeE Mode, const LLVMState &State,
75 const SnippetGenerator::Options &Opts) const {
76 switch (Mode) {
77 case Benchmark::Unknown:
78 return nullptr;
79 case Benchmark::Latency:
80 return createSerialSnippetGenerator(State, Opts);
81 case Benchmark::Uops:
82 case Benchmark::InverseThroughput:
83 return createParallelSnippetGenerator(State, Opts);
85 return nullptr;
88 Expected<std::unique_ptr<BenchmarkRunner>>
89 ExegesisTarget::createBenchmarkRunner(
90 Benchmark::ModeE Mode, const LLVMState &State,
91 BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
92 BenchmarkRunner::ExecutionModeE ExecutionMode,
93 unsigned BenchmarkRepeatCount, ArrayRef<ValidationEvent> ValidationCounters,
94 Benchmark::ResultAggregationModeE ResultAggMode) const {
95 PfmCountersInfo PfmCounters = State.getPfmCounters();
96 switch (Mode) {
97 case Benchmark::Unknown:
98 return nullptr;
99 case Benchmark::Latency:
100 case Benchmark::InverseThroughput:
101 if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
102 !PfmCounters.CycleCounter) {
103 const char *ModeName = Mode == Benchmark::Latency
104 ? "latency"
105 : "inverse_throughput";
106 return make_error<Failure>(
107 Twine("can't run '")
108 .concat(ModeName)
109 .concat(
110 "' mode, sched model does not define a cycle counter. You "
111 "can pass --benchmark-phase=... to skip the actual "
112 "benchmarking or --use-dummy-perf-counters to not query "
113 "the kernel for real event counts."));
115 return createLatencyBenchmarkRunner(
116 State, Mode, BenchmarkPhaseSelector, ResultAggMode, ExecutionMode,
117 ValidationCounters, BenchmarkRepeatCount);
118 case Benchmark::Uops:
119 if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
120 !PfmCounters.UopsCounter && !PfmCounters.IssueCounters)
121 return make_error<Failure>(
122 "can't run 'uops' mode, sched model does not define uops or issue "
123 "counters. You can pass --benchmark-phase=... to skip the actual "
124 "benchmarking or --use-dummy-perf-counters to not query the kernel "
125 "for real event counts.");
126 return createUopsBenchmarkRunner(State, BenchmarkPhaseSelector,
127 ResultAggMode, ExecutionMode,
128 ValidationCounters);
130 return nullptr;
133 std::unique_ptr<SnippetGenerator> ExegesisTarget::createSerialSnippetGenerator(
134 const LLVMState &State, const SnippetGenerator::Options &Opts) const {
135 return std::make_unique<SerialSnippetGenerator>(State, Opts);
138 std::unique_ptr<SnippetGenerator> ExegesisTarget::createParallelSnippetGenerator(
139 const LLVMState &State, const SnippetGenerator::Options &Opts) const {
140 return std::make_unique<ParallelSnippetGenerator>(State, Opts);
143 std::unique_ptr<BenchmarkRunner> ExegesisTarget::createLatencyBenchmarkRunner(
144 const LLVMState &State, Benchmark::ModeE Mode,
145 BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
146 Benchmark::ResultAggregationModeE ResultAggMode,
147 BenchmarkRunner::ExecutionModeE ExecutionMode,
148 ArrayRef<ValidationEvent> ValidationCounters,
149 unsigned BenchmarkRepeatCount) const {
150 return std::make_unique<LatencyBenchmarkRunner>(
151 State, Mode, BenchmarkPhaseSelector, ResultAggMode, ExecutionMode,
152 ValidationCounters, BenchmarkRepeatCount);
155 std::unique_ptr<BenchmarkRunner> ExegesisTarget::createUopsBenchmarkRunner(
156 const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
157 Benchmark::ResultAggregationModeE /*unused*/,
158 BenchmarkRunner::ExecutionModeE ExecutionMode,
159 ArrayRef<ValidationEvent> ValidationCounters) const {
160 return std::make_unique<UopsBenchmarkRunner>(
161 State, BenchmarkPhaseSelector, ExecutionMode, ValidationCounters);
164 static_assert(std::is_trivial_v<PfmCountersInfo>,
165 "We shouldn't have dynamic initialization here");
167 const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
168 0u, nullptr, 0u};
169 const PfmCountersInfo PfmCountersInfo::Dummy = {
170 pfm::PerfEvent::DummyEventString,
171 pfm::PerfEvent::DummyEventString,
172 nullptr,
174 nullptr,
175 0u};
177 const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
178 assert(
179 is_sorted(CpuPfmCounters,
180 [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
181 return strcmp(LHS.CpuName, RHS.CpuName) < 0;
182 }) &&
183 "CpuPfmCounters table is not sorted");
185 // Find entry
186 auto Found = lower_bound(CpuPfmCounters, CpuName);
187 if (Found == CpuPfmCounters.end() || StringRef(Found->CpuName) != CpuName) {
188 // Use the default.
189 if (!CpuPfmCounters.empty() && CpuPfmCounters.begin()->CpuName[0] == '\0') {
190 Found = CpuPfmCounters.begin(); // The target specifies a default.
191 } else {
192 return PfmCountersInfo::Default; // No default for the target.
195 assert(Found->PCI && "Missing counters");
196 return *Found->PCI;
199 const PfmCountersInfo &ExegesisTarget::getDummyPfmCounters() const {
200 return PfmCountersInfo::Dummy;
203 ExegesisTarget::SavedState::~SavedState() {} // anchor.
205 namespace {
207 bool opcodeIsNotAvailable(unsigned, const FeatureBitset &) { return false; }
209 // Default implementation.
210 class ExegesisDefaultTarget : public ExegesisTarget {
211 public:
212 ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable) {}
214 private:
215 std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
216 const APInt &Value) const override {
217 llvm_unreachable("Not yet implemented");
220 bool matchesArch(Triple::ArchType Arch) const override {
221 llvm_unreachable("never called");
222 return false;
226 } // namespace
228 const ExegesisTarget &ExegesisTarget::getDefault() {
229 static ExegesisDefaultTarget Target;
230 return Target;
233 } // namespace exegesis
234 } // namespace llvm