blob: 701ff14be2093ce27083c918a9eb5181db0544a4 [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
Clement Courbet4860b982018-06-26 08:49:30 +000056std::unique_ptr<BenchmarkRunner>
57ExegesisTarget::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";
69 report_fatal_error(Twine("can't run '").concat(ModeName).concat("' mode, "
70 "sched model does not define a cycle counter."));
71 }
Clement Courbet362653f2019-01-30 16:02:20 +000072 return createLatencyBenchmarkRunner(State, Mode);
Clement Courbet4860b982018-06-26 08:49:30 +000073 case InstructionBenchmark::Uops:
Miloš Stojanovićc7dc4732019-12-31 14:14:41 +010074 if (!PfmCounters.UopsCounter && !PfmCounters.IssueCounters)
75 report_fatal_error("can't run 'uops' mode, sched model does not define "
76 "uops or issue counters.");
Clement Courbet4860b982018-06-26 08:49:30 +000077 return createUopsBenchmarkRunner(State);
78 }
79 return nullptr;
80}
81
Miloš Stojanović24b7b992020-01-17 14:28:54 +010082std::unique_ptr<SnippetGenerator> ExegesisTarget::createSerialSnippetGenerator(
Clement Courbet2cd0f282019-10-08 14:30:24 +000083 const LLVMState &State, const SnippetGenerator::Options &Opts) const {
Miloš Stojanović24b7b992020-01-17 14:28:54 +010084 return std::make_unique<SerialSnippetGenerator>(State, Opts);
Clement Courbet0d79aaf2018-11-08 12:09:45 +000085}
86
Miloš Stojanović24b7b992020-01-17 14:28:54 +010087std::unique_ptr<SnippetGenerator> ExegesisTarget::createParallelSnippetGenerator(
Clement Courbet2cd0f282019-10-08 14:30:24 +000088 const LLVMState &State, const SnippetGenerator::Options &Opts) const {
Miloš Stojanović24b7b992020-01-17 14:28:54 +010089 return std::make_unique<ParallelSnippetGenerator>(State, Opts);
Clement Courbet0d79aaf2018-11-08 12:09:45 +000090}
91
Clement Courbet362653f2019-01-30 16:02:20 +000092std::unique_ptr<BenchmarkRunner> ExegesisTarget::createLatencyBenchmarkRunner(
93 const LLVMState &State, InstructionBenchmark::ModeE Mode) const {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +000094 return std::make_unique<LatencyBenchmarkRunner>(State, Mode);
Clement Courbet0d79aaf2018-11-08 12:09:45 +000095}
96
97std::unique_ptr<BenchmarkRunner>
98ExegesisTarget::createUopsBenchmarkRunner(const LLVMState &State) const {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +000099 return std::make_unique<UopsBenchmarkRunner>(State);
Clement Courbet0d79aaf2018-11-08 12:09:45 +0000100}
101
Clement Courbet41c8af32018-10-25 07:44:01 +0000102static_assert(std::is_pod<PfmCountersInfo>::value,
103 "We shouldn't have dynamic initialization here");
Clement Courbeteee2e062018-11-09 13:15:32 +0000104const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
105 0u};
Clement Courbet41c8af32018-10-25 07:44:01 +0000106
Clement Courbet50cdd562019-10-09 11:58:42 +0000107const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
Clement Courbet41c8af32018-10-25 07:44:01 +0000108 assert(std::is_sorted(
109 CpuPfmCounters.begin(), CpuPfmCounters.end(),
110 [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
111 return strcmp(LHS.CpuName, RHS.CpuName) < 0;
112 }) &&
113 "CpuPfmCounters table is not sorted");
114
115 // Find entry
116 auto Found =
117 std::lower_bound(CpuPfmCounters.begin(), CpuPfmCounters.end(), CpuName);
Clement Courbet50cdd562019-10-09 11:58:42 +0000118 if (Found == CpuPfmCounters.end() || StringRef(Found->CpuName) != CpuName) {
Clement Courbeteee2e062018-11-09 13:15:32 +0000119 // Use the default.
120 if (CpuPfmCounters.begin() != CpuPfmCounters.end() &&
121 CpuPfmCounters.begin()->CpuName[0] == '\0') {
122 Found = CpuPfmCounters.begin(); // The target specifies a default.
123 } else {
124 return PfmCountersInfo::Default; // No default for the target.
125 }
Clement Courbet41c8af32018-10-25 07:44:01 +0000126 }
127 assert(Found->PCI && "Missing counters");
128 return *Found->PCI;
129}
130
Clement Courbet4860b982018-06-26 08:49:30 +0000131namespace {
132
133// Default implementation.
134class ExegesisDefaultTarget : public ExegesisTarget {
Clement Courbet41c8af32018-10-25 07:44:01 +0000135public:
136 ExegesisDefaultTarget() : ExegesisTarget({}) {}
137
Clement Courbet4860b982018-06-26 08:49:30 +0000138private:
Clement Courbet50cdd562019-10-09 11:58:42 +0000139 std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
140 const APInt &Value) const override {
Guillaume Chatelet5ad29092018-09-18 11:26:27 +0000141 llvm_unreachable("Not yet implemented");
142 }
143
Clement Courbet50cdd562019-10-09 11:58:42 +0000144 bool matchesArch(Triple::ArchType Arch) const override {
Clement Courbet4860b982018-06-26 08:49:30 +0000145 llvm_unreachable("never called");
146 return false;
147 }
148};
149
150} // namespace
151
152const ExegesisTarget &ExegesisTarget::getDefault() {
153 static ExegesisDefaultTarget Target;
154 return Target;
155}
156
Clement Courbetcff2caa2018-06-25 11:22:23 +0000157} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +0000158} // namespace llvm