blob: 208237aca20c8e36339cf4543700e60e7ee6e924 [file] [log] [blame]
Clement Courbetf4fb61b2018-10-25 07:44:01 +00001//===- ExegesisEmitter.cpp - Generate exegesis target data ----------------===//
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//
10// This tablegen backend emits llvm-exegesis information.
11//
12//===----------------------------------------------------------------------===//
13
Clement Courbetb4abfc22018-11-09 13:15:32 +000014#include "llvm/ADT/STLExtras.h"
Clement Courbetf4fb61b2018-10-25 07:44:01 +000015#include "llvm/ADT/SmallSet.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/Support/Debug.h"
18#include "llvm/Support/Format.h"
19#include "llvm/Support/raw_ostream.h"
20#include "llvm/TableGen/Error.h"
21#include "llvm/TableGen/Record.h"
22#include "llvm/TableGen/TableGenBackend.h"
23#include <algorithm>
24#include <cassert>
25#include <cstdint>
26#include <map>
27#include <string>
28#include <vector>
29
30using namespace llvm;
31
32#define DEBUG_TYPE "exegesis-emitter"
33
34namespace {
35
36class ExegesisEmitter {
37public:
38 ExegesisEmitter(RecordKeeper &RK);
39
40 void run(raw_ostream &OS) const;
41
42private:
43 unsigned getPfmCounterId(llvm::StringRef Name) const {
44 const auto It = PfmCounterNameTable.find(Name);
45 if (It == PfmCounterNameTable.end())
46 PrintFatalError("no pfm counter id for " + Name);
47 return It->second;
48 }
49
50 // Collects all the ProcPfmCounters definitions available in this target.
51 void emitPfmCounters(raw_ostream &OS) const;
52
53 void emitPfmCountersInfo(const Record &Def,
54 unsigned &IssueCountersTableOffset,
55 raw_ostream &OS) const;
56
57 void emitPfmCountersLookupTable(raw_ostream &OS) const;
58
59 RecordKeeper &Records;
60 std::string Target;
61
62 // Table of counter name -> counter index.
63 const std::map<llvm::StringRef, unsigned> PfmCounterNameTable;
64};
65
66static std::map<llvm::StringRef, unsigned>
67collectPfmCounters(const RecordKeeper &Records) {
68 std::map<llvm::StringRef, unsigned> PfmCounterNameTable;
69 const auto AddPfmCounterName = [&PfmCounterNameTable](
70 const Record *PfmCounterDef) {
71 const llvm::StringRef Counter = PfmCounterDef->getValueAsString("Counter");
72 if (!Counter.empty())
73 PfmCounterNameTable.emplace(Counter, 0);
74 };
75 for (Record *Def : Records.getAllDerivedDefinitions("ProcPfmCounters")) {
76 // Check that ResourceNames are unique.
77 llvm::SmallSet<llvm::StringRef, 16> Seen;
78 for (const Record *IssueCounter :
79 Def->getValueAsListOfDefs("IssueCounters")) {
80 const llvm::StringRef ResourceName =
81 IssueCounter->getValueAsString("ResourceName");
82 if (ResourceName.empty())
83 PrintFatalError(IssueCounter->getLoc(), "invalid empty ResourceName");
84 if (!Seen.insert(ResourceName).second)
85 PrintFatalError(IssueCounter->getLoc(),
86 "duplicate ResourceName " + ResourceName);
87 AddPfmCounterName(IssueCounter);
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
98ExegesisEmitter::ExegesisEmitter(RecordKeeper &RK)
99 : Records(RK), PfmCounterNameTable(collectPfmCounters(RK)) {
100 std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target");
101 if (Targets.size() == 0)
102 PrintFatalError("ERROR: No 'Target' subclasses defined!");
103 if (Targets.size() != 1)
104 PrintFatalError("ERROR: Multiple subclasses of Target defined!");
105 Target = Targets[0]->getName();
106}
107
108void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
109 unsigned &IssueCountersTableOffset,
110 raw_ostream &OS) const {
111 const auto CycleCounter =
112 Def.getValueAsDef("CycleCounter")->getValueAsString("Counter");
113 const auto UopsCounter =
114 Def.getValueAsDef("UopsCounter")->getValueAsString("Counter");
115 const size_t NumIssueCounters =
116 Def.getValueAsListOfDefs("IssueCounters").size();
117
Clement Courbetf4fb61b2018-10-25 07:44:01 +0000118 OS << "\nstatic const PfmCountersInfo " << Target << Def.getName()
119 << " = {\n";
120
121 // Cycle Counter.
122 if (CycleCounter.empty())
123 OS << " nullptr, // No cycle counter.\n";
124 else
125 OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(CycleCounter)
126 << "], // Cycle counter\n";
127
128 // Uops Counter.
129 if (UopsCounter.empty())
130 OS << " nullptr, // No uops counter.\n";
131 else
132 OS << " " << Target << "PfmCounterNames[" << getPfmCounterId(UopsCounter)
133 << "], // Uops counter\n";
134
135 // Issue Counters
136 if (NumIssueCounters == 0)
137 OS << " nullptr, // No issue counters.\n 0\n";
138 else
139 OS << " " << Target << "PfmIssueCounters + " << IssueCountersTableOffset
140 << ", " << NumIssueCounters << " // Issue counters.\n";
141
142 OS << "};\n";
143 IssueCountersTableOffset += NumIssueCounters;
144}
145
146void ExegesisEmitter::emitPfmCounters(raw_ostream &OS) const {
147 // Emit the counter name table.
148 OS << "\nstatic const char* " << Target << "PfmCounterNames[] = {\n";
149 for (const auto &NameAndIndex : PfmCounterNameTable)
150 OS << " \"" << NameAndIndex.first << "\", // " << NameAndIndex.second
151 << "\n";
152 OS << "};\n\n";
153
154 // Emit the IssueCounters table.
155 const auto PfmCounterDefs =
156 Records.getAllDerivedDefinitions("ProcPfmCounters");
Clement Courbetb4abfc22018-11-09 13:15:32 +0000157 // Only emit if non-empty.
158 const bool HasAtLeastOnePfmIssueCounter =
159 llvm::any_of(PfmCounterDefs, [](const Record *Def) {
160 return !Def->getValueAsListOfDefs("IssueCounters").empty();
161 });
162 if (HasAtLeastOnePfmIssueCounter) {
163 OS << "static const PfmCountersInfo::IssueCounter " << Target
164 << "PfmIssueCounters[] = {\n";
165 for (const Record *Def : PfmCounterDefs) {
166 for (const Record *ICDef : Def->getValueAsListOfDefs("IssueCounters"))
167 OS << " { " << Target << "PfmCounterNames["
168 << getPfmCounterId(ICDef->getValueAsString("Counter")) << "], \""
169 << ICDef->getValueAsString("ResourceName") << "\"},\n";
170 }
171 OS << "};\n";
Clement Courbetf4fb61b2018-10-25 07:44:01 +0000172 }
173
Clement Courbetf4fb61b2018-10-25 07:44:01 +0000174 // Now generate the PfmCountersInfo.
175 unsigned IssueCountersTableOffset = 0;
176 for (const Record *Def : PfmCounterDefs)
177 emitPfmCountersInfo(*Def, IssueCountersTableOffset, OS);
178
179 OS << "\n";
Clement Courbetb4abfc22018-11-09 13:15:32 +0000180} // namespace
Clement Courbetf4fb61b2018-10-25 07:44:01 +0000181
182void ExegesisEmitter::emitPfmCountersLookupTable(raw_ostream &OS) const {
183 std::vector<Record *> Bindings =
184 Records.getAllDerivedDefinitions("PfmCountersBinding");
Clement Courbetb4abfc22018-11-09 13:15:32 +0000185 assert(!Bindings.empty() && "there must be at least one binding");
Clement Courbetf4fb61b2018-10-25 07:44:01 +0000186 llvm::sort(Bindings, [](const Record *L, const Record *R) {
187 return L->getValueAsString("CpuName") < R->getValueAsString("CpuName");
188 });
189
190 OS << "// Sorted (by CpuName) array of pfm counters.\n"
191 << "static const CpuAndPfmCounters " << Target << "CpuPfmCounters[] = {\n";
192 for (Record *Binding : Bindings) {
193 // Emit as { "cpu", procinit },
194 OS << " { \"" //
195 << Binding->getValueAsString("CpuName") << "\"," //
196 << " &" << Target << Binding->getValueAsDef("Counters")->getName() //
197 << " },\n";
198 }
199 OS << "};\n\n";
200}
201
202void ExegesisEmitter::run(raw_ostream &OS) const {
203 emitSourceFileHeader("Exegesis Tables", OS);
204 emitPfmCounters(OS);
205 emitPfmCountersLookupTable(OS);
206}
207
208} // end anonymous namespace
209
210namespace llvm {
211
212void EmitExegesis(RecordKeeper &RK, raw_ostream &OS) {
213 ExegesisEmitter(RK).run(OS);
214}
215
216} // end namespace llvm