1 //===-- Target.cpp ----------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
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()))
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
);
43 return llvm::make_error
<Failure
>(
44 llvm::Twine("Unable to create counter with name '")
48 return std::make_unique
<pfm::Counter
>(std::move(Event
), ProcessID
);
51 void ExegesisTarget::registerTarget(ExegesisTarget
*Target
) {
52 if (FirstTarget
== nullptr) {
56 if (Target
->Next
!= nullptr)
57 return; // Already registered.
58 Target
->Next
= FirstTarget
;
62 std::unique_ptr
<SnippetGenerator
> ExegesisTarget::createSnippetGenerator(
63 Benchmark::ModeE Mode
, const LLVMState
&State
,
64 const SnippetGenerator::Options
&Opts
) const {
66 case Benchmark::Unknown
:
68 case Benchmark::Latency
:
69 return createSerialSnippetGenerator(State
, Opts
);
71 case Benchmark::InverseThroughput
:
72 return createParallelSnippetGenerator(State
, Opts
);
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();
85 case Benchmark::Unknown
:
87 case Benchmark::Latency
:
88 case Benchmark::InverseThroughput
:
89 if (BenchmarkPhaseSelector
== BenchmarkPhaseSelectorE::Measure
&&
90 !PfmCounters
.CycleCounter
) {
91 const char *ModeName
= Mode
== Benchmark::Latency
93 : "inverse_throughput";
94 return make_error
<Failure
>(
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
);
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
,
146 static_assert(std::is_trivial_v
<PfmCountersInfo
>,
147 "We shouldn't have dynamic initialization here");
148 const PfmCountersInfo
PfmCountersInfo::Default
= {nullptr, nullptr, nullptr,
150 const PfmCountersInfo
PfmCountersInfo::Dummy
= {
151 pfm::PerfEvent::DummyEventString
, pfm::PerfEvent::DummyEventString
, nullptr,
154 const PfmCountersInfo
&ExegesisTarget::getPfmCounters(StringRef CpuName
) const {
155 assert(llvm::is_sorted(
157 [](const CpuAndPfmCounters
&LHS
, const CpuAndPfmCounters
&RHS
) {
158 return strcmp(LHS
.CpuName
, RHS
.CpuName
) < 0;
160 "CpuPfmCounters table is not sorted");
163 auto Found
= llvm::lower_bound(CpuPfmCounters
, CpuName
);
164 if (Found
== CpuPfmCounters
.end() || StringRef(Found
->CpuName
) != CpuName
) {
166 if (!CpuPfmCounters
.empty() && CpuPfmCounters
.begin()->CpuName
[0] == '\0') {
167 Found
= CpuPfmCounters
.begin(); // The target specifies a default.
169 return PfmCountersInfo::Default
; // No default for the target.
172 assert(Found
->PCI
&& "Missing counters");
176 const PfmCountersInfo
&ExegesisTarget::getDummyPfmCounters() const {
177 return PfmCountersInfo::Dummy
;
180 ExegesisTarget::SavedState::~SavedState() {} // anchor.
184 bool opcodeIsNotAvailable(unsigned, const FeatureBitset
&) { return false; }
186 // Default implementation.
187 class ExegesisDefaultTarget
: public ExegesisTarget
{
189 ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable
) {}
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");
205 const ExegesisTarget
&ExegesisTarget::getDefault() {
206 static ExegesisDefaultTarget Target
;
210 } // namespace exegesis