Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / tools / llvm-exegesis / lib / Target.cpp
blobaed093548f1580c24f1e18689280860a62d4e882
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::Counter>>
39 ExegesisTarget::createCounter(StringRef CounterName, const LLVMState &,
40 const pid_t ProcessID) const {
41 pfm::PerfEvent Event(CounterName);
42 if (!Event.valid())
43 return llvm::make_error<Failure>(
44 llvm::Twine("Unable to create counter with name '")
45 .concat(CounterName)
46 .concat("'"));
48 return std::make_unique<pfm::Counter>(std::move(Event), ProcessID);
51 void ExegesisTarget::registerTarget(ExegesisTarget *Target) {
52 if (FirstTarget == nullptr) {
53 FirstTarget = Target;
54 return;
56 if (Target->Next != nullptr)
57 return; // Already registered.
58 Target->Next = FirstTarget;
59 FirstTarget = Target;
62 std::unique_ptr<SnippetGenerator> ExegesisTarget::createSnippetGenerator(
63 Benchmark::ModeE Mode, const LLVMState &State,
64 const SnippetGenerator::Options &Opts) const {
65 switch (Mode) {
66 case Benchmark::Unknown:
67 return nullptr;
68 case Benchmark::Latency:
69 return createSerialSnippetGenerator(State, Opts);
70 case Benchmark::Uops:
71 case Benchmark::InverseThroughput:
72 return createParallelSnippetGenerator(State, Opts);
74 return nullptr;
77 Expected<std::unique_ptr<BenchmarkRunner>>
78 ExegesisTarget::createBenchmarkRunner(
79 Benchmark::ModeE Mode, const LLVMState &State,
80 BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
81 BenchmarkRunner::ExecutionModeE ExecutionMode,
82 Benchmark::ResultAggregationModeE ResultAggMode) const {
83 PfmCountersInfo PfmCounters = State.getPfmCounters();
84 switch (Mode) {
85 case Benchmark::Unknown:
86 return nullptr;
87 case Benchmark::Latency:
88 case Benchmark::InverseThroughput:
89 if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
90 !PfmCounters.CycleCounter) {
91 const char *ModeName = Mode == Benchmark::Latency
92 ? "latency"
93 : "inverse_throughput";
94 return make_error<Failure>(
95 Twine("can't run '")
96 .concat(ModeName)
97 .concat(
98 "' mode, sched model does not define a cycle counter. You "
99 "can pass --benchmark-phase=... to skip the actual "
100 "benchmarking or --use-dummy-perf-counters to not query "
101 "the kernel for real event counts."));
103 return createLatencyBenchmarkRunner(State, Mode, BenchmarkPhaseSelector,
104 ResultAggMode, ExecutionMode);
105 case Benchmark::Uops:
106 if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
107 !PfmCounters.UopsCounter && !PfmCounters.IssueCounters)
108 return make_error<Failure>(
109 "can't run 'uops' mode, sched model does not define uops or issue "
110 "counters. You can pass --benchmark-phase=... to skip the actual "
111 "benchmarking or --use-dummy-perf-counters to not query the kernel "
112 "for real event counts.");
113 return createUopsBenchmarkRunner(State, BenchmarkPhaseSelector,
114 ResultAggMode, ExecutionMode);
116 return nullptr;
119 std::unique_ptr<SnippetGenerator> ExegesisTarget::createSerialSnippetGenerator(
120 const LLVMState &State, const SnippetGenerator::Options &Opts) const {
121 return std::make_unique<SerialSnippetGenerator>(State, Opts);
124 std::unique_ptr<SnippetGenerator> ExegesisTarget::createParallelSnippetGenerator(
125 const LLVMState &State, const SnippetGenerator::Options &Opts) const {
126 return std::make_unique<ParallelSnippetGenerator>(State, Opts);
129 std::unique_ptr<BenchmarkRunner> ExegesisTarget::createLatencyBenchmarkRunner(
130 const LLVMState &State, Benchmark::ModeE Mode,
131 BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
132 Benchmark::ResultAggregationModeE ResultAggMode,
133 BenchmarkRunner::ExecutionModeE ExecutionMode) const {
134 return std::make_unique<LatencyBenchmarkRunner>(
135 State, Mode, BenchmarkPhaseSelector, ResultAggMode, ExecutionMode);
138 std::unique_ptr<BenchmarkRunner> ExegesisTarget::createUopsBenchmarkRunner(
139 const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
140 Benchmark::ResultAggregationModeE /*unused*/,
141 BenchmarkRunner::ExecutionModeE ExecutionMode) const {
142 return std::make_unique<UopsBenchmarkRunner>(State, BenchmarkPhaseSelector,
143 ExecutionMode);
146 static_assert(std::is_trivial_v<PfmCountersInfo>,
147 "We shouldn't have dynamic initialization here");
148 const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
149 0u};
150 const PfmCountersInfo PfmCountersInfo::Dummy = {
151 pfm::PerfEvent::DummyEventString, pfm::PerfEvent::DummyEventString, nullptr,
152 0u};
154 const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
155 assert(llvm::is_sorted(
156 CpuPfmCounters,
157 [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
158 return strcmp(LHS.CpuName, RHS.CpuName) < 0;
159 }) &&
160 "CpuPfmCounters table is not sorted");
162 // Find entry
163 auto Found = llvm::lower_bound(CpuPfmCounters, CpuName);
164 if (Found == CpuPfmCounters.end() || StringRef(Found->CpuName) != CpuName) {
165 // Use the default.
166 if (!CpuPfmCounters.empty() && CpuPfmCounters.begin()->CpuName[0] == '\0') {
167 Found = CpuPfmCounters.begin(); // The target specifies a default.
168 } else {
169 return PfmCountersInfo::Default; // No default for the target.
172 assert(Found->PCI && "Missing counters");
173 return *Found->PCI;
176 const PfmCountersInfo &ExegesisTarget::getDummyPfmCounters() const {
177 return PfmCountersInfo::Dummy;
180 ExegesisTarget::SavedState::~SavedState() {} // anchor.
182 namespace {
184 bool opcodeIsNotAvailable(unsigned, const FeatureBitset &) { return false; }
186 // Default implementation.
187 class ExegesisDefaultTarget : public ExegesisTarget {
188 public:
189 ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable) {}
191 private:
192 std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
193 const APInt &Value) const override {
194 llvm_unreachable("Not yet implemented");
197 bool matchesArch(Triple::ArchType Arch) const override {
198 llvm_unreachable("never called");
199 return false;
203 } // namespace
205 const ExegesisTarget &ExegesisTarget::getDefault() {
206 static ExegesisDefaultTarget Target;
207 return Target;
210 } // namespace exegesis
211 } // namespace llvm