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 "SerialSnippetGenerator.h"
13 #include "UopsBenchmarkRunner.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/Support/Error.h"
20 ExegesisTarget::~ExegesisTarget() {} // anchor.
22 static ExegesisTarget
*FirstTarget
= nullptr;
24 const ExegesisTarget
*ExegesisTarget::lookup(Triple TT
) {
25 for (const ExegesisTarget
*T
= FirstTarget
; T
!= nullptr; T
= T
->Next
) {
26 if (T
->matchesArch(TT
.getArch()))
32 Expected
<std::unique_ptr
<pfm::Counter
>>
33 ExegesisTarget::createCounter(StringRef CounterName
, const LLVMState
&) const {
34 pfm::PerfEvent
Event(CounterName
);
36 return llvm::make_error
<Failure
>(
37 llvm::Twine("Unable to create counter with name '")
41 return std::make_unique
<pfm::Counter
>(std::move(Event
));
44 void ExegesisTarget::registerTarget(ExegesisTarget
*Target
) {
45 if (FirstTarget
== nullptr) {
49 if (Target
->Next
!= nullptr)
50 return; // Already registered.
51 Target
->Next
= FirstTarget
;
55 std::unique_ptr
<SnippetGenerator
> ExegesisTarget::createSnippetGenerator(
56 InstructionBenchmark::ModeE Mode
, const LLVMState
&State
,
57 const SnippetGenerator::Options
&Opts
) const {
59 case InstructionBenchmark::Unknown
:
61 case InstructionBenchmark::Latency
:
62 return createSerialSnippetGenerator(State
, Opts
);
63 case InstructionBenchmark::Uops
:
64 case InstructionBenchmark::InverseThroughput
:
65 return createParallelSnippetGenerator(State
, Opts
);
70 Expected
<std::unique_ptr
<BenchmarkRunner
>>
71 ExegesisTarget::createBenchmarkRunner(
72 InstructionBenchmark::ModeE Mode
, const LLVMState
&State
,
73 InstructionBenchmark::ResultAggregationModeE ResultAggMode
) const {
74 PfmCountersInfo PfmCounters
= State
.getPfmCounters();
76 case InstructionBenchmark::Unknown
:
78 case InstructionBenchmark::Latency
:
79 case InstructionBenchmark::InverseThroughput
:
80 if (!PfmCounters
.CycleCounter
) {
81 const char *ModeName
= Mode
== InstructionBenchmark::Latency
83 : "inverse_throughput";
84 return make_error
<Failure
>(
87 .concat("' mode, sched model does not define a cycle counter."));
89 return createLatencyBenchmarkRunner(State
, Mode
, ResultAggMode
);
90 case InstructionBenchmark::Uops
:
91 if (!PfmCounters
.UopsCounter
&& !PfmCounters
.IssueCounters
)
92 return make_error
<Failure
>("can't run 'uops' mode, sched model does not "
93 "define uops or issue counters.");
94 return createUopsBenchmarkRunner(State
, ResultAggMode
);
99 std::unique_ptr
<SnippetGenerator
> ExegesisTarget::createSerialSnippetGenerator(
100 const LLVMState
&State
, const SnippetGenerator::Options
&Opts
) const {
101 return std::make_unique
<SerialSnippetGenerator
>(State
, Opts
);
104 std::unique_ptr
<SnippetGenerator
> ExegesisTarget::createParallelSnippetGenerator(
105 const LLVMState
&State
, const SnippetGenerator::Options
&Opts
) const {
106 return std::make_unique
<ParallelSnippetGenerator
>(State
, Opts
);
109 std::unique_ptr
<BenchmarkRunner
> ExegesisTarget::createLatencyBenchmarkRunner(
110 const LLVMState
&State
, InstructionBenchmark::ModeE Mode
,
111 InstructionBenchmark::ResultAggregationModeE ResultAggMode
) const {
112 return std::make_unique
<LatencyBenchmarkRunner
>(State
, Mode
, ResultAggMode
);
115 std::unique_ptr
<BenchmarkRunner
> ExegesisTarget::createUopsBenchmarkRunner(
116 const LLVMState
&State
,
117 InstructionBenchmark::ResultAggregationModeE
/*unused*/) const {
118 return std::make_unique
<UopsBenchmarkRunner
>(State
);
121 static_assert(std::is_pod
<PfmCountersInfo
>::value
,
122 "We shouldn't have dynamic initialization here");
123 const PfmCountersInfo
PfmCountersInfo::Default
= {nullptr, nullptr, nullptr,
126 const PfmCountersInfo
&ExegesisTarget::getPfmCounters(StringRef CpuName
) const {
127 assert(llvm::is_sorted(
129 [](const CpuAndPfmCounters
&LHS
, const CpuAndPfmCounters
&RHS
) {
130 return strcmp(LHS
.CpuName
, RHS
.CpuName
) < 0;
132 "CpuPfmCounters table is not sorted");
135 auto Found
= llvm::lower_bound(CpuPfmCounters
, CpuName
);
136 if (Found
== CpuPfmCounters
.end() || StringRef(Found
->CpuName
) != CpuName
) {
138 if (!CpuPfmCounters
.empty() && CpuPfmCounters
.begin()->CpuName
[0] == '\0') {
139 Found
= CpuPfmCounters
.begin(); // The target specifies a default.
141 return PfmCountersInfo::Default
; // No default for the target.
144 assert(Found
->PCI
&& "Missing counters");
148 ExegesisTarget::SavedState::~SavedState() {} // anchor.
152 // Default implementation.
153 class ExegesisDefaultTarget
: public ExegesisTarget
{
155 ExegesisDefaultTarget() : ExegesisTarget({}) {}
158 std::vector
<MCInst
> setRegTo(const MCSubtargetInfo
&STI
, unsigned Reg
,
159 const APInt
&Value
) const override
{
160 llvm_unreachable("Not yet implemented");
163 bool matchesArch(Triple::ArchType Arch
) const override
{
164 llvm_unreachable("never called");
171 const ExegesisTarget
&ExegesisTarget::getDefault() {
172 static ExegesisDefaultTarget Target
;
176 } // namespace exegesis