blob: 4e0de9375669392ae934781a5ff4a0d466e7dee0 [file] [log] [blame]
Clement Courbet44b4c542018-06-19 11:28:59 +00001//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Clement Courbet44b4c542018-06-19 11:28:59 +00006//
7//===----------------------------------------------------------------------===//
8#include "Target.h"
9
Miloš Stojanović24b7b992020-01-17 14:28:54 +010010#include "LatencyBenchmarkRunner.h"
11#include "ParallelSnippetGenerator.h"
12#include "SerialSnippetGenerator.h"
13#include "UopsBenchmarkRunner.h"
Clement Courbet4860b982018-06-26 08:49:30 +000014
Fangrui Song32401af2018-10-22 17:10:47 +000015namespace llvm {
Clement Courbet44b4c542018-06-19 11:28:59 +000016namespace exegesis {
17
Clement Courbetcff2caa2018-06-25 11:22:23 +000018ExegesisTarget::~ExegesisTarget() {} // anchor.
Clement Courbet44b4c542018-06-19 11:28:59 +000019
Clement Courbetcff2caa2018-06-25 11:22:23 +000020static ExegesisTarget *FirstTarget = nullptr;
Clement Courbet44b4c542018-06-19 11:28:59 +000021
Clement Courbet50cdd562019-10-09 11:58:42 +000022const ExegesisTarget *ExegesisTarget::lookup(Triple TT) {
Clement Courbetcff2caa2018-06-25 11:22:23 +000023 for (const ExegesisTarget *T = FirstTarget; T != nullptr; T = T->Next) {
Clement Courbet6fd00e32018-06-20 11:54:35 +000024 if (T->matchesArch(TT.getArch()))
25 return T;
Clement Courbet44b4c542018-06-19 11:28:59 +000026 }
27 return nullptr;
28}
29
Clement Courbetcff2caa2018-06-25 11:22:23 +000030void ExegesisTarget::registerTarget(ExegesisTarget *Target) {
Clement Courbet44b4c542018-06-19 11:28:59 +000031 if (FirstTarget == nullptr) {
32 FirstTarget = Target;
33 return;
34 }
Clement Courbet44b4c542018-06-19 11:28:59 +000035 if (Target->Next != nullptr)
Guillaume Chateletfb943542018-08-01 14:41:45 +000036 return; // Already registered.
Clement Courbet44b4c542018-06-19 11:28:59 +000037 Target->Next = FirstTarget;
38 FirstTarget = Target;
39}
Clement Courbet4860b982018-06-26 08:49:30 +000040
Clement Courbet2cd0f282019-10-08 14:30:24 +000041std::unique_ptr<SnippetGenerator> ExegesisTarget::createSnippetGenerator(
42 InstructionBenchmark::ModeE Mode, const LLVMState &State,
43 const SnippetGenerator::Options &Opts) const {
Clement Courbetd939f6d2018-09-13 07:40:53 +000044 switch (Mode) {
45 case InstructionBenchmark::Unknown:
46 return nullptr;
47 case InstructionBenchmark::Latency:
Miloš Stojanović24b7b992020-01-17 14:28:54 +010048 return createSerialSnippetGenerator(State, Opts);
Clement Courbetd939f6d2018-09-13 07:40:53 +000049 case InstructionBenchmark::Uops:
Clement Courbet362653f2019-01-30 16:02:20 +000050 case InstructionBenchmark::InverseThroughput:
Miloš Stojanović24b7b992020-01-17 14:28:54 +010051 return createParallelSnippetGenerator(State, Opts);
Clement Courbetd939f6d2018-09-13 07:40:53 +000052 }
53 return nullptr;
54}
55
Miloš Stojanović4bd40f72020-02-06 18:21:01 +010056Expected<std::unique_ptr<BenchmarkRunner>>
Clement Courbet4860b982018-06-26 08:49:30 +000057ExegesisTarget::createBenchmarkRunner(InstructionBenchmark::ModeE Mode,
58 const LLVMState &State) const {
Miloš Stojanovićc7dc4732019-12-31 14:14:41 +010059 PfmCountersInfo PfmCounters = State.getPfmCounters();
Clement Courbet4860b982018-06-26 08:49:30 +000060 switch (Mode) {
61 case InstructionBenchmark::Unknown:
62 return nullptr;
63 case InstructionBenchmark::Latency:
Clement Courbet362653f2019-01-30 16:02:20 +000064 case InstructionBenchmark::InverseThroughput:
Miloš Stojanovićc7dc4732019-12-31 14:14:41 +010065 if (!PfmCounters.CycleCounter) {
66 const char *ModeName = Mode == InstructionBenchmark::Latency
67 ? "latency"
68 : "inverse_throughput";
Miloš Stojanović4bd40f72020-02-06 18:21:01 +010069 return make_error<Failure>(
70 Twine("can't run '")
71 .concat(ModeName)
72 .concat("' mode, sched model does not define a cycle counter."));
Miloš Stojanovićc7dc4732019-12-31 14:14:41 +010073 }
Clement Courbet362653f2019-01-30 16:02:20 +000074 return createLatencyBenchmarkRunner(State, Mode);
Clement Courbet4860b982018-06-26 08:49:30 +000075 case InstructionBenchmark::Uops:
Miloš Stojanovićc7dc4732019-12-31 14:14:41 +010076 if (!PfmCounters.UopsCounter && !PfmCounters.IssueCounters)
Miloš Stojanović4bd40f72020-02-06 18:21:01 +010077 return make_error<Failure>("can't run 'uops' mode, sched model does not "
78 "define uops or issue counters.");
Clement Courbet4860b982018-06-26 08:49:30 +000079 return createUopsBenchmarkRunner(State);
80 }
81 return nullptr;
82}
83
Miloš Stojanović24b7b992020-01-17 14:28:54 +010084std::unique_ptr<SnippetGenerator> ExegesisTarget::createSerialSnippetGenerator(
Clement Courbet2cd0f282019-10-08 14:30:24 +000085 const LLVMState &State, const SnippetGenerator::Options &Opts) const {
Miloš Stojanović24b7b992020-01-17 14:28:54 +010086 return std::make_unique<SerialSnippetGenerator>(State, Opts);
Clement Courbet0d79aaf2018-11-08 12:09:45 +000087}
88
Miloš Stojanović24b7b992020-01-17 14:28:54 +010089std::unique_ptr<SnippetGenerator> ExegesisTarget::createParallelSnippetGenerator(
Clement Courbet2cd0f282019-10-08 14:30:24 +000090 const LLVMState &State, const SnippetGenerator::Options &Opts) const {
Miloš Stojanović24b7b992020-01-17 14:28:54 +010091 return std::make_unique<ParallelSnippetGenerator>(State, Opts);
Clement Courbet0d79aaf2018-11-08 12:09:45 +000092}
93
Clement Courbet362653f2019-01-30 16:02:20 +000094std::unique_ptr<BenchmarkRunner> ExegesisTarget::createLatencyBenchmarkRunner(
95 const LLVMState &State, InstructionBenchmark::ModeE Mode) const {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +000096 return std::make_unique<LatencyBenchmarkRunner>(State, Mode);
Clement Courbet0d79aaf2018-11-08 12:09:45 +000097}
98
99std::unique_ptr<BenchmarkRunner>
100ExegesisTarget::createUopsBenchmarkRunner(const LLVMState &State) const {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +0000101 return std::make_unique<UopsBenchmarkRunner>(State);
Clement Courbet0d79aaf2018-11-08 12:09:45 +0000102}
103
Clement Courbet41c8af32018-10-25 07:44:01 +0000104static_assert(std::is_pod<PfmCountersInfo>::value,
105 "We shouldn't have dynamic initialization here");
Clement Courbeteee2e062018-11-09 13:15:32 +0000106const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
107 0u};
Clement Courbet41c8af32018-10-25 07:44:01 +0000108
Clement Courbet50cdd562019-10-09 11:58:42 +0000109const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
Georgii Rymar1647ff62020-04-13 14:46:41 +0300110 assert(llvm::is_sorted(
111 CpuPfmCounters,
Clement Courbet41c8af32018-10-25 07:44:01 +0000112 [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
113 return strcmp(LHS.CpuName, RHS.CpuName) < 0;
114 }) &&
115 "CpuPfmCounters table is not sorted");
116
117 // Find entry
118 auto Found =
119 std::lower_bound(CpuPfmCounters.begin(), CpuPfmCounters.end(), CpuName);
Clement Courbet50cdd562019-10-09 11:58:42 +0000120 if (Found == CpuPfmCounters.end() || StringRef(Found->CpuName) != CpuName) {
Clement Courbeteee2e062018-11-09 13:15:32 +0000121 // Use the default.
122 if (CpuPfmCounters.begin() != CpuPfmCounters.end() &&
123 CpuPfmCounters.begin()->CpuName[0] == '\0') {
124 Found = CpuPfmCounters.begin(); // The target specifies a default.
125 } else {
126 return PfmCountersInfo::Default; // No default for the target.
127 }
Clement Courbet41c8af32018-10-25 07:44:01 +0000128 }
129 assert(Found->PCI && "Missing counters");
130 return *Found->PCI;
131}
132
Clement Courbet4860b982018-06-26 08:49:30 +0000133namespace {
134
135// Default implementation.
136class ExegesisDefaultTarget : public ExegesisTarget {
Clement Courbet41c8af32018-10-25 07:44:01 +0000137public:
138 ExegesisDefaultTarget() : ExegesisTarget({}) {}
139
Clement Courbet4860b982018-06-26 08:49:30 +0000140private:
Clement Courbet50cdd562019-10-09 11:58:42 +0000141 std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
142 const APInt &Value) const override {
Guillaume Chatelet5ad29092018-09-18 11:26:27 +0000143 llvm_unreachable("Not yet implemented");
144 }
145
Clement Courbet50cdd562019-10-09 11:58:42 +0000146 bool matchesArch(Triple::ArchType Arch) const override {
Clement Courbet4860b982018-06-26 08:49:30 +0000147 llvm_unreachable("never called");
148 return false;
149 }
150};
151
152} // namespace
153
154const ExegesisTarget &ExegesisTarget::getDefault() {
155 static ExegesisDefaultTarget Target;
156 return Target;
157}
158
Clement Courbetcff2caa2018-06-25 11:22:23 +0000159} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +0000160} // namespace llvm