blob: 06557770418c3278988421a7cead7cafba7834b0 [file] [log] [blame]
Clement Courbet44b4c542018-06-19 11:28:59 +00001//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "Target.h"
10
Clement Courbet4860b982018-06-26 08:49:30 +000011#include "Latency.h"
12#include "Uops.h"
13
Fangrui Song32401af2018-10-22 17:10:47 +000014namespace llvm {
Clement Courbet44b4c542018-06-19 11:28:59 +000015namespace exegesis {
16
Clement Courbetcff2caa2018-06-25 11:22:23 +000017ExegesisTarget::~ExegesisTarget() {} // anchor.
Clement Courbet44b4c542018-06-19 11:28:59 +000018
Clement Courbetcff2caa2018-06-25 11:22:23 +000019static ExegesisTarget *FirstTarget = nullptr;
Clement Courbet44b4c542018-06-19 11:28:59 +000020
Clement Courbet6fd00e32018-06-20 11:54:35 +000021const ExegesisTarget *ExegesisTarget::lookup(llvm::Triple TT) {
Clement Courbetcff2caa2018-06-25 11:22:23 +000022 for (const ExegesisTarget *T = FirstTarget; T != nullptr; T = T->Next) {
Clement Courbet6fd00e32018-06-20 11:54:35 +000023 if (T->matchesArch(TT.getArch()))
24 return T;
Clement Courbet44b4c542018-06-19 11:28:59 +000025 }
26 return nullptr;
27}
28
Clement Courbetcff2caa2018-06-25 11:22:23 +000029void ExegesisTarget::registerTarget(ExegesisTarget *Target) {
Clement Courbet44b4c542018-06-19 11:28:59 +000030 if (FirstTarget == nullptr) {
31 FirstTarget = Target;
32 return;
33 }
Clement Courbet44b4c542018-06-19 11:28:59 +000034 if (Target->Next != nullptr)
Guillaume Chateletfb943542018-08-01 14:41:45 +000035 return; // Already registered.
Clement Courbet44b4c542018-06-19 11:28:59 +000036 Target->Next = FirstTarget;
37 FirstTarget = Target;
38}
Clement Courbet4860b982018-06-26 08:49:30 +000039
Clement Courbetd939f6d2018-09-13 07:40:53 +000040std::unique_ptr<SnippetGenerator>
41ExegesisTarget::createSnippetGenerator(InstructionBenchmark::ModeE Mode,
42 const LLVMState &State) const {
43 switch (Mode) {
44 case InstructionBenchmark::Unknown:
45 return nullptr;
46 case InstructionBenchmark::Latency:
47 return createLatencySnippetGenerator(State);
48 case InstructionBenchmark::Uops:
49 return createUopsSnippetGenerator(State);
50 }
51 return nullptr;
52}
53
Clement Courbet4860b982018-06-26 08:49:30 +000054std::unique_ptr<BenchmarkRunner>
55ExegesisTarget::createBenchmarkRunner(InstructionBenchmark::ModeE Mode,
56 const LLVMState &State) const {
57 switch (Mode) {
58 case InstructionBenchmark::Unknown:
59 return nullptr;
60 case InstructionBenchmark::Latency:
61 return createLatencyBenchmarkRunner(State);
62 case InstructionBenchmark::Uops:
63 return createUopsBenchmarkRunner(State);
64 }
65 return nullptr;
66}
67
Clement Courbet0d79aaf2018-11-08 12:09:45 +000068std::unique_ptr<SnippetGenerator>
69ExegesisTarget::createLatencySnippetGenerator(const LLVMState &State) const {
70 return llvm::make_unique<LatencySnippetGenerator>(State);
71}
72
73std::unique_ptr<SnippetGenerator>
74ExegesisTarget::createUopsSnippetGenerator(const LLVMState &State) const {
75 return llvm::make_unique<UopsSnippetGenerator>(State);
76}
77
78std::unique_ptr<BenchmarkRunner>
79ExegesisTarget::createLatencyBenchmarkRunner(const LLVMState &State) const {
80 return llvm::make_unique<LatencyBenchmarkRunner>(State);
81}
82
83std::unique_ptr<BenchmarkRunner>
84ExegesisTarget::createUopsBenchmarkRunner(const LLVMState &State) const {
85 return llvm::make_unique<UopsBenchmarkRunner>(State);
86}
87
Clement Courbet41c8af32018-10-25 07:44:01 +000088static_assert(std::is_pod<PfmCountersInfo>::value,
89 "We shouldn't have dynamic initialization here");
Clement Courbetb4b6ec02018-10-25 08:11:35 +000090const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr, 0u};
Clement Courbet41c8af32018-10-25 07:44:01 +000091
92const PfmCountersInfo &
93ExegesisTarget::getPfmCounters(llvm::StringRef CpuName) const {
94 assert(std::is_sorted(
95 CpuPfmCounters.begin(), CpuPfmCounters.end(),
96 [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
97 return strcmp(LHS.CpuName, RHS.CpuName) < 0;
98 }) &&
99 "CpuPfmCounters table is not sorted");
100
101 // Find entry
102 auto Found =
103 std::lower_bound(CpuPfmCounters.begin(), CpuPfmCounters.end(), CpuName);
104 if (Found == CpuPfmCounters.end() ||
105 llvm::StringRef(Found->CpuName) != CpuName) {
106 return PfmCountersInfo::Default;
107 }
108 assert(Found->PCI && "Missing counters");
109 return *Found->PCI;
110}
111
Clement Courbet4860b982018-06-26 08:49:30 +0000112namespace {
113
114// Default implementation.
115class ExegesisDefaultTarget : public ExegesisTarget {
Clement Courbet41c8af32018-10-25 07:44:01 +0000116public:
117 ExegesisDefaultTarget() : ExegesisTarget({}) {}
118
Clement Courbet4860b982018-06-26 08:49:30 +0000119private:
Guillaume Chatelet5ad29092018-09-18 11:26:27 +0000120 std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
Guillaume Chateletc96a97b2018-09-20 12:22:18 +0000121 unsigned Reg,
122 const llvm::APInt &Value) const override {
Guillaume Chatelet5ad29092018-09-18 11:26:27 +0000123 llvm_unreachable("Not yet implemented");
124 }
125
Clement Courbet4860b982018-06-26 08:49:30 +0000126 bool matchesArch(llvm::Triple::ArchType Arch) const override {
127 llvm_unreachable("never called");
128 return false;
129 }
130};
131
132} // namespace
133
134const ExegesisTarget &ExegesisTarget::getDefault() {
135 static ExegesisDefaultTarget Target;
136 return Target;
137}
138
Clement Courbetcff2caa2018-06-25 11:22:23 +0000139} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +0000140} // namespace llvm