]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/utils/TableGen/ExegesisEmitter.cpp
Pull in r366369 from upstream llvm trunk (by Francis Visoiu Mistrih):
[FreeBSD/FreeBSD.git] / contrib / llvm / utils / TableGen / ExegesisEmitter.cpp
1 //===- 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/STLExtras.h"
15 #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
30 using namespace llvm;
31
32 #define DEBUG_TYPE "exegesis-emitter"
33
34 namespace {
35
36 class ExegesisEmitter {
37 public:
38   ExegesisEmitter(RecordKeeper &RK);
39
40   void run(raw_ostream &OS) const;
41
42 private:
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
66 static std::map<llvm::StringRef, unsigned>
67 collectPfmCounters(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
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("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
108 void 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
118   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
146 void 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");
157   // 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";
172   }
173
174   // Now generate the PfmCountersInfo.
175   unsigned IssueCountersTableOffset = 0;
176   for (const Record *Def : PfmCounterDefs)
177     emitPfmCountersInfo(*Def, IssueCountersTableOffset, OS);
178
179   OS << "\n";
180 } // namespace
181
182 void ExegesisEmitter::emitPfmCountersLookupTable(raw_ostream &OS) const {
183   std::vector<Record *> Bindings =
184       Records.getAllDerivedDefinitions("PfmCountersBinding");
185   assert(!Bindings.empty() && "there must be at least one binding");
186   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
202 void ExegesisEmitter::run(raw_ostream &OS) const {
203   emitSourceFileHeader("Exegesis Tables", OS);
204   emitPfmCounters(OS);
205   emitPfmCountersLookupTable(OS);
206 }
207
208 } // end anonymous namespace
209
210 namespace llvm {
211
212 void EmitExegesis(RecordKeeper &RK, raw_ostream &OS) {
213   ExegesisEmitter(RK).run(OS);
214 }
215
216 } // end namespace llvm