Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / utils / TableGen / ExegesisEmitter.cpp
blob736f1220be14ddee602c829eed98fd31ab46b761
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(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 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 (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);
84 AddPfmCounterName(Def->getValueAsDef("CycleCounter"));
85 AddPfmCounterName(Def->getValueAsDef("UopsCounter"));
87 unsigned Index = 0;
88 for (auto &NameAndIndex : PfmCounterNameTable)
89 NameAndIndex.second = Index++;
90 return PfmCounterNameTable;
93 ExegesisEmitter::ExegesisEmitter(RecordKeeper &RK)
94 : Records(RK), PfmCounterNameTable(collectPfmCounters(RK)) {
95 std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target");
96 if (Targets.size() == 0)
97 PrintFatalError("No 'Target' subclasses defined!");
98 if (Targets.size() != 1)
99 PrintFatalError("Multiple subclasses of Target defined!");
100 Target = std::string(Targets[0]->getName());
103 void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
104 unsigned &IssueCountersTableOffset,
105 raw_ostream &OS) const {
106 const auto CycleCounter =
107 Def.getValueAsDef("CycleCounter")->getValueAsString("Counter");
108 const auto UopsCounter =
109 Def.getValueAsDef("UopsCounter")->getValueAsString("Counter");
110 const size_t NumIssueCounters =
111 Def.getValueAsListOfDefs("IssueCounters").size();
113 OS << "\nstatic const PfmCountersInfo " << Target << Def.getName()
114 << " = {\n";
116 // Cycle Counter.
117 if (CycleCounter.empty())
118 OS << " nullptr, // No cycle counter.\n";
119 else
120 OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(CycleCounter)
121 << "], // Cycle counter\n";
123 // Uops Counter.
124 if (UopsCounter.empty())
125 OS << " nullptr, // No uops counter.\n";
126 else
127 OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(UopsCounter)
128 << "], // Uops counter\n";
130 // Issue Counters
131 if (NumIssueCounters == 0)
132 OS << " nullptr, // No issue counters.\n 0\n";
133 else
134 OS << " " << Target << "PfmIssueCounters + " << IssueCountersTableOffset
135 << ", " << NumIssueCounters << " // Issue counters.\n";
137 OS << "};\n";
138 IssueCountersTableOffset += NumIssueCounters;
141 void ExegesisEmitter::emitPfmCounters(raw_ostream &OS) const {
142 // Emit the counter name table.
143 OS << "\nstatic const char *" << Target << "PfmCounterNames[] = {\n";
144 for (const auto &NameAndIndex : PfmCounterNameTable)
145 OS << " \"" << NameAndIndex.first << "\", // " << NameAndIndex.second
146 << "\n";
147 OS << "};\n\n";
149 // Emit the IssueCounters table.
150 const auto PfmCounterDefs =
151 Records.getAllDerivedDefinitions("ProcPfmCounters");
152 // Only emit if non-empty.
153 const bool HasAtLeastOnePfmIssueCounter =
154 llvm::any_of(PfmCounterDefs, [](const Record *Def) {
155 return !Def->getValueAsListOfDefs("IssueCounters").empty();
157 if (HasAtLeastOnePfmIssueCounter) {
158 OS << "static const PfmCountersInfo::IssueCounter " << Target
159 << "PfmIssueCounters[] = {\n";
160 for (const Record *Def : PfmCounterDefs) {
161 for (const Record *ICDef : Def->getValueAsListOfDefs("IssueCounters"))
162 OS << " { " << Target << "PfmCounterNames["
163 << getPfmCounterId(ICDef->getValueAsString("Counter")) << "], \""
164 << ICDef->getValueAsString("ResourceName") << "\"},\n";
166 OS << "};\n";
169 // Now generate the PfmCountersInfo.
170 unsigned IssueCountersTableOffset = 0;
171 for (const Record *Def : PfmCounterDefs)
172 emitPfmCountersInfo(*Def, IssueCountersTableOffset, OS);
174 OS << "\n";
175 } // namespace
177 void ExegesisEmitter::emitPfmCountersLookupTable(raw_ostream &OS) const {
178 std::vector<Record *> Bindings =
179 Records.getAllDerivedDefinitions("PfmCountersBinding");
180 assert(!Bindings.empty() && "there must be at least one binding");
181 llvm::sort(Bindings, [](const Record *L, const Record *R) {
182 return L->getValueAsString("CpuName") < R->getValueAsString("CpuName");
185 OS << "// Sorted (by CpuName) array of pfm counters.\n"
186 << "static const CpuAndPfmCounters " << Target << "CpuPfmCounters[] = {\n";
187 for (Record *Binding : Bindings) {
188 // Emit as { "cpu", procinit },
189 OS << " { \"" //
190 << Binding->getValueAsString("CpuName") << "\"," //
191 << " &" << Target << Binding->getValueAsDef("Counters")->getName() //
192 << " },\n";
194 OS << "};\n\n";
197 void ExegesisEmitter::run(raw_ostream &OS) const {
198 emitSourceFileHeader("Exegesis Tables", OS);
199 emitPfmCounters(OS);
200 emitPfmCountersLookupTable(OS);
203 } // end anonymous namespace
205 static TableGen::Emitter::OptClass<ExegesisEmitter>
206 X("gen-exegesis", "Generate llvm-exegesis tables");