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"
18 ExegesisTarget::~ExegesisTarget() {} // anchor.
20 static ExegesisTarget
*FirstTarget
= nullptr;
22 const ExegesisTarget
*ExegesisTarget::lookup(Triple TT
) {
23 for (const ExegesisTarget
*T
= FirstTarget
; T
!= nullptr; T
= T
->Next
) {
24 if (T
->matchesArch(TT
.getArch()))
30 void ExegesisTarget::registerTarget(ExegesisTarget
*Target
) {
31 if (FirstTarget
== nullptr) {
35 if (Target
->Next
!= nullptr)
36 return; // Already registered.
37 Target
->Next
= FirstTarget
;
41 std::unique_ptr
<SnippetGenerator
> ExegesisTarget::createSnippetGenerator(
42 InstructionBenchmark::ModeE Mode
, const LLVMState
&State
,
43 const SnippetGenerator::Options
&Opts
) const {
45 case InstructionBenchmark::Unknown
:
47 case InstructionBenchmark::Latency
:
48 return createSerialSnippetGenerator(State
, Opts
);
49 case InstructionBenchmark::Uops
:
50 case InstructionBenchmark::InverseThroughput
:
51 return createParallelSnippetGenerator(State
, Opts
);
56 std::unique_ptr
<BenchmarkRunner
>
57 ExegesisTarget::createBenchmarkRunner(InstructionBenchmark::ModeE Mode
,
58 const LLVMState
&State
) const {
59 PfmCountersInfo PfmCounters
= State
.getPfmCounters();
61 case InstructionBenchmark::Unknown
:
63 case InstructionBenchmark::Latency
:
64 case InstructionBenchmark::InverseThroughput
:
65 if (!PfmCounters
.CycleCounter
) {
66 const char *ModeName
= Mode
== InstructionBenchmark::Latency
68 : "inverse_throughput";
69 report_fatal_error(Twine("can't run '").concat(ModeName
).concat("' mode, "
70 "sched model does not define a cycle counter."));
72 return createLatencyBenchmarkRunner(State
, Mode
);
73 case InstructionBenchmark::Uops
:
74 if (!PfmCounters
.UopsCounter
&& !PfmCounters
.IssueCounters
)
75 report_fatal_error("can't run 'uops' mode, sched model does not define "
76 "uops or issue counters.");
77 return createUopsBenchmarkRunner(State
);
82 std::unique_ptr
<SnippetGenerator
> ExegesisTarget::createSerialSnippetGenerator(
83 const LLVMState
&State
, const SnippetGenerator::Options
&Opts
) const {
84 return std::make_unique
<SerialSnippetGenerator
>(State
, Opts
);
87 std::unique_ptr
<SnippetGenerator
> ExegesisTarget::createParallelSnippetGenerator(
88 const LLVMState
&State
, const SnippetGenerator::Options
&Opts
) const {
89 return std::make_unique
<ParallelSnippetGenerator
>(State
, Opts
);
92 std::unique_ptr
<BenchmarkRunner
> ExegesisTarget::createLatencyBenchmarkRunner(
93 const LLVMState
&State
, InstructionBenchmark::ModeE Mode
) const {
94 return std::make_unique
<LatencyBenchmarkRunner
>(State
, Mode
);
97 std::unique_ptr
<BenchmarkRunner
>
98 ExegesisTarget::createUopsBenchmarkRunner(const LLVMState
&State
) const {
99 return std::make_unique
<UopsBenchmarkRunner
>(State
);
102 void ExegesisTarget::randomizeMCOperand(const Instruction
&Instr
,
104 MCOperand
&AssignedValue
,
105 const BitVector
&ForbiddenRegs
) const {
106 const Operand
&Op
= Instr
.getPrimaryOperand(Var
);
107 switch (Op
.getExplicitOperandInfo().OperandType
) {
108 case MCOI::OperandType::OPERAND_IMMEDIATE
:
109 // FIXME: explore immediate values too.
110 AssignedValue
= MCOperand::createImm(1);
112 case MCOI::OperandType::OPERAND_REGISTER
: {
114 auto AllowedRegs
= Op
.getRegisterAliasing().sourceBits();
115 assert(AllowedRegs
.size() == ForbiddenRegs
.size());
116 for (auto I
: ForbiddenRegs
.set_bits())
117 AllowedRegs
.reset(I
);
118 AssignedValue
= MCOperand::createReg(randomBit(AllowedRegs
));
126 static_assert(std::is_pod
<PfmCountersInfo
>::value
,
127 "We shouldn't have dynamic initialization here");
128 const PfmCountersInfo
PfmCountersInfo::Default
= {nullptr, nullptr, nullptr,
131 const PfmCountersInfo
&ExegesisTarget::getPfmCounters(StringRef CpuName
) const {
132 assert(std::is_sorted(
133 CpuPfmCounters
.begin(), CpuPfmCounters
.end(),
134 [](const CpuAndPfmCounters
&LHS
, const CpuAndPfmCounters
&RHS
) {
135 return strcmp(LHS
.CpuName
, RHS
.CpuName
) < 0;
137 "CpuPfmCounters table is not sorted");
141 std::lower_bound(CpuPfmCounters
.begin(), CpuPfmCounters
.end(), CpuName
);
142 if (Found
== CpuPfmCounters
.end() || StringRef(Found
->CpuName
) != CpuName
) {
144 if (CpuPfmCounters
.begin() != CpuPfmCounters
.end() &&
145 CpuPfmCounters
.begin()->CpuName
[0] == '\0') {
146 Found
= CpuPfmCounters
.begin(); // The target specifies a default.
148 return PfmCountersInfo::Default
; // No default for the target.
151 assert(Found
->PCI
&& "Missing counters");
157 // Default implementation.
158 class ExegesisDefaultTarget
: public ExegesisTarget
{
160 ExegesisDefaultTarget() : ExegesisTarget({}) {}
163 std::vector
<MCInst
> setRegTo(const MCSubtargetInfo
&STI
, unsigned Reg
,
164 const APInt
&Value
) const override
{
165 llvm_unreachable("Not yet implemented");
168 bool matchesArch(Triple::ArchType Arch
) const override
{
169 llvm_unreachable("never called");
176 const ExegesisTarget
&ExegesisTarget::getDefault() {
177 static ExegesisDefaultTarget Target
;
181 } // namespace exegesis