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::CounterGroup
>>
39 ExegesisTarget::createCounter(StringRef CounterName
, const LLVMState
&,
40 ArrayRef
<const char *> ValidationCounters
,
41 const pid_t ProcessID
) const {
42 pfm::PerfEvent
Event(CounterName
);
44 return make_error
<Failure
>(Twine("Unable to create counter with name '")
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
)
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) {
67 if (Target
->Next
!= nullptr)
68 return; // Already registered.
69 Target
->Next
= FirstTarget
;
73 std::unique_ptr
<SnippetGenerator
> ExegesisTarget::createSnippetGenerator(
74 Benchmark::ModeE Mode
, const LLVMState
&State
,
75 const SnippetGenerator::Options
&Opts
) const {
77 case Benchmark::Unknown
:
79 case Benchmark::Latency
:
80 return createSerialSnippetGenerator(State
, Opts
);
82 case Benchmark::InverseThroughput
:
83 return createParallelSnippetGenerator(State
, Opts
);
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();
97 case Benchmark::Unknown
:
99 case Benchmark::Latency
:
100 case Benchmark::InverseThroughput
:
101 if (BenchmarkPhaseSelector
== BenchmarkPhaseSelectorE::Measure
&&
102 !PfmCounters
.CycleCounter
) {
103 const char *ModeName
= Mode
== Benchmark::Latency
105 : "inverse_throughput";
106 return make_error
<Failure
>(
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
,
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,
169 const PfmCountersInfo
PfmCountersInfo::Dummy
= {
170 pfm::PerfEvent::DummyEventString
,
171 pfm::PerfEvent::DummyEventString
,
177 const PfmCountersInfo
&ExegesisTarget::getPfmCounters(StringRef CpuName
) const {
179 is_sorted(CpuPfmCounters
,
180 [](const CpuAndPfmCounters
&LHS
, const CpuAndPfmCounters
&RHS
) {
181 return strcmp(LHS
.CpuName
, RHS
.CpuName
) < 0;
183 "CpuPfmCounters table is not sorted");
186 auto Found
= lower_bound(CpuPfmCounters
, CpuName
);
187 if (Found
== CpuPfmCounters
.end() || StringRef(Found
->CpuName
) != CpuName
) {
189 if (!CpuPfmCounters
.empty() && CpuPfmCounters
.begin()->CpuName
[0] == '\0') {
190 Found
= CpuPfmCounters
.begin(); // The target specifies a default.
192 return PfmCountersInfo::Default
; // No default for the target.
195 assert(Found
->PCI
&& "Missing counters");
199 const PfmCountersInfo
&ExegesisTarget::getDummyPfmCounters() const {
200 return PfmCountersInfo::Dummy
;
203 ExegesisTarget::SavedState::~SavedState() {} // anchor.
207 bool opcodeIsNotAvailable(unsigned, const FeatureBitset
&) { return false; }
209 // Default implementation.
210 class ExegesisDefaultTarget
: public ExegesisTarget
{
212 ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable
) {}
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");
228 const ExegesisTarget
&ExegesisTarget::getDefault() {
229 static ExegesisDefaultTarget Target
;
233 } // namespace exegesis