Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/ExegesisEmitter.cpp
35258 views
1
//===- ExegesisEmitter.cpp - Generate exegesis target data ----------------===//
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
//
9
// This tablegen backend emits llvm-exegesis information.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/ADT/STLExtras.h"
14
#include "llvm/ADT/SmallSet.h"
15
#include "llvm/ADT/StringRef.h"
16
#include "llvm/Support/raw_ostream.h"
17
#include "llvm/TableGen/Error.h"
18
#include "llvm/TableGen/Record.h"
19
#include "llvm/TableGen/TableGenBackend.h"
20
#include <cassert>
21
#include <map>
22
#include <string>
23
#include <vector>
24
25
using namespace llvm;
26
27
#define DEBUG_TYPE "exegesis-emitter"
28
29
namespace {
30
31
class ExegesisEmitter {
32
public:
33
ExegesisEmitter(RecordKeeper &RK);
34
35
void run(raw_ostream &OS) const;
36
37
private:
38
unsigned getPfmCounterId(llvm::StringRef Name) const {
39
const auto It = PfmCounterNameTable.find(Name);
40
if (It == PfmCounterNameTable.end())
41
PrintFatalError("no pfm counter id for " + Name);
42
return It->second;
43
}
44
45
// Collects all the ProcPfmCounters definitions available in this target.
46
void emitPfmCounters(raw_ostream &OS) const;
47
48
void emitPfmCountersInfo(const Record &Def,
49
unsigned &IssueCountersTableOffset,
50
raw_ostream &OS) const;
51
52
void emitPfmCountersLookupTable(raw_ostream &OS) const;
53
54
RecordKeeper &Records;
55
std::string Target;
56
57
// Table of counter name -> counter index.
58
const std::map<llvm::StringRef, unsigned> PfmCounterNameTable;
59
};
60
61
static std::map<llvm::StringRef, unsigned>
62
collectPfmCounters(const RecordKeeper &Records) {
63
std::map<llvm::StringRef, unsigned> PfmCounterNameTable;
64
const auto AddPfmCounterName = [&PfmCounterNameTable](
65
const Record *PfmCounterDef) {
66
const llvm::StringRef Counter = PfmCounterDef->getValueAsString("Counter");
67
if (!Counter.empty())
68
PfmCounterNameTable.emplace(Counter, 0);
69
};
70
for (Record *Def : Records.getAllDerivedDefinitions("ProcPfmCounters")) {
71
// Check that ResourceNames are unique.
72
llvm::SmallSet<llvm::StringRef, 16> Seen;
73
for (const Record *IssueCounter :
74
Def->getValueAsListOfDefs("IssueCounters")) {
75
const llvm::StringRef ResourceName =
76
IssueCounter->getValueAsString("ResourceName");
77
if (ResourceName.empty())
78
PrintFatalError(IssueCounter->getLoc(), "invalid empty ResourceName");
79
if (!Seen.insert(ResourceName).second)
80
PrintFatalError(IssueCounter->getLoc(),
81
"duplicate ResourceName " + ResourceName);
82
AddPfmCounterName(IssueCounter);
83
}
84
85
for (const Record *ValidationCounter :
86
Def->getValueAsListOfDefs("ValidationCounters"))
87
AddPfmCounterName(ValidationCounter);
88
89
AddPfmCounterName(Def->getValueAsDef("CycleCounter"));
90
AddPfmCounterName(Def->getValueAsDef("UopsCounter"));
91
}
92
unsigned Index = 0;
93
for (auto &NameAndIndex : PfmCounterNameTable)
94
NameAndIndex.second = Index++;
95
return PfmCounterNameTable;
96
}
97
98
ExegesisEmitter::ExegesisEmitter(RecordKeeper &RK)
99
: Records(RK), PfmCounterNameTable(collectPfmCounters(RK)) {
100
std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target");
101
if (Targets.size() == 0)
102
PrintFatalError("No 'Target' subclasses defined!");
103
if (Targets.size() != 1)
104
PrintFatalError("Multiple subclasses of Target defined!");
105
Target = std::string(Targets[0]->getName());
106
}
107
108
struct ValidationCounterInfo {
109
int64_t EventNumber;
110
StringRef EventName;
111
unsigned PfmCounterID;
112
};
113
114
bool EventNumberLess(const ValidationCounterInfo &LHS,
115
const ValidationCounterInfo &RHS) {
116
return LHS.EventNumber < RHS.EventNumber;
117
}
118
119
void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
120
unsigned &IssueCountersTableOffset,
121
raw_ostream &OS) const {
122
const auto CycleCounter =
123
Def.getValueAsDef("CycleCounter")->getValueAsString("Counter");
124
const auto UopsCounter =
125
Def.getValueAsDef("UopsCounter")->getValueAsString("Counter");
126
const size_t NumIssueCounters =
127
Def.getValueAsListOfDefs("IssueCounters").size();
128
const size_t NumValidationCounters =
129
Def.getValueAsListOfDefs("ValidationCounters").size();
130
131
// Emit Validation Counters Array
132
if (NumValidationCounters != 0) {
133
std::vector<ValidationCounterInfo> ValidationCounters;
134
ValidationCounters.reserve(NumValidationCounters);
135
for (const Record *ValidationCounter :
136
Def.getValueAsListOfDefs("ValidationCounters")) {
137
ValidationCounters.push_back(
138
{ValidationCounter->getValueAsDef("EventType")
139
->getValueAsInt("EventNumber"),
140
ValidationCounter->getValueAsDef("EventType")->getName(),
141
getPfmCounterId(ValidationCounter->getValueAsString("Counter"))});
142
}
143
std::sort(ValidationCounters.begin(), ValidationCounters.end(),
144
EventNumberLess);
145
OS << "\nstatic const std::pair<ValidationEvent, const char*> " << Target
146
<< Def.getName() << "ValidationCounters[] = {\n";
147
for (const ValidationCounterInfo &VCI : ValidationCounters) {
148
OS << " { " << VCI.EventName << ", " << Target << "PfmCounterNames["
149
<< VCI.PfmCounterID << "]},\n";
150
}
151
OS << "};\n";
152
}
153
154
OS << "\nstatic const PfmCountersInfo " << Target << Def.getName()
155
<< " = {\n";
156
157
// Cycle Counter.
158
if (CycleCounter.empty())
159
OS << " nullptr, // No cycle counter.\n";
160
else
161
OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(CycleCounter)
162
<< "], // Cycle counter\n";
163
164
// Uops Counter.
165
if (UopsCounter.empty())
166
OS << " nullptr, // No uops counter.\n";
167
else
168
OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(UopsCounter)
169
<< "], // Uops counter\n";
170
171
// Issue Counters
172
if (NumIssueCounters == 0)
173
OS << " nullptr, 0, // No issue counters\n";
174
else
175
OS << " " << Target << "PfmIssueCounters + " << IssueCountersTableOffset
176
<< ", " << NumIssueCounters << ", // Issue counters.\n";
177
178
// Validation Counters
179
if (NumValidationCounters == 0)
180
OS << " nullptr, 0 // No validation counters.\n";
181
else
182
OS << " " << Target << Def.getName() << "ValidationCounters, "
183
<< NumValidationCounters << " // Validation counters.\n";
184
185
OS << "};\n";
186
IssueCountersTableOffset += NumIssueCounters;
187
}
188
189
void ExegesisEmitter::emitPfmCounters(raw_ostream &OS) const {
190
// Emit the counter name table.
191
OS << "\nstatic const char *" << Target << "PfmCounterNames[] = {\n";
192
for (const auto &NameAndIndex : PfmCounterNameTable)
193
OS << " \"" << NameAndIndex.first << "\", // " << NameAndIndex.second
194
<< "\n";
195
OS << "};\n\n";
196
197
// Emit the IssueCounters table.
198
const auto PfmCounterDefs =
199
Records.getAllDerivedDefinitions("ProcPfmCounters");
200
// Only emit if non-empty.
201
const bool HasAtLeastOnePfmIssueCounter =
202
llvm::any_of(PfmCounterDefs, [](const Record *Def) {
203
return !Def->getValueAsListOfDefs("IssueCounters").empty();
204
});
205
if (HasAtLeastOnePfmIssueCounter) {
206
OS << "static const PfmCountersInfo::IssueCounter " << Target
207
<< "PfmIssueCounters[] = {\n";
208
for (const Record *Def : PfmCounterDefs) {
209
for (const Record *ICDef : Def->getValueAsListOfDefs("IssueCounters"))
210
OS << " { " << Target << "PfmCounterNames["
211
<< getPfmCounterId(ICDef->getValueAsString("Counter")) << "], \""
212
<< ICDef->getValueAsString("ResourceName") << "\"},\n";
213
}
214
OS << "};\n";
215
}
216
217
// Now generate the PfmCountersInfo.
218
unsigned IssueCountersTableOffset = 0;
219
for (const Record *Def : PfmCounterDefs)
220
emitPfmCountersInfo(*Def, IssueCountersTableOffset, OS);
221
222
OS << "\n";
223
} // namespace
224
225
void ExegesisEmitter::emitPfmCountersLookupTable(raw_ostream &OS) const {
226
std::vector<Record *> Bindings =
227
Records.getAllDerivedDefinitions("PfmCountersBinding");
228
assert(!Bindings.empty() && "there must be at least one binding");
229
llvm::sort(Bindings, [](const Record *L, const Record *R) {
230
return L->getValueAsString("CpuName") < R->getValueAsString("CpuName");
231
});
232
233
OS << "// Sorted (by CpuName) array of pfm counters.\n"
234
<< "static const CpuAndPfmCounters " << Target << "CpuPfmCounters[] = {\n";
235
for (Record *Binding : Bindings) {
236
// Emit as { "cpu", procinit },
237
OS << " { \"" //
238
<< Binding->getValueAsString("CpuName") << "\"," //
239
<< " &" << Target << Binding->getValueAsDef("Counters")->getName() //
240
<< " },\n";
241
}
242
OS << "};\n\n";
243
}
244
245
void ExegesisEmitter::run(raw_ostream &OS) const {
246
emitSourceFileHeader("Exegesis Tables", OS);
247
emitPfmCounters(OS);
248
emitPfmCountersLookupTable(OS);
249
}
250
251
} // end anonymous namespace
252
253
static TableGen::Emitter::OptClass<ExegesisEmitter>
254
X("gen-exegesis", "Generate llvm-exegesis tables");
255
256