[RISCV][VLOPT] Add vector narrowing integer right shift instructions to isSupportedIn...
[llvm-project.git] / llvm / utils / TableGen / ExegesisEmitter.cpp
bloba5dd2994b3753428e3f1726555faf7f20b9725b9
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.
11 //===----------------------------------------------------------------------===//
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>
25 using namespace llvm;
27 #define DEBUG_TYPE "exegesis-emitter"
29 namespace {
31 class ExegesisEmitter {
32 public:
33 ExegesisEmitter(const RecordKeeper &RK);
35 void run(raw_ostream &OS) const;
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;
45 // Collects all the ProcPfmCounters definitions available in this target.
46 void emitPfmCounters(raw_ostream &OS) const;
48 void emitPfmCountersInfo(const Record &Def,
49 unsigned &IssueCountersTableOffset,
50 raw_ostream &OS) const;
52 void emitPfmCountersLookupTable(raw_ostream &OS) const;
54 const RecordKeeper &Records;
55 std::string Target;
57 // Table of counter name -> counter index.
58 const std::map<llvm::StringRef, unsigned> PfmCounterNameTable;
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);
70 for (const Record *Def :
71 Records.getAllDerivedDefinitions("ProcPfmCounters")) {
72 // Check that ResourceNames are unique.
73 llvm::SmallSet<llvm::StringRef, 16> Seen;
74 for (const Record *IssueCounter :
75 Def->getValueAsListOfDefs("IssueCounters")) {
76 const llvm::StringRef ResourceName =
77 IssueCounter->getValueAsString("ResourceName");
78 if (ResourceName.empty())
79 PrintFatalError(IssueCounter->getLoc(), "invalid empty ResourceName");
80 if (!Seen.insert(ResourceName).second)
81 PrintFatalError(IssueCounter->getLoc(),
82 "duplicate ResourceName " + ResourceName);
83 AddPfmCounterName(IssueCounter);
86 for (const Record *ValidationCounter :
87 Def->getValueAsListOfDefs("ValidationCounters"))
88 AddPfmCounterName(ValidationCounter);
90 AddPfmCounterName(Def->getValueAsDef("CycleCounter"));
91 AddPfmCounterName(Def->getValueAsDef("UopsCounter"));
93 unsigned Index = 0;
94 for (auto &NameAndIndex : PfmCounterNameTable)
95 NameAndIndex.second = Index++;
96 return PfmCounterNameTable;
99 ExegesisEmitter::ExegesisEmitter(const RecordKeeper &RK)
100 : Records(RK), PfmCounterNameTable(collectPfmCounters(RK)) {
101 ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target");
102 if (Targets.size() == 0)
103 PrintFatalError("No 'Target' subclasses defined!");
104 if (Targets.size() != 1)
105 PrintFatalError("Multiple subclasses of Target defined!");
106 Target = std::string(Targets[0]->getName());
109 struct ValidationCounterInfo {
110 int64_t EventNumber;
111 StringRef EventName;
112 unsigned PfmCounterID;
115 bool EventNumberLess(const ValidationCounterInfo &LHS,
116 const ValidationCounterInfo &RHS) {
117 return LHS.EventNumber < RHS.EventNumber;
120 void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
121 unsigned &IssueCountersTableOffset,
122 raw_ostream &OS) const {
123 const auto CycleCounter =
124 Def.getValueAsDef("CycleCounter")->getValueAsString("Counter");
125 const auto UopsCounter =
126 Def.getValueAsDef("UopsCounter")->getValueAsString("Counter");
127 const size_t NumIssueCounters =
128 Def.getValueAsListOfDefs("IssueCounters").size();
129 const size_t NumValidationCounters =
130 Def.getValueAsListOfDefs("ValidationCounters").size();
132 // Emit Validation Counters Array
133 if (NumValidationCounters != 0) {
134 std::vector<ValidationCounterInfo> ValidationCounters;
135 ValidationCounters.reserve(NumValidationCounters);
136 for (const Record *ValidationCounter :
137 Def.getValueAsListOfDefs("ValidationCounters")) {
138 ValidationCounters.push_back(
139 {ValidationCounter->getValueAsDef("EventType")
140 ->getValueAsInt("EventNumber"),
141 ValidationCounter->getValueAsDef("EventType")->getName(),
142 getPfmCounterId(ValidationCounter->getValueAsString("Counter"))});
144 std::sort(ValidationCounters.begin(), ValidationCounters.end(),
145 EventNumberLess);
146 OS << "\nstatic const std::pair<ValidationEvent, const char*> " << Target
147 << Def.getName() << "ValidationCounters[] = {\n";
148 for (const ValidationCounterInfo &VCI : ValidationCounters) {
149 OS << " { " << VCI.EventName << ", " << Target << "PfmCounterNames["
150 << VCI.PfmCounterID << "]},\n";
152 OS << "};\n";
155 OS << "\nstatic const PfmCountersInfo " << Target << Def.getName()
156 << " = {\n";
158 // Cycle Counter.
159 if (CycleCounter.empty())
160 OS << " nullptr, // No cycle counter.\n";
161 else
162 OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(CycleCounter)
163 << "], // Cycle counter\n";
165 // Uops Counter.
166 if (UopsCounter.empty())
167 OS << " nullptr, // No uops counter.\n";
168 else
169 OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(UopsCounter)
170 << "], // Uops counter\n";
172 // Issue Counters
173 if (NumIssueCounters == 0)
174 OS << " nullptr, 0, // No issue counters\n";
175 else
176 OS << " " << Target << "PfmIssueCounters + " << IssueCountersTableOffset
177 << ", " << NumIssueCounters << ", // Issue counters.\n";
179 // Validation Counters
180 if (NumValidationCounters == 0)
181 OS << " nullptr, 0 // No validation counters.\n";
182 else
183 OS << " " << Target << Def.getName() << "ValidationCounters, "
184 << NumValidationCounters << " // Validation counters.\n";
186 OS << "};\n";
187 IssueCountersTableOffset += NumIssueCounters;
190 void ExegesisEmitter::emitPfmCounters(raw_ostream &OS) const {
191 // Emit the counter name table.
192 OS << "\nstatic const char *" << Target << "PfmCounterNames[] = {\n";
193 for (const auto &NameAndIndex : PfmCounterNameTable)
194 OS << " \"" << NameAndIndex.first << "\", // " << NameAndIndex.second
195 << "\n";
196 OS << "};\n\n";
198 // Emit the IssueCounters table.
199 const auto PfmCounterDefs =
200 Records.getAllDerivedDefinitions("ProcPfmCounters");
201 // Only emit if non-empty.
202 const bool HasAtLeastOnePfmIssueCounter =
203 llvm::any_of(PfmCounterDefs, [](const Record *Def) {
204 return !Def->getValueAsListOfDefs("IssueCounters").empty();
206 if (HasAtLeastOnePfmIssueCounter) {
207 OS << "static const PfmCountersInfo::IssueCounter " << Target
208 << "PfmIssueCounters[] = {\n";
209 for (const Record *Def : PfmCounterDefs) {
210 for (const Record *ICDef : Def->getValueAsListOfDefs("IssueCounters"))
211 OS << " { " << Target << "PfmCounterNames["
212 << getPfmCounterId(ICDef->getValueAsString("Counter")) << "], \""
213 << ICDef->getValueAsString("ResourceName") << "\"},\n";
215 OS << "};\n";
218 // Now generate the PfmCountersInfo.
219 unsigned IssueCountersTableOffset = 0;
220 for (const Record *Def : PfmCounterDefs)
221 emitPfmCountersInfo(*Def, IssueCountersTableOffset, OS);
223 OS << "\n";
224 } // namespace
226 void ExegesisEmitter::emitPfmCountersLookupTable(raw_ostream &OS) const {
227 std::vector<const Record *> Bindings =
228 Records.getAllDerivedDefinitions("PfmCountersBinding");
229 assert(!Bindings.empty() && "there must be at least one binding");
230 llvm::sort(Bindings, [](const Record *L, const Record *R) {
231 return L->getValueAsString("CpuName") < R->getValueAsString("CpuName");
234 OS << "// Sorted (by CpuName) array of pfm counters.\n"
235 << "static const CpuAndPfmCounters " << Target << "CpuPfmCounters[] = {\n";
236 for (const Record *Binding : Bindings) {
237 // Emit as { "cpu", procinit },
238 OS << " { \"" //
239 << Binding->getValueAsString("CpuName") << "\"," //
240 << " &" << Target << Binding->getValueAsDef("Counters")->getName() //
241 << " },\n";
243 OS << "};\n\n";
246 void ExegesisEmitter::run(raw_ostream &OS) const {
247 emitSourceFileHeader("Exegesis Tables", OS);
248 emitPfmCounters(OS);
249 emitPfmCountersLookupTable(OS);
252 } // end anonymous namespace
254 static TableGen::Emitter::OptClass<ExegesisEmitter>
255 X("gen-exegesis", "Generate llvm-exegesis tables");