[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / tools / llvm-exegesis / lib / Target.cpp
blob9ff19d57a871af6b8ebd8df34ea4dc3a5b0da38b
1 //===-- Target.cpp ----------------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 #include "Target.h"
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"
17 namespace llvm {
18 namespace exegesis {
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()))
27 return T;
29 return nullptr;
32 Expected<std::unique_ptr<pfm::Counter>>
33 ExegesisTarget::createCounter(StringRef CounterName, const LLVMState &) const {
34 pfm::PerfEvent Event(CounterName);
35 if (!Event.valid())
36 return llvm::make_error<Failure>(
37 llvm::Twine("Unable to create counter with name '")
38 .concat(CounterName)
39 .concat("'"));
41 return std::make_unique<pfm::Counter>(std::move(Event));
44 void ExegesisTarget::registerTarget(ExegesisTarget *Target) {
45 if (FirstTarget == nullptr) {
46 FirstTarget = Target;
47 return;
49 if (Target->Next != nullptr)
50 return; // Already registered.
51 Target->Next = FirstTarget;
52 FirstTarget = Target;
55 std::unique_ptr<SnippetGenerator> ExegesisTarget::createSnippetGenerator(
56 InstructionBenchmark::ModeE Mode, const LLVMState &State,
57 const SnippetGenerator::Options &Opts) const {
58 switch (Mode) {
59 case InstructionBenchmark::Unknown:
60 return nullptr;
61 case InstructionBenchmark::Latency:
62 return createSerialSnippetGenerator(State, Opts);
63 case InstructionBenchmark::Uops:
64 case InstructionBenchmark::InverseThroughput:
65 return createParallelSnippetGenerator(State, Opts);
67 return nullptr;
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();
75 switch (Mode) {
76 case InstructionBenchmark::Unknown:
77 return nullptr;
78 case InstructionBenchmark::Latency:
79 case InstructionBenchmark::InverseThroughput:
80 if (!PfmCounters.CycleCounter) {
81 const char *ModeName = Mode == InstructionBenchmark::Latency
82 ? "latency"
83 : "inverse_throughput";
84 return make_error<Failure>(
85 Twine("can't run '")
86 .concat(ModeName)
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);
96 return nullptr;
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,
124 0u};
126 const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
127 assert(llvm::is_sorted(
128 CpuPfmCounters,
129 [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
130 return strcmp(LHS.CpuName, RHS.CpuName) < 0;
131 }) &&
132 "CpuPfmCounters table is not sorted");
134 // Find entry
135 auto Found = llvm::lower_bound(CpuPfmCounters, CpuName);
136 if (Found == CpuPfmCounters.end() || StringRef(Found->CpuName) != CpuName) {
137 // Use the default.
138 if (!CpuPfmCounters.empty() && CpuPfmCounters.begin()->CpuName[0] == '\0') {
139 Found = CpuPfmCounters.begin(); // The target specifies a default.
140 } else {
141 return PfmCountersInfo::Default; // No default for the target.
144 assert(Found->PCI && "Missing counters");
145 return *Found->PCI;
148 ExegesisTarget::SavedState::~SavedState() {} // anchor.
150 namespace {
152 // Default implementation.
153 class ExegesisDefaultTarget : public ExegesisTarget {
154 public:
155 ExegesisDefaultTarget() : ExegesisTarget({}) {}
157 private:
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");
165 return false;
169 } // namespace
171 const ExegesisTarget &ExegesisTarget::getDefault() {
172 static ExegesisDefaultTarget Target;
173 return Target;
176 } // namespace exegesis
177 } // namespace llvm