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