1 | //===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===// |
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 is responsible for emitting a description of a target |
10 | // register file for a code generator. It uses instances of the Register, |
11 | // RegisterAliases, and RegisterClass classes to gather this information. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "Basic/SequenceToOffsetTable.h" |
16 | #include "Common/CodeGenHwModes.h" |
17 | #include "Common/CodeGenRegisters.h" |
18 | #include "Common/CodeGenTarget.h" |
19 | #include "Common/InfoByHwMode.h" |
20 | #include "Common/Types.h" |
21 | #include "llvm/ADT/ArrayRef.h" |
22 | #include "llvm/ADT/BitVector.h" |
23 | #include "llvm/ADT/STLExtras.h" |
24 | #include "llvm/ADT/SetVector.h" |
25 | #include "llvm/ADT/SmallVector.h" |
26 | #include "llvm/ADT/SparseBitVector.h" |
27 | #include "llvm/ADT/Twine.h" |
28 | #include "llvm/CodeGenTypes/MachineValueType.h" |
29 | #include "llvm/Support/Casting.h" |
30 | #include "llvm/Support/CommandLine.h" |
31 | #include "llvm/Support/Format.h" |
32 | #include "llvm/Support/raw_ostream.h" |
33 | #include "llvm/TableGen/Error.h" |
34 | #include "llvm/TableGen/Record.h" |
35 | #include "llvm/TableGen/SetTheory.h" |
36 | #include "llvm/TableGen/TableGenBackend.h" |
37 | #include <algorithm> |
38 | #include <cassert> |
39 | #include <cstddef> |
40 | #include <cstdint> |
41 | #include <deque> |
42 | #include <iterator> |
43 | #include <set> |
44 | #include <string> |
45 | #include <vector> |
46 | |
47 | using namespace llvm; |
48 | |
49 | cl::OptionCategory RegisterInfoCat("Options for -gen-register-info" ); |
50 | |
51 | static cl::opt<bool> |
52 | RegisterInfoDebug("register-info-debug" , cl::init(Val: false), |
53 | cl::desc("Dump register information to help debugging" ), |
54 | cl::cat(RegisterInfoCat)); |
55 | |
56 | namespace { |
57 | |
58 | class RegisterInfoEmitter { |
59 | CodeGenTarget Target; |
60 | RecordKeeper &Records; |
61 | |
62 | public: |
63 | RegisterInfoEmitter(RecordKeeper &R) : Target(R), Records(R) { |
64 | CodeGenRegBank &RegBank = Target.getRegBank(); |
65 | RegBank.computeDerivedInfo(); |
66 | } |
67 | |
68 | // runEnums - Print out enum values for all of the registers. |
69 | void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); |
70 | |
71 | // runMCDesc - Print out MC register descriptions. |
72 | void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); |
73 | |
74 | // runTargetHeader - Emit a header fragment for the register info emitter. |
75 | void runTargetHeader(raw_ostream &o, CodeGenTarget &Target, |
76 | CodeGenRegBank &Bank); |
77 | |
78 | // runTargetDesc - Output the target register and register file descriptions. |
79 | void runTargetDesc(raw_ostream &o, CodeGenTarget &Target, |
80 | CodeGenRegBank &Bank); |
81 | |
82 | // run - Output the register file description. |
83 | void run(raw_ostream &o); |
84 | |
85 | void debugDump(raw_ostream &OS); |
86 | |
87 | private: |
88 | void EmitRegMapping(raw_ostream &o, const std::deque<CodeGenRegister> &Regs, |
89 | bool isCtor); |
90 | void EmitRegMappingTables(raw_ostream &o, |
91 | const std::deque<CodeGenRegister> &Regs, |
92 | bool isCtor); |
93 | void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, |
94 | const std::string &ClassName); |
95 | void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank, |
96 | const std::string &ClassName); |
97 | void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank, |
98 | const std::string &ClassName); |
99 | }; |
100 | |
101 | } // end anonymous namespace |
102 | |
103 | // runEnums - Print out enum values for all of the registers. |
104 | void RegisterInfoEmitter::runEnums(raw_ostream &OS, CodeGenTarget &Target, |
105 | CodeGenRegBank &Bank) { |
106 | const auto &Registers = Bank.getRegisters(); |
107 | |
108 | // Register enums are stored as uint16_t in the tables. Make sure we'll fit. |
109 | assert(Registers.size() <= 0xffff && "Too many regs to fit in tables" ); |
110 | |
111 | StringRef Namespace = Registers.front().TheDef->getValueAsString(FieldName: "Namespace" ); |
112 | |
113 | emitSourceFileHeader(Desc: "Target Register Enum Values" , OS); |
114 | |
115 | OS << "\n#ifdef GET_REGINFO_ENUM\n" ; |
116 | OS << "#undef GET_REGINFO_ENUM\n\n" ; |
117 | |
118 | OS << "namespace llvm {\n\n" ; |
119 | |
120 | OS << "class MCRegisterClass;\n" |
121 | << "extern const MCRegisterClass " << Target.getName() |
122 | << "MCRegisterClasses[];\n\n" ; |
123 | |
124 | if (!Namespace.empty()) |
125 | OS << "namespace " << Namespace << " {\n" ; |
126 | OS << "enum {\n NoRegister,\n" ; |
127 | |
128 | for (const auto &Reg : Registers) |
129 | OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n" ; |
130 | assert(Registers.size() == Registers.back().EnumValue && |
131 | "Register enum value mismatch!" ); |
132 | OS << " NUM_TARGET_REGS // " << Registers.size() + 1 << "\n" ; |
133 | OS << "};\n" ; |
134 | if (!Namespace.empty()) |
135 | OS << "} // end namespace " << Namespace << "\n" ; |
136 | |
137 | const auto &RegisterClasses = Bank.getRegClasses(); |
138 | if (!RegisterClasses.empty()) { |
139 | |
140 | // RegisterClass enums are stored as uint16_t in the tables. |
141 | assert(RegisterClasses.size() <= 0xffff && |
142 | "Too many register classes to fit in tables" ); |
143 | |
144 | OS << "\n// Register classes\n\n" ; |
145 | if (!Namespace.empty()) |
146 | OS << "namespace " << Namespace << " {\n" ; |
147 | OS << "enum {\n" ; |
148 | for (const auto &RC : RegisterClasses) |
149 | OS << " " << RC.getIdName() << " = " << RC.EnumValue << ",\n" ; |
150 | OS << "\n};\n" ; |
151 | if (!Namespace.empty()) |
152 | OS << "} // end namespace " << Namespace << "\n\n" ; |
153 | } |
154 | |
155 | const std::vector<Record *> &RegAltNameIndices = |
156 | Target.getRegAltNameIndices(); |
157 | // If the only definition is the default NoRegAltName, we don't need to |
158 | // emit anything. |
159 | if (RegAltNameIndices.size() > 1) { |
160 | OS << "\n// Register alternate name indices\n\n" ; |
161 | if (!Namespace.empty()) |
162 | OS << "namespace " << Namespace << " {\n" ; |
163 | OS << "enum {\n" ; |
164 | for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i) |
165 | OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n" ; |
166 | OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n" ; |
167 | OS << "};\n" ; |
168 | if (!Namespace.empty()) |
169 | OS << "} // end namespace " << Namespace << "\n\n" ; |
170 | } |
171 | |
172 | auto &SubRegIndices = Bank.getSubRegIndices(); |
173 | if (!SubRegIndices.empty()) { |
174 | OS << "\n// Subregister indices\n\n" ; |
175 | std::string Namespace = SubRegIndices.front().getNamespace(); |
176 | if (!Namespace.empty()) |
177 | OS << "namespace " << Namespace << " {\n" ; |
178 | OS << "enum : uint16_t {\n NoSubRegister,\n" ; |
179 | unsigned i = 0; |
180 | for (const auto &Idx : SubRegIndices) |
181 | OS << " " << Idx.getName() << ",\t// " << ++i << "\n" ; |
182 | OS << " NUM_TARGET_SUBREGS\n};\n" ; |
183 | if (!Namespace.empty()) |
184 | OS << "} // end namespace " << Namespace << "\n\n" ; |
185 | } |
186 | |
187 | OS << "// Register pressure sets enum.\n" ; |
188 | if (!Namespace.empty()) |
189 | OS << "namespace " << Namespace << " {\n" ; |
190 | OS << "enum RegisterPressureSets {\n" ; |
191 | unsigned NumSets = Bank.getNumRegPressureSets(); |
192 | for (unsigned i = 0; i < NumSets; ++i) { |
193 | const RegUnitSet &RegUnits = Bank.getRegSetAt(Order: i); |
194 | OS << " " << RegUnits.Name << " = " << i << ",\n" ; |
195 | } |
196 | OS << "};\n" ; |
197 | if (!Namespace.empty()) |
198 | OS << "} // end namespace " << Namespace << '\n'; |
199 | OS << '\n'; |
200 | |
201 | OS << "} // end namespace llvm\n\n" ; |
202 | OS << "#endif // GET_REGINFO_ENUM\n\n" ; |
203 | } |
204 | |
205 | static void printInt(raw_ostream &OS, int Val) { OS << Val; } |
206 | |
207 | void RegisterInfoEmitter::EmitRegUnitPressure(raw_ostream &OS, |
208 | const CodeGenRegBank &RegBank, |
209 | const std::string &ClassName) { |
210 | unsigned NumRCs = RegBank.getRegClasses().size(); |
211 | unsigned NumSets = RegBank.getNumRegPressureSets(); |
212 | |
213 | OS << "/// Get the weight in units of pressure for this register class.\n" |
214 | << "const RegClassWeight &" << ClassName << "::\n" |
215 | << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" |
216 | << " static const RegClassWeight RCWeightTable[] = {\n" ; |
217 | for (const auto &RC : RegBank.getRegClasses()) { |
218 | const CodeGenRegister::Vec &Regs = RC.getMembers(); |
219 | OS << " {" << RC.getWeight(RegBank) << ", " ; |
220 | if (Regs.empty() || RC.Artificial) |
221 | OS << '0'; |
222 | else { |
223 | std::vector<unsigned> RegUnits; |
224 | RC.buildRegUnitSet(RegBank, RegUnits); |
225 | OS << RegBank.getRegUnitSetWeight(Units: RegUnits); |
226 | } |
227 | OS << "}, \t// " << RC.getName() << "\n" ; |
228 | } |
229 | OS << " };\n" |
230 | << " return RCWeightTable[RC->getID()];\n" |
231 | << "}\n\n" ; |
232 | |
233 | // Reasonable targets (not ARMv7) have unit weight for all units, so don't |
234 | // bother generating a table. |
235 | bool RegUnitsHaveUnitWeight = true; |
236 | for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); |
237 | UnitIdx < UnitEnd; ++UnitIdx) { |
238 | if (RegBank.getRegUnit(RUID: UnitIdx).Weight > 1) |
239 | RegUnitsHaveUnitWeight = false; |
240 | } |
241 | OS << "/// Get the weight in units of pressure for this register unit.\n" |
242 | << "unsigned " << ClassName << "::\n" |
243 | << "getRegUnitWeight(unsigned RegUnit) const {\n" |
244 | << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() |
245 | << " && \"invalid register unit\");\n" ; |
246 | if (!RegUnitsHaveUnitWeight) { |
247 | OS << " static const uint8_t RUWeightTable[] = {\n " ; |
248 | for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); |
249 | UnitIdx < UnitEnd; ++UnitIdx) { |
250 | const RegUnit &RU = RegBank.getRegUnit(RUID: UnitIdx); |
251 | assert(RU.Weight < 256 && "RegUnit too heavy" ); |
252 | OS << RU.Weight << ", " ; |
253 | } |
254 | OS << "};\n" |
255 | << " return RUWeightTable[RegUnit];\n" ; |
256 | } else { |
257 | OS << " // All register units have unit weight.\n" |
258 | << " return 1;\n" ; |
259 | } |
260 | OS << "}\n\n" ; |
261 | |
262 | OS << "\n" |
263 | << "// Get the number of dimensions of register pressure.\n" |
264 | << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n" |
265 | << " return " << NumSets << ";\n}\n\n" ; |
266 | |
267 | OS << "// Get the name of this register unit pressure set.\n" |
268 | << "const char *" << ClassName << "::\n" |
269 | << "getRegPressureSetName(unsigned Idx) const {\n" |
270 | << " static const char *PressureNameTable[] = {\n" ; |
271 | unsigned MaxRegUnitWeight = 0; |
272 | for (unsigned i = 0; i < NumSets; ++i) { |
273 | const RegUnitSet &RegUnits = RegBank.getRegSetAt(Order: i); |
274 | MaxRegUnitWeight = std::max(a: MaxRegUnitWeight, b: RegUnits.Weight); |
275 | OS << " \"" << RegUnits.Name << "\",\n" ; |
276 | } |
277 | OS << " };\n" |
278 | << " return PressureNameTable[Idx];\n" |
279 | << "}\n\n" ; |
280 | |
281 | OS << "// Get the register unit pressure limit for this dimension.\n" |
282 | << "// This limit must be adjusted dynamically for reserved registers.\n" |
283 | << "unsigned " << ClassName << "::\n" |
284 | << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const " |
285 | "{\n" |
286 | << " static const " << getMinimalTypeForRange(Range: MaxRegUnitWeight, MaxSize: 32) |
287 | << " PressureLimitTable[] = {\n" ; |
288 | for (unsigned i = 0; i < NumSets; ++i) { |
289 | const RegUnitSet &RegUnits = RegBank.getRegSetAt(Order: i); |
290 | OS << " " << RegUnits.Weight << ", \t// " << i << ": " << RegUnits.Name |
291 | << "\n" ; |
292 | } |
293 | OS << " };\n" |
294 | << " return PressureLimitTable[Idx];\n" |
295 | << "}\n\n" ; |
296 | |
297 | SequenceToOffsetTable<std::vector<int>> PSetsSeqs; |
298 | |
299 | // This table may be larger than NumRCs if some register units needed a list |
300 | // of unit sets that did not correspond to a register class. |
301 | unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists(); |
302 | std::vector<std::vector<int>> PSets(NumRCUnitSets); |
303 | |
304 | for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) { |
305 | ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(RCIdx: i); |
306 | PSets[i].reserve(n: PSetIDs.size()); |
307 | for (unsigned PSetID : PSetIDs) { |
308 | PSets[i].push_back(x: RegBank.getRegPressureSet(Idx: PSetID).Order); |
309 | } |
310 | llvm::sort(C&: PSets[i]); |
311 | PSetsSeqs.add(Seq: PSets[i]); |
312 | } |
313 | |
314 | PSetsSeqs.layout(); |
315 | |
316 | OS << "/// Table of pressure sets per register class or unit.\n" |
317 | << "static const int RCSetsTable[] = {\n" ; |
318 | PSetsSeqs.emit(OS, Print: printInt, Term: "-1" ); |
319 | OS << "};\n\n" ; |
320 | |
321 | OS << "/// Get the dimensions of register pressure impacted by this " |
322 | << "register class.\n" |
323 | << "/// Returns a -1 terminated array of pressure set IDs\n" |
324 | << "const int *" << ClassName << "::\n" |
325 | << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n" ; |
326 | OS << " static const " << getMinimalTypeForRange(Range: PSetsSeqs.size() - 1, MaxSize: 32) |
327 | << " RCSetStartTable[] = {\n " ; |
328 | for (unsigned i = 0, e = NumRCs; i != e; ++i) { |
329 | OS << PSetsSeqs.get(Seq: PSets[i]) << "," ; |
330 | } |
331 | OS << "};\n" |
332 | << " return &RCSetsTable[RCSetStartTable[RC->getID()]];\n" |
333 | << "}\n\n" ; |
334 | |
335 | OS << "/// Get the dimensions of register pressure impacted by this " |
336 | << "register unit.\n" |
337 | << "/// Returns a -1 terminated array of pressure set IDs\n" |
338 | << "const int *" << ClassName << "::\n" |
339 | << "getRegUnitPressureSets(unsigned RegUnit) const {\n" |
340 | << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() |
341 | << " && \"invalid register unit\");\n" ; |
342 | OS << " static const " << getMinimalTypeForRange(Range: PSetsSeqs.size() - 1, MaxSize: 32) |
343 | << " RUSetStartTable[] = {\n " ; |
344 | for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); |
345 | UnitIdx < UnitEnd; ++UnitIdx) { |
346 | OS << PSetsSeqs.get(Seq: PSets[RegBank.getRegUnit(RUID: UnitIdx).RegClassUnitSetsIdx]) |
347 | << "," ; |
348 | } |
349 | OS << "};\n" |
350 | << " return &RCSetsTable[RUSetStartTable[RegUnit]];\n" |
351 | << "}\n\n" ; |
352 | } |
353 | |
354 | using DwarfRegNumsMapPair = std::pair<Record *, std::vector<int64_t>>; |
355 | using DwarfRegNumsVecTy = std::vector<DwarfRegNumsMapPair>; |
356 | |
357 | static void finalizeDwarfRegNumsKeys(DwarfRegNumsVecTy &DwarfRegNums) { |
358 | // Sort and unique to get a map-like vector. We want the last assignment to |
359 | // match previous behaviour. |
360 | llvm::stable_sort(Range&: DwarfRegNums, C: on_first<LessRecordRegister>()); |
361 | // Warn about duplicate assignments. |
362 | const Record *LastSeenReg = nullptr; |
363 | for (const auto &X : DwarfRegNums) { |
364 | const auto &Reg = X.first; |
365 | // The only way LessRecordRegister can return equal is if they're the same |
366 | // string. Use simple equality instead. |
367 | if (LastSeenReg && Reg->getName() == LastSeenReg->getName()) |
368 | PrintWarning(WarningLoc: Reg->getLoc(), Msg: Twine("DWARF numbers for register " ) + |
369 | getQualifiedName(R: Reg) + |
370 | "specified multiple times" ); |
371 | LastSeenReg = Reg; |
372 | } |
373 | auto Last = llvm::unique(R&: DwarfRegNums, P: [](const DwarfRegNumsMapPair &A, |
374 | const DwarfRegNumsMapPair &B) { |
375 | return A.first->getName() == B.first->getName(); |
376 | }); |
377 | DwarfRegNums.erase(first: Last, last: DwarfRegNums.end()); |
378 | } |
379 | |
380 | void RegisterInfoEmitter::EmitRegMappingTables( |
381 | raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) { |
382 | // Collect all information about dwarf register numbers |
383 | DwarfRegNumsVecTy DwarfRegNums; |
384 | |
385 | // First, just pull all provided information to the map |
386 | unsigned maxLength = 0; |
387 | for (auto &RE : Regs) { |
388 | Record *Reg = RE.TheDef; |
389 | std::vector<int64_t> RegNums = Reg->getValueAsListOfInts(FieldName: "DwarfNumbers" ); |
390 | maxLength = std::max(a: (size_t)maxLength, b: RegNums.size()); |
391 | DwarfRegNums.emplace_back(args&: Reg, args: std::move(RegNums)); |
392 | } |
393 | finalizeDwarfRegNumsKeys(DwarfRegNums); |
394 | |
395 | if (!maxLength) |
396 | return; |
397 | |
398 | // Now we know maximal length of number list. Append -1's, where needed |
399 | for (auto &DwarfRegNum : DwarfRegNums) |
400 | for (unsigned I = DwarfRegNum.second.size(), E = maxLength; I != E; ++I) |
401 | DwarfRegNum.second.push_back(x: -1); |
402 | |
403 | StringRef Namespace = Regs.front().TheDef->getValueAsString(FieldName: "Namespace" ); |
404 | |
405 | OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n" ; |
406 | |
407 | // Emit reverse information about the dwarf register numbers. |
408 | for (unsigned j = 0; j < 2; ++j) { |
409 | for (unsigned I = 0, E = maxLength; I != E; ++I) { |
410 | OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; |
411 | OS << (j == 0 ? "DwarfFlavour" : "EHFlavour" ); |
412 | OS << I << "Dwarf2L[]" ; |
413 | |
414 | if (!isCtor) { |
415 | OS << " = {\n" ; |
416 | |
417 | // Store the mapping sorted by the LLVM reg num so lookup can be done |
418 | // with a binary search. |
419 | std::map<uint64_t, Record *> Dwarf2LMap; |
420 | for (auto &DwarfRegNum : DwarfRegNums) { |
421 | int DwarfRegNo = DwarfRegNum.second[I]; |
422 | if (DwarfRegNo < 0) |
423 | continue; |
424 | Dwarf2LMap[DwarfRegNo] = DwarfRegNum.first; |
425 | } |
426 | |
427 | for (auto &I : Dwarf2LMap) |
428 | OS << " { " << I.first << "U, " << getQualifiedName(R: I.second) |
429 | << " },\n" ; |
430 | |
431 | OS << "};\n" ; |
432 | } else { |
433 | OS << ";\n" ; |
434 | } |
435 | |
436 | // We have to store the size in a const global, it's used in multiple |
437 | // places. |
438 | OS << "extern const unsigned " << Namespace |
439 | << (j == 0 ? "DwarfFlavour" : "EHFlavour" ) << I << "Dwarf2LSize" ; |
440 | if (!isCtor) |
441 | OS << " = std::size(" << Namespace |
442 | << (j == 0 ? "DwarfFlavour" : "EHFlavour" ) << I << "Dwarf2L);\n\n" ; |
443 | else |
444 | OS << ";\n\n" ; |
445 | } |
446 | } |
447 | |
448 | for (auto &RE : Regs) { |
449 | Record *Reg = RE.TheDef; |
450 | const RecordVal *V = Reg->getValue(Name: "DwarfAlias" ); |
451 | if (!V || !V->getValue()) |
452 | continue; |
453 | |
454 | DefInit *DI = cast<DefInit>(Val: V->getValue()); |
455 | Record *Alias = DI->getDef(); |
456 | const auto &AliasIter = llvm::lower_bound( |
457 | Range&: DwarfRegNums, Value&: Alias, C: [](const DwarfRegNumsMapPair &A, const Record *B) { |
458 | return LessRecordRegister()(A.first, B); |
459 | }); |
460 | assert(AliasIter != DwarfRegNums.end() && AliasIter->first == Alias && |
461 | "Expected Alias to be present in map" ); |
462 | const auto &RegIter = llvm::lower_bound( |
463 | Range&: DwarfRegNums, Value&: Reg, C: [](const DwarfRegNumsMapPair &A, const Record *B) { |
464 | return LessRecordRegister()(A.first, B); |
465 | }); |
466 | assert(RegIter != DwarfRegNums.end() && RegIter->first == Reg && |
467 | "Expected Reg to be present in map" ); |
468 | RegIter->second = AliasIter->second; |
469 | } |
470 | |
471 | // Emit information about the dwarf register numbers. |
472 | for (unsigned j = 0; j < 2; ++j) { |
473 | for (unsigned i = 0, e = maxLength; i != e; ++i) { |
474 | OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; |
475 | OS << (j == 0 ? "DwarfFlavour" : "EHFlavour" ); |
476 | OS << i << "L2Dwarf[]" ; |
477 | if (!isCtor) { |
478 | OS << " = {\n" ; |
479 | // Store the mapping sorted by the Dwarf reg num so lookup can be done |
480 | // with a binary search. |
481 | for (auto &DwarfRegNum : DwarfRegNums) { |
482 | int RegNo = DwarfRegNum.second[i]; |
483 | if (RegNo == -1) // -1 is the default value, don't emit a mapping. |
484 | continue; |
485 | |
486 | OS << " { " << getQualifiedName(R: DwarfRegNum.first) << ", " << RegNo |
487 | << "U },\n" ; |
488 | } |
489 | OS << "};\n" ; |
490 | } else { |
491 | OS << ";\n" ; |
492 | } |
493 | |
494 | // We have to store the size in a const global, it's used in multiple |
495 | // places. |
496 | OS << "extern const unsigned " << Namespace |
497 | << (j == 0 ? "DwarfFlavour" : "EHFlavour" ) << i << "L2DwarfSize" ; |
498 | if (!isCtor) |
499 | OS << " = std::size(" << Namespace |
500 | << (j == 0 ? "DwarfFlavour" : "EHFlavour" ) << i << "L2Dwarf);\n\n" ; |
501 | else |
502 | OS << ";\n\n" ; |
503 | } |
504 | } |
505 | } |
506 | |
507 | void RegisterInfoEmitter::EmitRegMapping( |
508 | raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) { |
509 | // Emit the initializer so the tables from EmitRegMappingTables get wired up |
510 | // to the MCRegisterInfo object. |
511 | unsigned maxLength = 0; |
512 | for (auto &RE : Regs) { |
513 | Record *Reg = RE.TheDef; |
514 | maxLength = std::max(a: (size_t)maxLength, |
515 | b: Reg->getValueAsListOfInts(FieldName: "DwarfNumbers" ).size()); |
516 | } |
517 | |
518 | if (!maxLength) |
519 | return; |
520 | |
521 | StringRef Namespace = Regs.front().TheDef->getValueAsString(FieldName: "Namespace" ); |
522 | |
523 | // Emit reverse information about the dwarf register numbers. |
524 | for (unsigned j = 0; j < 2; ++j) { |
525 | OS << " switch (" ; |
526 | if (j == 0) |
527 | OS << "DwarfFlavour" ; |
528 | else |
529 | OS << "EHFlavour" ; |
530 | OS << ") {\n" |
531 | << " default:\n" |
532 | << " llvm_unreachable(\"Unknown DWARF flavour\");\n" ; |
533 | |
534 | for (unsigned i = 0, e = maxLength; i != e; ++i) { |
535 | OS << " case " << i << ":\n" ; |
536 | OS << " " ; |
537 | if (!isCtor) |
538 | OS << "RI->" ; |
539 | std::string Tmp; |
540 | raw_string_ostream(Tmp) |
541 | << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour" ) << i |
542 | << "Dwarf2L" ; |
543 | OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, " ; |
544 | if (j == 0) |
545 | OS << "false" ; |
546 | else |
547 | OS << "true" ; |
548 | OS << ");\n" ; |
549 | OS << " break;\n" ; |
550 | } |
551 | OS << " }\n" ; |
552 | } |
553 | |
554 | // Emit information about the dwarf register numbers. |
555 | for (unsigned j = 0; j < 2; ++j) { |
556 | OS << " switch (" ; |
557 | if (j == 0) |
558 | OS << "DwarfFlavour" ; |
559 | else |
560 | OS << "EHFlavour" ; |
561 | OS << ") {\n" |
562 | << " default:\n" |
563 | << " llvm_unreachable(\"Unknown DWARF flavour\");\n" ; |
564 | |
565 | for (unsigned i = 0, e = maxLength; i != e; ++i) { |
566 | OS << " case " << i << ":\n" ; |
567 | OS << " " ; |
568 | if (!isCtor) |
569 | OS << "RI->" ; |
570 | std::string Tmp; |
571 | raw_string_ostream(Tmp) |
572 | << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour" ) << i |
573 | << "L2Dwarf" ; |
574 | OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, " ; |
575 | if (j == 0) |
576 | OS << "false" ; |
577 | else |
578 | OS << "true" ; |
579 | OS << ");\n" ; |
580 | OS << " break;\n" ; |
581 | } |
582 | OS << " }\n" ; |
583 | } |
584 | } |
585 | |
586 | // Print a BitVector as a sequence of hex numbers using a little-endian mapping. |
587 | // Width is the number of bits per hex number. |
588 | static void printBitVectorAsHex(raw_ostream &OS, const BitVector &Bits, |
589 | unsigned Width) { |
590 | assert(Width <= 32 && "Width too large" ); |
591 | unsigned Digits = (Width + 3) / 4; |
592 | for (unsigned i = 0, e = Bits.size(); i < e; i += Width) { |
593 | unsigned Value = 0; |
594 | for (unsigned j = 0; j != Width && i + j != e; ++j) |
595 | Value |= Bits.test(Idx: i + j) << j; |
596 | OS << format(Fmt: "0x%0*x, " , Vals: Digits, Vals: Value); |
597 | } |
598 | } |
599 | |
600 | // Helper to emit a set of bits into a constant byte array. |
601 | class BitVectorEmitter { |
602 | BitVector Values; |
603 | |
604 | public: |
605 | void add(unsigned v) { |
606 | if (v >= Values.size()) |
607 | Values.resize(N: ((v / 8) + 1) * 8); // Round up to the next byte. |
608 | Values[v] = true; |
609 | } |
610 | |
611 | void print(raw_ostream &OS) { printBitVectorAsHex(OS, Bits: Values, Width: 8); } |
612 | }; |
613 | |
614 | static void printSimpleValueType(raw_ostream &OS, MVT::SimpleValueType VT) { |
615 | OS << getEnumName(T: VT); |
616 | } |
617 | |
618 | static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) { |
619 | OS << Idx->EnumValue; |
620 | } |
621 | |
622 | // Differentially encoded register and regunit lists allow for better |
623 | // compression on regular register banks. The sequence is computed from the |
624 | // differential list as: |
625 | // |
626 | // out[0] = InitVal; |
627 | // out[n+1] = out[n] + diff[n]; // n = 0, 1, ... |
628 | // |
629 | // The initial value depends on the specific list. The list is terminated by a |
630 | // 0 differential which means we can't encode repeated elements. |
631 | |
632 | typedef SmallVector<int16_t, 4> DiffVec; |
633 | typedef SmallVector<LaneBitmask, 4> MaskVec; |
634 | |
635 | // Fills V with differentials between every two consecutive elements of List. |
636 | static DiffVec &diffEncode(DiffVec &V, SparseBitVector<> List) { |
637 | assert(V.empty() && "Clear DiffVec before diffEncode." ); |
638 | SparseBitVector<>::iterator I = List.begin(), E = List.end(); |
639 | unsigned Val = *I; |
640 | while (++I != E) { |
641 | unsigned Cur = *I; |
642 | V.push_back(Elt: Cur - Val); |
643 | Val = Cur; |
644 | } |
645 | return V; |
646 | } |
647 | |
648 | template <typename Iter> |
649 | static DiffVec &diffEncode(DiffVec &V, unsigned InitVal, Iter Begin, Iter End) { |
650 | assert(V.empty() && "Clear DiffVec before diffEncode." ); |
651 | unsigned Val = InitVal; |
652 | for (Iter I = Begin; I != End; ++I) { |
653 | unsigned Cur = (*I)->EnumValue; |
654 | V.push_back(Elt: Cur - Val); |
655 | Val = Cur; |
656 | } |
657 | return V; |
658 | } |
659 | |
660 | static void printDiff16(raw_ostream &OS, int16_t Val) { OS << Val; } |
661 | |
662 | static void printMask(raw_ostream &OS, LaneBitmask Val) { |
663 | OS << "LaneBitmask(0x" << PrintLaneMask(LaneMask: Val) << ')'; |
664 | } |
665 | |
666 | // Try to combine Idx's compose map into Vec if it is compatible. |
667 | // Return false if it's not possible. |
668 | static bool combine(const CodeGenSubRegIndex *Idx, |
669 | SmallVectorImpl<CodeGenSubRegIndex *> &Vec) { |
670 | const CodeGenSubRegIndex::CompMap &Map = Idx->getComposites(); |
671 | for (const auto &I : Map) { |
672 | CodeGenSubRegIndex *&Entry = Vec[I.first->EnumValue - 1]; |
673 | if (Entry && Entry != I.second) |
674 | return false; |
675 | } |
676 | |
677 | // All entries are compatible. Make it so. |
678 | for (const auto &I : Map) { |
679 | auto *&Entry = Vec[I.first->EnumValue - 1]; |
680 | assert((!Entry || Entry == I.second) && "Expected EnumValue to be unique" ); |
681 | Entry = I.second; |
682 | } |
683 | return true; |
684 | } |
685 | |
686 | void RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, |
687 | CodeGenRegBank &RegBank, |
688 | const std::string &ClName) { |
689 | const auto &SubRegIndices = RegBank.getSubRegIndices(); |
690 | OS << "unsigned " << ClName |
691 | << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n" ; |
692 | |
693 | // Many sub-register indexes are composition-compatible, meaning that |
694 | // |
695 | // compose(IdxA, IdxB) == compose(IdxA', IdxB) |
696 | // |
697 | // for many IdxA, IdxA' pairs. Not all sub-register indexes can be composed. |
698 | // The illegal entries can be use as wildcards to compress the table further. |
699 | |
700 | // Map each Sub-register index to a compatible table row. |
701 | SmallVector<unsigned, 4> RowMap; |
702 | SmallVector<SmallVector<CodeGenSubRegIndex *, 4>, 4> Rows; |
703 | |
704 | auto SubRegIndicesSize = |
705 | std::distance(first: SubRegIndices.begin(), last: SubRegIndices.end()); |
706 | for (const auto &Idx : SubRegIndices) { |
707 | unsigned Found = ~0u; |
708 | for (unsigned r = 0, re = Rows.size(); r != re; ++r) { |
709 | if (combine(Idx: &Idx, Vec&: Rows[r])) { |
710 | Found = r; |
711 | break; |
712 | } |
713 | } |
714 | if (Found == ~0u) { |
715 | Found = Rows.size(); |
716 | Rows.resize(N: Found + 1); |
717 | Rows.back().resize(N: SubRegIndicesSize); |
718 | combine(Idx: &Idx, Vec&: Rows.back()); |
719 | } |
720 | RowMap.push_back(Elt: Found); |
721 | } |
722 | |
723 | // Output the row map if there is multiple rows. |
724 | if (Rows.size() > 1) { |
725 | OS << " static const " << getMinimalTypeForRange(Range: Rows.size(), MaxSize: 32) |
726 | << " RowMap[" << SubRegIndicesSize << "] = {\n " ; |
727 | for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) |
728 | OS << RowMap[i] << ", " ; |
729 | OS << "\n };\n" ; |
730 | } |
731 | |
732 | // Output the rows. |
733 | OS << " static const " << getMinimalTypeForRange(Range: SubRegIndicesSize + 1, MaxSize: 32) |
734 | << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n" ; |
735 | for (unsigned r = 0, re = Rows.size(); r != re; ++r) { |
736 | OS << " { " ; |
737 | for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) |
738 | if (Rows[r][i]) |
739 | OS << Rows[r][i]->getQualifiedName() << ", " ; |
740 | else |
741 | OS << "0, " ; |
742 | OS << "},\n" ; |
743 | } |
744 | OS << " };\n\n" ; |
745 | |
746 | OS << " --IdxA; assert(IdxA < " << SubRegIndicesSize << "); (void) IdxA;\n" |
747 | << " --IdxB; assert(IdxB < " << SubRegIndicesSize << ");\n" ; |
748 | if (Rows.size() > 1) |
749 | OS << " return Rows[RowMap[IdxA]][IdxB];\n" ; |
750 | else |
751 | OS << " return Rows[0][IdxB];\n" ; |
752 | OS << "}\n\n" ; |
753 | } |
754 | |
755 | void RegisterInfoEmitter::emitComposeSubRegIndexLaneMask( |
756 | raw_ostream &OS, CodeGenRegBank &RegBank, const std::string &ClName) { |
757 | // See the comments in computeSubRegLaneMasks() for our goal here. |
758 | const auto &SubRegIndices = RegBank.getSubRegIndices(); |
759 | |
760 | // Create a list of Mask+Rotate operations, with equivalent entries merged. |
761 | SmallVector<unsigned, 4> SubReg2SequenceIndexMap; |
762 | SmallVector<SmallVector<MaskRolPair, 1>, 4> Sequences; |
763 | for (const auto &Idx : SubRegIndices) { |
764 | const SmallVector<MaskRolPair, 1> &IdxSequence = |
765 | Idx.CompositionLaneMaskTransform; |
766 | |
767 | unsigned Found = ~0u; |
768 | unsigned SIdx = 0; |
769 | unsigned NextSIdx; |
770 | for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) { |
771 | SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s]; |
772 | NextSIdx = SIdx + Sequence.size() + 1; |
773 | if (Sequence == IdxSequence) { |
774 | Found = SIdx; |
775 | break; |
776 | } |
777 | } |
778 | if (Found == ~0u) { |
779 | Sequences.push_back(Elt: IdxSequence); |
780 | Found = SIdx; |
781 | } |
782 | SubReg2SequenceIndexMap.push_back(Elt: Found); |
783 | } |
784 | |
785 | OS << " struct MaskRolOp {\n" |
786 | " LaneBitmask Mask;\n" |
787 | " uint8_t RotateLeft;\n" |
788 | " };\n" |
789 | " static const MaskRolOp LaneMaskComposeSequences[] = {\n" ; |
790 | unsigned Idx = 0; |
791 | for (size_t s = 0, se = Sequences.size(); s != se; ++s) { |
792 | OS << " " ; |
793 | const SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s]; |
794 | for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) { |
795 | const MaskRolPair &P = Sequence[p]; |
796 | printMask(OS&: OS << "{ " , Val: P.Mask); |
797 | OS << format(Fmt: ", %2u }, " , Vals: P.RotateLeft); |
798 | } |
799 | OS << "{ LaneBitmask::getNone(), 0 }" ; |
800 | if (s + 1 != se) |
801 | OS << ", " ; |
802 | OS << " // Sequence " << Idx << "\n" ; |
803 | Idx += Sequence.size() + 1; |
804 | } |
805 | auto *IntType = |
806 | getMinimalTypeForRange(Range: *llvm::max_element(Range&: SubReg2SequenceIndexMap)); |
807 | OS << " };\n" |
808 | " static const " |
809 | << IntType << " CompositeSequences[] = {\n" ; |
810 | for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) { |
811 | OS << " " ; |
812 | OS << SubReg2SequenceIndexMap[i]; |
813 | if (i + 1 != e) |
814 | OS << "," ; |
815 | OS << " // to " << SubRegIndices[i].getName() << "\n" ; |
816 | } |
817 | OS << " };\n\n" ; |
818 | |
819 | OS << "LaneBitmask " << ClName |
820 | << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, LaneBitmask LaneMask)" |
821 | " const {\n" |
822 | " --IdxA; assert(IdxA < " |
823 | << SubRegIndices.size() |
824 | << " && \"Subregister index out of bounds\");\n" |
825 | " LaneBitmask Result;\n" |
826 | " for (const MaskRolOp *Ops =\n" |
827 | " &LaneMaskComposeSequences[CompositeSequences[IdxA]];\n" |
828 | " Ops->Mask.any(); ++Ops) {\n" |
829 | " LaneBitmask::Type M = LaneMask.getAsInteger() & " |
830 | "Ops->Mask.getAsInteger();\n" |
831 | " if (unsigned S = Ops->RotateLeft)\n" |
832 | " Result |= LaneBitmask((M << S) | (M >> (LaneBitmask::BitWidth - " |
833 | "S)));\n" |
834 | " else\n" |
835 | " Result |= LaneBitmask(M);\n" |
836 | " }\n" |
837 | " return Result;\n" |
838 | "}\n\n" ; |
839 | |
840 | OS << "LaneBitmask " << ClName |
841 | << "::reverseComposeSubRegIndexLaneMaskImpl(unsigned IdxA, " |
842 | " LaneBitmask LaneMask) const {\n" |
843 | " LaneMask &= getSubRegIndexLaneMask(IdxA);\n" |
844 | " --IdxA; assert(IdxA < " |
845 | << SubRegIndices.size() |
846 | << " && \"Subregister index out of bounds\");\n" |
847 | " LaneBitmask Result;\n" |
848 | " for (const MaskRolOp *Ops =\n" |
849 | " &LaneMaskComposeSequences[CompositeSequences[IdxA]];\n" |
850 | " Ops->Mask.any(); ++Ops) {\n" |
851 | " LaneBitmask::Type M = LaneMask.getAsInteger();\n" |
852 | " if (unsigned S = Ops->RotateLeft)\n" |
853 | " Result |= LaneBitmask((M >> S) | (M << (LaneBitmask::BitWidth - " |
854 | "S)));\n" |
855 | " else\n" |
856 | " Result |= LaneBitmask(M);\n" |
857 | " }\n" |
858 | " return Result;\n" |
859 | "}\n\n" ; |
860 | } |
861 | |
862 | // |
863 | // runMCDesc - Print out MC register descriptions. |
864 | // |
865 | void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, |
866 | CodeGenRegBank &RegBank) { |
867 | emitSourceFileHeader(Desc: "MC Register Information" , OS); |
868 | |
869 | OS << "\n#ifdef GET_REGINFO_MC_DESC\n" ; |
870 | OS << "#undef GET_REGINFO_MC_DESC\n\n" ; |
871 | |
872 | const auto &Regs = RegBank.getRegisters(); |
873 | |
874 | auto &SubRegIndices = RegBank.getSubRegIndices(); |
875 | // The lists of sub-registers and super-registers go in the same array. That |
876 | // allows us to share suffixes. |
877 | typedef std::vector<const CodeGenRegister *> RegVec; |
878 | |
879 | // Differentially encoded lists. |
880 | SequenceToOffsetTable<DiffVec> DiffSeqs; |
881 | SmallVector<DiffVec, 4> SubRegLists(Regs.size()); |
882 | SmallVector<DiffVec, 4> SuperRegLists(Regs.size()); |
883 | SmallVector<DiffVec, 4> RegUnitLists(Regs.size()); |
884 | |
885 | // List of lane masks accompanying register unit sequences. |
886 | SequenceToOffsetTable<MaskVec> LaneMaskSeqs; |
887 | SmallVector<MaskVec, 4> RegUnitLaneMasks(Regs.size()); |
888 | |
889 | // Keep track of sub-register names as well. These are not differentially |
890 | // encoded. |
891 | typedef SmallVector<const CodeGenSubRegIndex *, 4> SubRegIdxVec; |
892 | SequenceToOffsetTable<SubRegIdxVec, deref<std::less<>>> SubRegIdxSeqs; |
893 | SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size()); |
894 | |
895 | SequenceToOffsetTable<std::string> RegStrings; |
896 | |
897 | // Precompute register lists for the SequenceToOffsetTable. |
898 | unsigned i = 0; |
899 | for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I, ++i) { |
900 | const auto &Reg = *I; |
901 | RegStrings.add(Seq: std::string(Reg.getName())); |
902 | |
903 | // Compute the ordered sub-register list. |
904 | SetVector<const CodeGenRegister *> SR; |
905 | Reg.addSubRegsPreOrder(OSet&: SR, RegBank); |
906 | diffEncode(V&: SubRegLists[i], InitVal: Reg.EnumValue, Begin: SR.begin(), End: SR.end()); |
907 | DiffSeqs.add(Seq: SubRegLists[i]); |
908 | |
909 | // Compute the corresponding sub-register indexes. |
910 | SubRegIdxVec &SRIs = SubRegIdxLists[i]; |
911 | for (const CodeGenRegister *S : SR) |
912 | SRIs.push_back(Elt: Reg.getSubRegIndex(Reg: S)); |
913 | SubRegIdxSeqs.add(Seq: SRIs); |
914 | |
915 | // Super-registers are already computed. |
916 | const RegVec &SuperRegList = Reg.getSuperRegs(); |
917 | diffEncode(V&: SuperRegLists[i], InitVal: Reg.EnumValue, Begin: SuperRegList.begin(), |
918 | End: SuperRegList.end()); |
919 | DiffSeqs.add(Seq: SuperRegLists[i]); |
920 | |
921 | const SparseBitVector<> &RUs = Reg.getNativeRegUnits(); |
922 | DiffSeqs.add(Seq: diffEncode(V&: RegUnitLists[i], List: RUs)); |
923 | |
924 | const auto &RUMasks = Reg.getRegUnitLaneMasks(); |
925 | MaskVec &LaneMaskVec = RegUnitLaneMasks[i]; |
926 | assert(LaneMaskVec.empty()); |
927 | llvm::append_range(C&: LaneMaskVec, R: RUMasks); |
928 | LaneMaskSeqs.add(Seq: LaneMaskVec); |
929 | } |
930 | |
931 | // Compute the final layout of the sequence table. |
932 | DiffSeqs.layout(); |
933 | LaneMaskSeqs.layout(); |
934 | SubRegIdxSeqs.layout(); |
935 | |
936 | OS << "namespace llvm {\n\n" ; |
937 | |
938 | const std::string &TargetName = std::string(Target.getName()); |
939 | |
940 | // Emit the shared table of differential lists. |
941 | OS << "extern const int16_t " << TargetName << "RegDiffLists[] = {\n" ; |
942 | DiffSeqs.emit(OS, Print: printDiff16); |
943 | OS << "};\n\n" ; |
944 | |
945 | // Emit the shared table of regunit lane mask sequences. |
946 | OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n" ; |
947 | // TODO: Omit the terminator since it is never used. The length of this list |
948 | // is known implicitly from the corresponding reg unit list. |
949 | LaneMaskSeqs.emit(OS, Print: printMask, Term: "LaneBitmask::getAll()" ); |
950 | OS << "};\n\n" ; |
951 | |
952 | // Emit the table of sub-register indexes. |
953 | OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n" ; |
954 | SubRegIdxSeqs.emit(OS, Print: printSubRegIndex); |
955 | OS << "};\n\n" ; |
956 | |
957 | // Emit the string table. |
958 | RegStrings.layout(); |
959 | RegStrings.emitStringLiteralDef(OS, Decl: Twine("extern const char " ) + TargetName + |
960 | "RegStrings[]" ); |
961 | |
962 | OS << "extern const MCRegisterDesc " << TargetName |
963 | << "RegDesc[] = { // Descriptors\n" ; |
964 | OS << " { " << RegStrings.get(Seq: "" ) << ", 0, 0, 0, 0, 0, 0 },\n" ; |
965 | |
966 | // Emit the register descriptors now. |
967 | i = 0; |
968 | for (const auto &Reg : Regs) { |
969 | unsigned FirstRU = Reg.getNativeRegUnits().find_first(); |
970 | unsigned Offset = DiffSeqs.get(Seq: RegUnitLists[i]); |
971 | // The value must be kept in sync with MCRegisterInfo.h. |
972 | constexpr unsigned RegUnitBits = 12; |
973 | assert(isUInt<RegUnitBits>(FirstRU) && "Too many regunits" ); |
974 | assert(isUInt<32 - RegUnitBits>(Offset) && "Offset is too big" ); |
975 | OS << " { " << RegStrings.get(Seq: std::string(Reg.getName())) << ", " |
976 | << DiffSeqs.get(Seq: SubRegLists[i]) << ", " << DiffSeqs.get(Seq: SuperRegLists[i]) |
977 | << ", " << SubRegIdxSeqs.get(Seq: SubRegIdxLists[i]) << ", " |
978 | << (Offset << RegUnitBits | FirstRU) << ", " |
979 | << LaneMaskSeqs.get(Seq: RegUnitLaneMasks[i]) << ", " << Reg.Constant |
980 | << " },\n" ; |
981 | ++i; |
982 | } |
983 | OS << "};\n\n" ; // End of register descriptors... |
984 | |
985 | // Emit the table of register unit roots. Each regunit has one or two root |
986 | // registers. |
987 | OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n" ; |
988 | for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) { |
989 | ArrayRef<const CodeGenRegister *> Roots = RegBank.getRegUnit(RUID: i).getRoots(); |
990 | assert(!Roots.empty() && "All regunits must have a root register." ); |
991 | assert(Roots.size() <= 2 && "More than two roots not supported yet." ); |
992 | OS << " { " ; |
993 | ListSeparator LS; |
994 | for (const CodeGenRegister *R : Roots) |
995 | OS << LS << getQualifiedName(R: R->TheDef); |
996 | OS << " },\n" ; |
997 | } |
998 | OS << "};\n\n" ; |
999 | |
1000 | const auto &RegisterClasses = RegBank.getRegClasses(); |
1001 | |
1002 | // Loop over all of the register classes... emitting each one. |
1003 | OS << "namespace { // Register classes...\n" ; |
1004 | |
1005 | SequenceToOffsetTable<std::string> RegClassStrings; |
1006 | |
1007 | // Emit the register enum value arrays for each RegisterClass |
1008 | for (const auto &RC : RegisterClasses) { |
1009 | ArrayRef<Record *> Order = RC.getOrder(); |
1010 | |
1011 | // Give the register class a legal C name if it's anonymous. |
1012 | const std::string &Name = RC.getName(); |
1013 | |
1014 | RegClassStrings.add(Seq: Name); |
1015 | |
1016 | // Emit the register list now (unless it would be a zero-length array). |
1017 | if (!Order.empty()) { |
1018 | OS << " // " << Name << " Register Class...\n" |
1019 | << " const MCPhysReg " << Name << "[] = {\n " ; |
1020 | for (Record *Reg : Order) { |
1021 | OS << getQualifiedName(R: Reg) << ", " ; |
1022 | } |
1023 | OS << "\n };\n\n" ; |
1024 | |
1025 | OS << " // " << Name << " Bit set.\n" |
1026 | << " const uint8_t " << Name << "Bits[] = {\n " ; |
1027 | BitVectorEmitter BVE; |
1028 | for (Record *Reg : Order) { |
1029 | BVE.add(v: Target.getRegBank().getReg(Reg)->EnumValue); |
1030 | } |
1031 | BVE.print(OS); |
1032 | OS << "\n };\n\n" ; |
1033 | } |
1034 | } |
1035 | OS << "} // end anonymous namespace\n\n" ; |
1036 | |
1037 | RegClassStrings.layout(); |
1038 | RegClassStrings.emitStringLiteralDef( |
1039 | OS, Decl: Twine("extern const char " ) + TargetName + "RegClassStrings[]" ); |
1040 | |
1041 | OS << "extern const MCRegisterClass " << TargetName |
1042 | << "MCRegisterClasses[] = {\n" ; |
1043 | |
1044 | for (const auto &RC : RegisterClasses) { |
1045 | ArrayRef<Record *> Order = RC.getOrder(); |
1046 | std::string RCName = Order.empty() ? "nullptr" : RC.getName(); |
1047 | std::string RCBitsName = Order.empty() ? "nullptr" : RC.getName() + "Bits" ; |
1048 | std::string RCBitsSize = Order.empty() ? "0" : "sizeof(" + RCBitsName + ")" ; |
1049 | assert(isInt<8>(RC.CopyCost) && "Copy cost too large." ); |
1050 | uint32_t RegSize = 0; |
1051 | if (RC.RSI.isSimple()) |
1052 | RegSize = RC.RSI.getSimple().RegSize; |
1053 | OS << " { " << RCName << ", " << RCBitsName << ", " |
1054 | << RegClassStrings.get(Seq: RC.getName()) << ", " << RC.getOrder().size() |
1055 | << ", " << RCBitsSize << ", " << RC.getQualifiedIdName() << ", " |
1056 | << RegSize << ", " << RC.CopyCost << ", " |
1057 | << (RC.Allocatable ? "true" : "false" ) << ", " |
1058 | << (RC.getBaseClassOrder() ? "true" : "false" ) << " },\n" ; |
1059 | } |
1060 | |
1061 | OS << "};\n\n" ; |
1062 | |
1063 | EmitRegMappingTables(OS, Regs, isCtor: false); |
1064 | |
1065 | // Emit Reg encoding table |
1066 | OS << "extern const uint16_t " << TargetName; |
1067 | OS << "RegEncodingTable[] = {\n" ; |
1068 | // Add entry for NoRegister |
1069 | OS << " 0,\n" ; |
1070 | for (const auto &RE : Regs) { |
1071 | Record *Reg = RE.TheDef; |
1072 | BitsInit *BI = Reg->getValueAsBitsInit(FieldName: "HWEncoding" ); |
1073 | uint64_t Value = 0; |
1074 | for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { |
1075 | if (BitInit *B = dyn_cast<BitInit>(Val: BI->getBit(Bit: b))) |
1076 | Value |= (uint64_t)B->getValue() << b; |
1077 | } |
1078 | OS << " " << Value << ",\n" ; |
1079 | } |
1080 | OS << "};\n" ; // End of HW encoding table |
1081 | |
1082 | // MCRegisterInfo initialization routine. |
1083 | OS << "static inline void Init" << TargetName |
1084 | << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " |
1085 | << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) " |
1086 | "{\n" |
1087 | << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " |
1088 | << Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " |
1089 | << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " |
1090 | << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " |
1091 | << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, " |
1092 | << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " |
1093 | << (std::distance(first: SubRegIndices.begin(), last: SubRegIndices.end()) + 1) << ",\n" |
1094 | << TargetName << "RegEncodingTable);\n\n" ; |
1095 | |
1096 | EmitRegMapping(OS, Regs, isCtor: false); |
1097 | |
1098 | OS << "}\n\n" ; |
1099 | |
1100 | OS << "} // end namespace llvm\n\n" ; |
1101 | OS << "#endif // GET_REGINFO_MC_DESC\n\n" ; |
1102 | } |
1103 | |
1104 | void RegisterInfoEmitter::(raw_ostream &OS, |
1105 | CodeGenTarget &Target, |
1106 | CodeGenRegBank &RegBank) { |
1107 | emitSourceFileHeader(Desc: "Register Information Header Fragment" , OS); |
1108 | |
1109 | OS << "\n#ifdef GET_REGINFO_HEADER\n" ; |
1110 | OS << "#undef GET_REGINFO_HEADER\n\n" ; |
1111 | |
1112 | const std::string &TargetName = std::string(Target.getName()); |
1113 | std::string ClassName = TargetName + "GenRegisterInfo" ; |
1114 | |
1115 | OS << "#include \"llvm/CodeGen/TargetRegisterInfo.h\"\n\n" ; |
1116 | |
1117 | OS << "namespace llvm {\n\n" ; |
1118 | |
1119 | OS << "class " << TargetName << "FrameLowering;\n\n" ; |
1120 | |
1121 | OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" |
1122 | << " explicit " << ClassName |
1123 | << "(unsigned RA, unsigned D = 0, unsigned E = 0,\n" |
1124 | << " unsigned PC = 0, unsigned HwMode = 0);\n" ; |
1125 | if (!RegBank.getSubRegIndices().empty()) { |
1126 | OS << " unsigned composeSubRegIndicesImpl" |
1127 | << "(unsigned, unsigned) const override;\n" |
1128 | << " LaneBitmask composeSubRegIndexLaneMaskImpl" |
1129 | << "(unsigned, LaneBitmask) const override;\n" |
1130 | << " LaneBitmask reverseComposeSubRegIndexLaneMaskImpl" |
1131 | << "(unsigned, LaneBitmask) const override;\n" |
1132 | << " const TargetRegisterClass *getSubClassWithSubReg" |
1133 | << "(const TargetRegisterClass *, unsigned) const override;\n" |
1134 | << " const TargetRegisterClass *getSubRegisterClass" |
1135 | << "(const TargetRegisterClass *, unsigned) const override;\n" ; |
1136 | } |
1137 | OS << " const RegClassWeight &getRegClassWeight(" |
1138 | << "const TargetRegisterClass *RC) const override;\n" |
1139 | << " unsigned getRegUnitWeight(unsigned RegUnit) const override;\n" |
1140 | << " unsigned getNumRegPressureSets() const override;\n" |
1141 | << " const char *getRegPressureSetName(unsigned Idx) const override;\n" |
1142 | << " unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned " |
1143 | "Idx) const override;\n" |
1144 | << " const int *getRegClassPressureSets(" |
1145 | << "const TargetRegisterClass *RC) const override;\n" |
1146 | << " const int *getRegUnitPressureSets(" |
1147 | << "unsigned RegUnit) const override;\n" |
1148 | << " ArrayRef<const char *> getRegMaskNames() const override;\n" |
1149 | << " ArrayRef<const uint32_t *> getRegMasks() const override;\n" |
1150 | << " bool isGeneralPurposeRegister(const MachineFunction &, " |
1151 | << "MCRegister) const override;\n" |
1152 | << " bool isFixedRegister(const MachineFunction &, " |
1153 | << "MCRegister) const override;\n" |
1154 | << " bool isArgumentRegister(const MachineFunction &, " |
1155 | << "MCRegister) const override;\n" |
1156 | << " bool isConstantPhysReg(MCRegister PhysReg) const override final;\n" |
1157 | << " /// Devirtualized TargetFrameLowering.\n" |
1158 | << " static const " << TargetName << "FrameLowering *getFrameLowering(\n" |
1159 | << " const MachineFunction &MF);\n" ; |
1160 | |
1161 | const auto &RegisterClasses = RegBank.getRegClasses(); |
1162 | if (llvm::any_of(Range: RegisterClasses, |
1163 | P: [](const auto &RC) { return RC.getBaseClassOrder(); })) { |
1164 | OS << " const TargetRegisterClass *getPhysRegBaseClass(MCRegister Reg) " |
1165 | "const override;\n" ; |
1166 | } |
1167 | |
1168 | OS << "};\n\n" ; |
1169 | |
1170 | if (!RegisterClasses.empty()) { |
1171 | OS << "namespace " << RegisterClasses.front().Namespace |
1172 | << " { // Register classes\n" ; |
1173 | |
1174 | for (const auto &RC : RegisterClasses) { |
1175 | const std::string &Name = RC.getName(); |
1176 | |
1177 | // Output the extern for the instance. |
1178 | OS << " extern const TargetRegisterClass " << Name << "RegClass;\n" ; |
1179 | } |
1180 | OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n\n" ; |
1181 | } |
1182 | OS << "} // end namespace llvm\n\n" ; |
1183 | OS << "#endif // GET_REGINFO_HEADER\n\n" ; |
1184 | } |
1185 | |
1186 | // |
1187 | // runTargetDesc - Output the target register and register file descriptions. |
1188 | // |
1189 | void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, |
1190 | CodeGenRegBank &RegBank) { |
1191 | emitSourceFileHeader(Desc: "Target Register and Register Classes Information" , OS); |
1192 | |
1193 | OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n" ; |
1194 | OS << "#undef GET_REGINFO_TARGET_DESC\n\n" ; |
1195 | |
1196 | OS << "namespace llvm {\n\n" ; |
1197 | |
1198 | // Get access to MCRegisterClass data. |
1199 | OS << "extern const MCRegisterClass " << Target.getName() |
1200 | << "MCRegisterClasses[];\n" ; |
1201 | |
1202 | // Start out by emitting each of the register classes. |
1203 | const auto &RegisterClasses = RegBank.getRegClasses(); |
1204 | const auto &SubRegIndices = RegBank.getSubRegIndices(); |
1205 | |
1206 | // Collect all registers belonging to any allocatable class. |
1207 | std::set<Record *> AllocatableRegs; |
1208 | |
1209 | // Collect allocatable registers. |
1210 | for (const auto &RC : RegisterClasses) { |
1211 | ArrayRef<Record *> Order = RC.getOrder(); |
1212 | |
1213 | if (RC.Allocatable) |
1214 | AllocatableRegs.insert(first: Order.begin(), last: Order.end()); |
1215 | } |
1216 | |
1217 | const CodeGenHwModes &CGH = Target.getHwModes(); |
1218 | unsigned NumModes = CGH.getNumModeIds(); |
1219 | |
1220 | // Build a shared array of value types. |
1221 | SequenceToOffsetTable<std::vector<MVT::SimpleValueType>> VTSeqs; |
1222 | for (unsigned M = 0; M < NumModes; ++M) { |
1223 | for (const auto &RC : RegisterClasses) { |
1224 | std::vector<MVT::SimpleValueType> S; |
1225 | for (const ValueTypeByHwMode &VVT : RC.VTs) |
1226 | if (VVT.hasDefault() || VVT.hasMode(M)) |
1227 | S.push_back(x: VVT.get(Mode: M).SimpleTy); |
1228 | VTSeqs.add(Seq: S); |
1229 | } |
1230 | } |
1231 | VTSeqs.layout(); |
1232 | OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n" ; |
1233 | VTSeqs.emit(OS, Print: printSimpleValueType, Term: "MVT::Other" ); |
1234 | OS << "};\n" ; |
1235 | |
1236 | // Emit SubRegIndex names, skipping 0. |
1237 | OS << "\nstatic const char *SubRegIndexNameTable[] = { \"" ; |
1238 | |
1239 | for (const auto &Idx : SubRegIndices) { |
1240 | OS << Idx.getName(); |
1241 | OS << "\", \"" ; |
1242 | } |
1243 | OS << "\" };\n\n" ; |
1244 | |
1245 | // Emit the table of sub-register index sizes. |
1246 | OS << "static const TargetRegisterInfo::SubRegCoveredBits " |
1247 | "SubRegIdxRangeTable[] = {\n" ; |
1248 | for (unsigned M = 0; M < NumModes; ++M) { |
1249 | OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n" ; |
1250 | for (const auto &Idx : SubRegIndices) { |
1251 | const SubRegRange &Range = Idx.Range.get(Mode: M); |
1252 | OS << " { " << Range.Offset << ", " << Range.Size << " },\t// " |
1253 | << Idx.getName() << "\n" ; |
1254 | } |
1255 | } |
1256 | OS << "};\n\n" ; |
1257 | |
1258 | // Emit SubRegIndex lane masks, including 0. |
1259 | OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n " |
1260 | "LaneBitmask::getAll(),\n" ; |
1261 | for (const auto &Idx : SubRegIndices) { |
1262 | printMask(OS&: OS << " " , Val: Idx.LaneMask); |
1263 | OS << ", // " << Idx.getName() << '\n'; |
1264 | } |
1265 | OS << " };\n\n" ; |
1266 | |
1267 | OS << "\n" ; |
1268 | |
1269 | // Now that all of the structs have been emitted, emit the instances. |
1270 | if (!RegisterClasses.empty()) { |
1271 | OS << "\nstatic const TargetRegisterInfo::RegClassInfo RegClassInfos[]" |
1272 | << " = {\n" ; |
1273 | for (unsigned M = 0; M < NumModes; ++M) { |
1274 | unsigned EV = 0; |
1275 | OS << " // Mode = " << M << " (" ; |
1276 | if (M == 0) |
1277 | OS << "Default" ; |
1278 | else |
1279 | OS << CGH.getMode(Id: M).Name; |
1280 | OS << ")\n" ; |
1281 | for (const auto &RC : RegisterClasses) { |
1282 | assert(RC.EnumValue == EV && "Unexpected order of register classes" ); |
1283 | ++EV; |
1284 | (void)EV; |
1285 | const RegSizeInfo &RI = RC.RSI.get(Mode: M); |
1286 | OS << " { " << RI.RegSize << ", " << RI.SpillSize << ", " |
1287 | << RI.SpillAlignment; |
1288 | std::vector<MVT::SimpleValueType> VTs; |
1289 | for (const ValueTypeByHwMode &VVT : RC.VTs) |
1290 | if (VVT.hasDefault() || VVT.hasMode(M)) |
1291 | VTs.push_back(x: VVT.get(Mode: M).SimpleTy); |
1292 | OS << ", /*VTLists+*/" << VTSeqs.get(Seq: VTs) << " }, // " |
1293 | << RC.getName() << '\n'; |
1294 | } |
1295 | } |
1296 | OS << "};\n" ; |
1297 | |
1298 | OS << "\nstatic const TargetRegisterClass *const " |
1299 | << "NullRegClasses[] = { nullptr };\n\n" ; |
1300 | |
1301 | // Emit register class bit mask tables. The first bit mask emitted for a |
1302 | // register class, RC, is the set of sub-classes, including RC itself. |
1303 | // |
1304 | // If RC has super-registers, also create a list of subreg indices and bit |
1305 | // masks, (Idx, Mask). The bit mask has a bit for every superreg regclass, |
1306 | // SuperRC, that satisfies: |
1307 | // |
1308 | // For all SuperReg in SuperRC: SuperReg:Idx in RC |
1309 | // |
1310 | // The 0-terminated list of subreg indices starts at: |
1311 | // |
1312 | // RC->getSuperRegIndices() = SuperRegIdxSeqs + ... |
1313 | // |
1314 | // The corresponding bitmasks follow the sub-class mask in memory. Each |
1315 | // mask has RCMaskWords uint32_t entries. |
1316 | // |
1317 | // Every bit mask present in the list has at least one bit set. |
1318 | |
1319 | // Compress the sub-reg index lists. |
1320 | typedef std::vector<const CodeGenSubRegIndex *> IdxList; |
1321 | SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size()); |
1322 | SequenceToOffsetTable<IdxList, deref<std::less<>>> SuperRegIdxSeqs; |
1323 | BitVector MaskBV(RegisterClasses.size()); |
1324 | |
1325 | for (const auto &RC : RegisterClasses) { |
1326 | OS << "static const uint32_t " << RC.getName() |
1327 | << "SubClassMask[] = {\n " ; |
1328 | printBitVectorAsHex(OS, Bits: RC.getSubClasses(), Width: 32); |
1329 | |
1330 | // Emit super-reg class masks for any relevant SubRegIndices that can |
1331 | // project into RC. |
1332 | IdxList &SRIList = SuperRegIdxLists[RC.EnumValue]; |
1333 | for (auto &Idx : SubRegIndices) { |
1334 | MaskBV.reset(); |
1335 | RC.getSuperRegClasses(SubIdx: &Idx, Out&: MaskBV); |
1336 | if (MaskBV.none()) |
1337 | continue; |
1338 | SRIList.push_back(x: &Idx); |
1339 | OS << "\n " ; |
1340 | printBitVectorAsHex(OS, Bits: MaskBV, Width: 32); |
1341 | OS << "// " << Idx.getName(); |
1342 | } |
1343 | SuperRegIdxSeqs.add(Seq: SRIList); |
1344 | OS << "\n};\n\n" ; |
1345 | } |
1346 | |
1347 | OS << "static const uint16_t SuperRegIdxSeqs[] = {\n" ; |
1348 | SuperRegIdxSeqs.layout(); |
1349 | SuperRegIdxSeqs.emit(OS, Print: printSubRegIndex); |
1350 | OS << "};\n\n" ; |
1351 | |
1352 | // Emit NULL terminated super-class lists. |
1353 | for (const auto &RC : RegisterClasses) { |
1354 | ArrayRef<CodeGenRegisterClass *> Supers = RC.getSuperClasses(); |
1355 | |
1356 | // Skip classes without supers. We can reuse NullRegClasses. |
1357 | if (Supers.empty()) |
1358 | continue; |
1359 | |
1360 | OS << "static const TargetRegisterClass *const " << RC.getName() |
1361 | << "Superclasses[] = {\n" ; |
1362 | for (const auto *Super : Supers) |
1363 | OS << " &" << Super->getQualifiedName() << "RegClass,\n" ; |
1364 | OS << " nullptr\n};\n\n" ; |
1365 | } |
1366 | |
1367 | // Emit methods. |
1368 | for (const auto &RC : RegisterClasses) { |
1369 | if (!RC.AltOrderSelect.empty()) { |
1370 | OS << "\nstatic inline unsigned " << RC.getName() |
1371 | << "AltOrderSelect(const MachineFunction &MF) {" << RC.AltOrderSelect |
1372 | << "}\n\n" |
1373 | << "static ArrayRef<MCPhysReg> " << RC.getName() |
1374 | << "GetRawAllocationOrder(const MachineFunction &MF) {\n" ; |
1375 | for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) { |
1376 | ArrayRef<Record *> Elems = RC.getOrder(No: oi); |
1377 | if (!Elems.empty()) { |
1378 | OS << " static const MCPhysReg AltOrder" << oi << "[] = {" ; |
1379 | for (unsigned elem = 0; elem != Elems.size(); ++elem) |
1380 | OS << (elem ? ", " : " " ) << getQualifiedName(R: Elems[elem]); |
1381 | OS << " };\n" ; |
1382 | } |
1383 | } |
1384 | OS << " const MCRegisterClass &MCR = " << Target.getName() |
1385 | << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" |
1386 | << " const ArrayRef<MCPhysReg> Order[] = {\n" |
1387 | << " ArrayRef(MCR.begin(), MCR.getNumRegs()" ; |
1388 | for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) |
1389 | if (RC.getOrder(No: oi).empty()) |
1390 | OS << "),\n ArrayRef<MCPhysReg>(" ; |
1391 | else |
1392 | OS << "),\n ArrayRef(AltOrder" << oi; |
1393 | OS << ")\n };\n const unsigned Select = " << RC.getName() |
1394 | << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() |
1395 | << ");\n return Order[Select];\n}\n" ; |
1396 | } |
1397 | } |
1398 | |
1399 | // Now emit the actual value-initialized register class instances. |
1400 | OS << "\nnamespace " << RegisterClasses.front().Namespace |
1401 | << " { // Register class instances\n" ; |
1402 | |
1403 | for (const auto &RC : RegisterClasses) { |
1404 | OS << " extern const TargetRegisterClass " << RC.getName() |
1405 | << "RegClass = {\n " << '&' << Target.getName() |
1406 | << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n " |
1407 | << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + " |
1408 | << SuperRegIdxSeqs.get(Seq: SuperRegIdxLists[RC.EnumValue]) << ",\n " ; |
1409 | printMask(OS, Val: RC.LaneMask); |
1410 | OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n " |
1411 | << (RC.GlobalPriority ? "true" : "false" ) << ",\n " |
1412 | << format(Fmt: "0x%02x" , Vals: RC.TSFlags) << ", /* TSFlags */\n " |
1413 | << (RC.HasDisjunctSubRegs ? "true" : "false" ) |
1414 | << ", /* HasDisjunctSubRegs */\n " |
1415 | << (RC.CoveredBySubRegs ? "true" : "false" ) |
1416 | << ", /* CoveredBySubRegs */\n " ; |
1417 | if (RC.getSuperClasses().empty()) |
1418 | OS << "NullRegClasses,\n " ; |
1419 | else |
1420 | OS << RC.getName() << "Superclasses,\n " ; |
1421 | if (RC.AltOrderSelect.empty()) |
1422 | OS << "nullptr\n" ; |
1423 | else |
1424 | OS << RC.getName() << "GetRawAllocationOrder\n" ; |
1425 | OS << " };\n\n" ; |
1426 | } |
1427 | |
1428 | OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n" ; |
1429 | } |
1430 | |
1431 | OS << "\nnamespace {\n" ; |
1432 | OS << " const TargetRegisterClass *const RegisterClasses[] = {\n" ; |
1433 | for (const auto &RC : RegisterClasses) |
1434 | OS << " &" << RC.getQualifiedName() << "RegClass,\n" ; |
1435 | OS << " };\n" ; |
1436 | OS << "} // end anonymous namespace\n" ; |
1437 | |
1438 | // Emit extra information about registers. |
1439 | const std::string &TargetName = std::string(Target.getName()); |
1440 | const auto &Regs = RegBank.getRegisters(); |
1441 | unsigned NumRegCosts = 1; |
1442 | for (const auto &Reg : Regs) |
1443 | NumRegCosts = std::max(a: (size_t)NumRegCosts, b: Reg.CostPerUse.size()); |
1444 | |
1445 | std::vector<unsigned> AllRegCostPerUse; |
1446 | llvm::BitVector InAllocClass(Regs.size() + 1, false); |
1447 | AllRegCostPerUse.insert(position: AllRegCostPerUse.end(), n: NumRegCosts, x: 0); |
1448 | |
1449 | // Populate the vector RegCosts with the CostPerUse list of the registers |
1450 | // in the order they are read. Have at most NumRegCosts entries for |
1451 | // each register. Fill with zero for values which are not explicitly given. |
1452 | for (const auto &Reg : Regs) { |
1453 | auto Costs = Reg.CostPerUse; |
1454 | AllRegCostPerUse.insert(position: AllRegCostPerUse.end(), first: Costs.begin(), last: Costs.end()); |
1455 | if (NumRegCosts > Costs.size()) |
1456 | AllRegCostPerUse.insert(position: AllRegCostPerUse.end(), |
1457 | n: NumRegCosts - Costs.size(), x: 0); |
1458 | |
1459 | if (AllocatableRegs.count(x: Reg.TheDef)) |
1460 | InAllocClass.set(Reg.EnumValue); |
1461 | } |
1462 | |
1463 | // Emit the cost values as a 1D-array after grouping them by their indices, |
1464 | // i.e. the costs for all registers corresponds to index 0, 1, 2, etc. |
1465 | // Size of the emitted array should be NumRegCosts * (Regs.size() + 1). |
1466 | OS << "\nstatic const uint8_t " |
1467 | << "CostPerUseTable[] = { \n" ; |
1468 | for (unsigned int I = 0; I < NumRegCosts; ++I) { |
1469 | for (unsigned J = I, E = AllRegCostPerUse.size(); J < E; J += NumRegCosts) |
1470 | OS << AllRegCostPerUse[J] << ", " ; |
1471 | } |
1472 | OS << "};\n\n" ; |
1473 | |
1474 | OS << "\nstatic const bool " |
1475 | << "InAllocatableClassTable[] = { \n" ; |
1476 | for (unsigned I = 0, E = InAllocClass.size(); I < E; ++I) { |
1477 | OS << (InAllocClass[I] ? "true" : "false" ) << ", " ; |
1478 | } |
1479 | OS << "};\n\n" ; |
1480 | |
1481 | OS << "\nstatic const TargetRegisterInfoDesc " << TargetName |
1482 | << "RegInfoDesc = { // Extra Descriptors\n" ; |
1483 | OS << "CostPerUseTable, " << NumRegCosts << ", " |
1484 | << "InAllocatableClassTable" ; |
1485 | OS << "};\n\n" ; // End of register descriptors... |
1486 | |
1487 | std::string ClassName = Target.getName().str() + "GenRegisterInfo" ; |
1488 | |
1489 | auto SubRegIndicesSize = |
1490 | std::distance(first: SubRegIndices.begin(), last: SubRegIndices.end()); |
1491 | |
1492 | if (!SubRegIndices.empty()) { |
1493 | emitComposeSubRegIndices(OS, RegBank, ClName: ClassName); |
1494 | emitComposeSubRegIndexLaneMask(OS, RegBank, ClName: ClassName); |
1495 | } |
1496 | |
1497 | if (!SubRegIndices.empty()) { |
1498 | // Emit getSubClassWithSubReg. |
1499 | OS << "const TargetRegisterClass *" << ClassName |
1500 | << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)" |
1501 | << " const {\n" ; |
1502 | // Use the smallest type that can hold a regclass ID with room for a |
1503 | // sentinel. |
1504 | if (RegisterClasses.size() <= UINT8_MAX) |
1505 | OS << " static const uint8_t Table[" ; |
1506 | else if (RegisterClasses.size() <= UINT16_MAX) |
1507 | OS << " static const uint16_t Table[" ; |
1508 | else |
1509 | PrintFatalError(Msg: "Too many register classes." ); |
1510 | OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n" ; |
1511 | for (const auto &RC : RegisterClasses) { |
1512 | OS << " {\t// " << RC.getName() << "\n" ; |
1513 | for (auto &Idx : SubRegIndices) { |
1514 | if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(SubIdx: &Idx)) |
1515 | OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName() |
1516 | << " -> " << SRC->getName() << "\n" ; |
1517 | else |
1518 | OS << " 0,\t// " << Idx.getName() << "\n" ; |
1519 | } |
1520 | OS << " },\n" ; |
1521 | } |
1522 | OS << " };\n assert(RC && \"Missing regclass\");\n" |
1523 | << " if (!Idx) return RC;\n --Idx;\n" |
1524 | << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" |
1525 | << " unsigned TV = Table[RC->getID()][Idx];\n" |
1526 | << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n" ; |
1527 | |
1528 | // Emit getSubRegisterClass |
1529 | OS << "const TargetRegisterClass *" << ClassName |
1530 | << "::getSubRegisterClass(const TargetRegisterClass *RC, unsigned Idx)" |
1531 | << " const {\n" ; |
1532 | |
1533 | // Use the smallest type that can hold a regclass ID with room for a |
1534 | // sentinel. |
1535 | if (RegisterClasses.size() <= UINT8_MAX) |
1536 | OS << " static const uint8_t Table[" ; |
1537 | else if (RegisterClasses.size() <= UINT16_MAX) |
1538 | OS << " static const uint16_t Table[" ; |
1539 | else |
1540 | PrintFatalError(Msg: "Too many register classes." ); |
1541 | |
1542 | OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n" ; |
1543 | |
1544 | for (const auto &RC : RegisterClasses) { |
1545 | OS << " {\t// " << RC.getName() << '\n'; |
1546 | for (auto &Idx : SubRegIndices) { |
1547 | std::optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>> |
1548 | MatchingSubClass = RC.getMatchingSubClassWithSubRegs(RegBank, SubIdx: &Idx); |
1549 | |
1550 | unsigned EnumValue = 0; |
1551 | if (MatchingSubClass) { |
1552 | CodeGenRegisterClass *SubRegClass = MatchingSubClass->second; |
1553 | EnumValue = SubRegClass->EnumValue + 1; |
1554 | } |
1555 | |
1556 | OS << " " << EnumValue << ",\t// " << RC.getName() << ':' |
1557 | << Idx.getName(); |
1558 | |
1559 | if (MatchingSubClass) { |
1560 | CodeGenRegisterClass *SubRegClass = MatchingSubClass->second; |
1561 | OS << " -> " << SubRegClass->getName(); |
1562 | } |
1563 | |
1564 | OS << '\n'; |
1565 | } |
1566 | |
1567 | OS << " },\n" ; |
1568 | } |
1569 | OS << " };\n assert(RC && \"Missing regclass\");\n" |
1570 | << " if (!Idx) return RC;\n --Idx;\n" |
1571 | << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" |
1572 | << " unsigned TV = Table[RC->getID()][Idx];\n" |
1573 | << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n" ; |
1574 | } |
1575 | |
1576 | EmitRegUnitPressure(OS, RegBank, ClassName); |
1577 | |
1578 | // Emit register base class mapper |
1579 | if (!RegisterClasses.empty()) { |
1580 | // Collect base classes |
1581 | SmallVector<const CodeGenRegisterClass *> BaseClasses; |
1582 | for (const auto &RC : RegisterClasses) { |
1583 | if (RC.getBaseClassOrder()) |
1584 | BaseClasses.push_back(Elt: &RC); |
1585 | } |
1586 | if (!BaseClasses.empty()) { |
1587 | assert(BaseClasses.size() < UINT16_MAX && |
1588 | "Too many base register classes" ); |
1589 | |
1590 | // Apply order |
1591 | struct BaseClassOrdering { |
1592 | bool operator()(const CodeGenRegisterClass *LHS, |
1593 | const CodeGenRegisterClass *RHS) const { |
1594 | return std::pair(*LHS->getBaseClassOrder(), LHS->EnumValue) < |
1595 | std::pair(*RHS->getBaseClassOrder(), RHS->EnumValue); |
1596 | } |
1597 | }; |
1598 | llvm::stable_sort(Range&: BaseClasses, C: BaseClassOrdering()); |
1599 | |
1600 | OS << "\n// Register to base register class mapping\n\n" ; |
1601 | OS << "\n" ; |
1602 | OS << "const TargetRegisterClass *" << ClassName |
1603 | << "::getPhysRegBaseClass(MCRegister Reg)" |
1604 | << " const {\n" ; |
1605 | OS << " static const uint16_t InvalidRegClassID = UINT16_MAX;\n\n" ; |
1606 | OS << " static const uint16_t Mapping[" << Regs.size() + 1 << "] = {\n" ; |
1607 | OS << " InvalidRegClassID, // NoRegister\n" ; |
1608 | for (const CodeGenRegister &Reg : Regs) { |
1609 | const CodeGenRegisterClass *BaseRC = nullptr; |
1610 | for (const CodeGenRegisterClass *RC : BaseClasses) { |
1611 | if (is_contained(Range: RC->getMembers(), Element: &Reg)) { |
1612 | BaseRC = RC; |
1613 | break; |
1614 | } |
1615 | } |
1616 | |
1617 | OS << " " |
1618 | << (BaseRC ? BaseRC->getQualifiedIdName() : "InvalidRegClassID" ) |
1619 | << ", // " << Reg.getName() << "\n" ; |
1620 | } |
1621 | OS << " };\n\n" |
1622 | " assert(Reg < ArrayRef(Mapping).size());\n" |
1623 | " unsigned RCID = Mapping[Reg];\n" |
1624 | " if (RCID == InvalidRegClassID)\n" |
1625 | " return nullptr;\n" |
1626 | " return RegisterClasses[RCID];\n" |
1627 | "}\n" ; |
1628 | } |
1629 | } |
1630 | |
1631 | // Emit the constructor of the class... |
1632 | OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n" ; |
1633 | OS << "extern const int16_t " << TargetName << "RegDiffLists[];\n" ; |
1634 | OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[];\n" ; |
1635 | OS << "extern const char " << TargetName << "RegStrings[];\n" ; |
1636 | OS << "extern const char " << TargetName << "RegClassStrings[];\n" ; |
1637 | OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n" ; |
1638 | OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n" ; |
1639 | OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n" ; |
1640 | |
1641 | EmitRegMappingTables(OS, Regs, isCtor: true); |
1642 | |
1643 | OS << ClassName << "::\n" |
1644 | << ClassName |
1645 | << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour,\n" |
1646 | " unsigned PC, unsigned HwMode)\n" |
1647 | << " : TargetRegisterInfo(&" << TargetName << "RegInfoDesc" |
1648 | << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() << ",\n" |
1649 | << " SubRegIndexNameTable, SubRegIdxRangeTable, " |
1650 | "SubRegIndexLaneMaskTable,\n" |
1651 | << " " ; |
1652 | printMask(OS, Val: RegBank.CoveringLanes); |
1653 | OS << ", RegClassInfos, VTLists, HwMode) {\n" |
1654 | << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1 |
1655 | << ", RA, PC,\n " << TargetName |
1656 | << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" |
1657 | << " " << TargetName << "RegUnitRoots,\n" |
1658 | << " " << RegBank.getNumNativeRegUnits() << ",\n" |
1659 | << " " << TargetName << "RegDiffLists,\n" |
1660 | << " " << TargetName << "LaneMaskLists,\n" |
1661 | << " " << TargetName << "RegStrings,\n" |
1662 | << " " << TargetName << "RegClassStrings,\n" |
1663 | << " " << TargetName << "SubRegIdxLists,\n" |
1664 | << " " << SubRegIndicesSize + 1 << ",\n" |
1665 | << " " << TargetName << "RegEncodingTable);\n\n" ; |
1666 | |
1667 | EmitRegMapping(OS, Regs, isCtor: true); |
1668 | |
1669 | OS << "}\n\n" ; |
1670 | |
1671 | // Emit CalleeSavedRegs information. |
1672 | std::vector<Record *> CSRSets = |
1673 | Records.getAllDerivedDefinitions(ClassName: "CalleeSavedRegs" ); |
1674 | for (unsigned i = 0, e = CSRSets.size(); i != e; ++i) { |
1675 | Record *CSRSet = CSRSets[i]; |
1676 | const SetTheory::RecVec *Regs = RegBank.getSets().expand(Set: CSRSet); |
1677 | assert(Regs && "Cannot expand CalleeSavedRegs instance" ); |
1678 | |
1679 | // Emit the *_SaveList list of callee-saved registers. |
1680 | OS << "static const MCPhysReg " << CSRSet->getName() << "_SaveList[] = { " ; |
1681 | for (unsigned r = 0, re = Regs->size(); r != re; ++r) |
1682 | OS << getQualifiedName(R: (*Regs)[r]) << ", " ; |
1683 | OS << "0 };\n" ; |
1684 | |
1685 | // Emit the *_RegMask bit mask of call-preserved registers. |
1686 | BitVector Covered = RegBank.computeCoveredRegisters(Regs: *Regs); |
1687 | |
1688 | // Check for an optional OtherPreserved set. |
1689 | // Add those registers to RegMask, but not to SaveList. |
1690 | if (DagInit *OPDag = |
1691 | dyn_cast<DagInit>(Val: CSRSet->getValueInit(FieldName: "OtherPreserved" ))) { |
1692 | SetTheory::RecSet OPSet; |
1693 | RegBank.getSets().evaluate(Expr: OPDag, Elts&: OPSet, Loc: CSRSet->getLoc()); |
1694 | Covered |= RegBank.computeCoveredRegisters( |
1695 | Regs: ArrayRef<Record *>(OPSet.begin(), OPSet.end())); |
1696 | } |
1697 | |
1698 | // Add all constant physical registers to the preserved mask: |
1699 | SetTheory::RecSet ConstantSet; |
1700 | for (auto &Reg : RegBank.getRegisters()) { |
1701 | if (Reg.Constant) |
1702 | ConstantSet.insert(X: Reg.TheDef); |
1703 | } |
1704 | Covered |= RegBank.computeCoveredRegisters( |
1705 | Regs: ArrayRef<Record *>(ConstantSet.begin(), ConstantSet.end())); |
1706 | |
1707 | OS << "static const uint32_t " << CSRSet->getName() << "_RegMask[] = { " ; |
1708 | printBitVectorAsHex(OS, Bits: Covered, Width: 32); |
1709 | OS << "};\n" ; |
1710 | } |
1711 | OS << "\n\n" ; |
1712 | |
1713 | OS << "ArrayRef<const uint32_t *> " << ClassName |
1714 | << "::getRegMasks() const {\n" ; |
1715 | if (!CSRSets.empty()) { |
1716 | OS << " static const uint32_t *const Masks[] = {\n" ; |
1717 | for (Record *CSRSet : CSRSets) |
1718 | OS << " " << CSRSet->getName() << "_RegMask,\n" ; |
1719 | OS << " };\n" ; |
1720 | OS << " return ArrayRef(Masks);\n" ; |
1721 | } else { |
1722 | OS << " return std::nullopt;\n" ; |
1723 | } |
1724 | OS << "}\n\n" ; |
1725 | |
1726 | const std::list<CodeGenRegisterCategory> &RegCategories = |
1727 | RegBank.getRegCategories(); |
1728 | OS << "bool " << ClassName << "::\n" |
1729 | << "isGeneralPurposeRegister(const MachineFunction &MF, " |
1730 | << "MCRegister PhysReg) const {\n" |
1731 | << " return\n" ; |
1732 | for (const CodeGenRegisterCategory &Category : RegCategories) |
1733 | if (Category.getName() == "GeneralPurposeRegisters" ) { |
1734 | for (const CodeGenRegisterClass *RC : Category.getClasses()) |
1735 | OS << " " << RC->getQualifiedName() |
1736 | << "RegClass.contains(PhysReg) ||\n" ; |
1737 | break; |
1738 | } |
1739 | OS << " false;\n" ; |
1740 | OS << "}\n\n" ; |
1741 | |
1742 | OS << "bool " << ClassName << "::\n" |
1743 | << "isFixedRegister(const MachineFunction &MF, " |
1744 | << "MCRegister PhysReg) const {\n" |
1745 | << " return\n" ; |
1746 | for (const CodeGenRegisterCategory &Category : RegCategories) |
1747 | if (Category.getName() == "FixedRegisters" ) { |
1748 | for (const CodeGenRegisterClass *RC : Category.getClasses()) |
1749 | OS << " " << RC->getQualifiedName() |
1750 | << "RegClass.contains(PhysReg) ||\n" ; |
1751 | break; |
1752 | } |
1753 | OS << " false;\n" ; |
1754 | OS << "}\n\n" ; |
1755 | |
1756 | OS << "bool " << ClassName << "::\n" |
1757 | << "isArgumentRegister(const MachineFunction &MF, " |
1758 | << "MCRegister PhysReg) const {\n" |
1759 | << " return\n" ; |
1760 | for (const CodeGenRegisterCategory &Category : RegCategories) |
1761 | if (Category.getName() == "ArgumentRegisters" ) { |
1762 | for (const CodeGenRegisterClass *RC : Category.getClasses()) |
1763 | OS << " " << RC->getQualifiedName() |
1764 | << "RegClass.contains(PhysReg) ||\n" ; |
1765 | break; |
1766 | } |
1767 | OS << " false;\n" ; |
1768 | OS << "}\n\n" ; |
1769 | |
1770 | OS << "bool " << ClassName << "::\n" |
1771 | << "isConstantPhysReg(MCRegister PhysReg) const {\n" |
1772 | << " return\n" ; |
1773 | for (const auto &Reg : Regs) |
1774 | if (Reg.Constant) |
1775 | OS << " PhysReg == " << getQualifiedName(R: Reg.TheDef) << " ||\n" ; |
1776 | OS << " false;\n" ; |
1777 | OS << "}\n\n" ; |
1778 | |
1779 | OS << "ArrayRef<const char *> " << ClassName |
1780 | << "::getRegMaskNames() const {\n" ; |
1781 | if (!CSRSets.empty()) { |
1782 | OS << " static const char *Names[] = {\n" ; |
1783 | for (Record *CSRSet : CSRSets) |
1784 | OS << " " << '"' << CSRSet->getName() << '"' << ",\n" ; |
1785 | OS << " };\n" ; |
1786 | OS << " return ArrayRef(Names);\n" ; |
1787 | } else { |
1788 | OS << " return std::nullopt;\n" ; |
1789 | } |
1790 | OS << "}\n\n" ; |
1791 | |
1792 | OS << "const " << TargetName << "FrameLowering *\n" |
1793 | << TargetName |
1794 | << "GenRegisterInfo::getFrameLowering(const MachineFunction &MF) {\n" |
1795 | << " return static_cast<const " << TargetName << "FrameLowering *>(\n" |
1796 | << " MF.getSubtarget().getFrameLowering());\n" |
1797 | << "}\n\n" ; |
1798 | |
1799 | OS << "} // end namespace llvm\n\n" ; |
1800 | OS << "#endif // GET_REGINFO_TARGET_DESC\n\n" ; |
1801 | } |
1802 | |
1803 | void RegisterInfoEmitter::run(raw_ostream &OS) { |
1804 | CodeGenRegBank &RegBank = Target.getRegBank(); |
1805 | Records.startTimer(Name: "Print enums" ); |
1806 | runEnums(OS, Target, Bank&: RegBank); |
1807 | |
1808 | Records.startTimer(Name: "Print MC registers" ); |
1809 | runMCDesc(OS, Target, RegBank); |
1810 | |
1811 | Records.startTimer(Name: "Print header fragment" ); |
1812 | runTargetHeader(OS, Target, RegBank); |
1813 | |
1814 | Records.startTimer(Name: "Print target registers" ); |
1815 | runTargetDesc(OS, Target, RegBank); |
1816 | |
1817 | if (RegisterInfoDebug) |
1818 | debugDump(OS&: errs()); |
1819 | } |
1820 | |
1821 | void RegisterInfoEmitter::debugDump(raw_ostream &OS) { |
1822 | CodeGenRegBank &RegBank = Target.getRegBank(); |
1823 | const CodeGenHwModes &CGH = Target.getHwModes(); |
1824 | unsigned NumModes = CGH.getNumModeIds(); |
1825 | auto getModeName = [CGH](unsigned M) -> StringRef { |
1826 | if (M == 0) |
1827 | return "Default" ; |
1828 | return CGH.getMode(Id: M).Name; |
1829 | }; |
1830 | |
1831 | for (const CodeGenRegisterClass &RC : RegBank.getRegClasses()) { |
1832 | OS << "RegisterClass " << RC.getName() << ":\n" ; |
1833 | OS << "\tSpillSize: {" ; |
1834 | for (unsigned M = 0; M != NumModes; ++M) |
1835 | OS << ' ' << getModeName(M) << ':' << RC.RSI.get(Mode: M).SpillSize; |
1836 | OS << " }\n\tSpillAlignment: {" ; |
1837 | for (unsigned M = 0; M != NumModes; ++M) |
1838 | OS << ' ' << getModeName(M) << ':' << RC.RSI.get(Mode: M).SpillAlignment; |
1839 | OS << " }\n\tNumRegs: " << RC.getMembers().size() << '\n'; |
1840 | OS << "\tLaneMask: " << PrintLaneMask(LaneMask: RC.LaneMask) << '\n'; |
1841 | OS << "\tHasDisjunctSubRegs: " << RC.HasDisjunctSubRegs << '\n'; |
1842 | OS << "\tCoveredBySubRegs: " << RC.CoveredBySubRegs << '\n'; |
1843 | OS << "\tAllocatable: " << RC.Allocatable << '\n'; |
1844 | OS << "\tAllocationPriority: " << unsigned(RC.AllocationPriority) << '\n'; |
1845 | OS << "\tBaseClassOrder: " << RC.getBaseClassOrder() << '\n'; |
1846 | OS << "\tRegs:" ; |
1847 | for (const CodeGenRegister *R : RC.getMembers()) { |
1848 | OS << " " << R->getName(); |
1849 | } |
1850 | OS << '\n'; |
1851 | OS << "\tSubClasses:" ; |
1852 | const BitVector &SubClasses = RC.getSubClasses(); |
1853 | for (const CodeGenRegisterClass &SRC : RegBank.getRegClasses()) { |
1854 | if (!SubClasses.test(Idx: SRC.EnumValue)) |
1855 | continue; |
1856 | OS << " " << SRC.getName(); |
1857 | } |
1858 | OS << '\n'; |
1859 | OS << "\tSuperClasses:" ; |
1860 | for (const CodeGenRegisterClass *SRC : RC.getSuperClasses()) { |
1861 | OS << " " << SRC->getName(); |
1862 | } |
1863 | OS << '\n'; |
1864 | } |
1865 | |
1866 | for (const CodeGenSubRegIndex &SRI : RegBank.getSubRegIndices()) { |
1867 | OS << "SubRegIndex " << SRI.getName() << ":\n" ; |
1868 | OS << "\tLaneMask: " << PrintLaneMask(LaneMask: SRI.LaneMask) << '\n'; |
1869 | OS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n'; |
1870 | OS << "\tOffset: {" ; |
1871 | for (unsigned M = 0; M != NumModes; ++M) |
1872 | OS << ' ' << getModeName(M) << ':' << SRI.Range.get(Mode: M).Offset; |
1873 | OS << " }\n\tSize: {" ; |
1874 | for (unsigned M = 0; M != NumModes; ++M) |
1875 | OS << ' ' << getModeName(M) << ':' << SRI.Range.get(Mode: M).Size; |
1876 | OS << " }\n" ; |
1877 | } |
1878 | |
1879 | for (const CodeGenRegister &R : RegBank.getRegisters()) { |
1880 | OS << "Register " << R.getName() << ":\n" ; |
1881 | OS << "\tCostPerUse: " ; |
1882 | for (const auto &Cost : R.CostPerUse) |
1883 | OS << Cost << " " ; |
1884 | OS << '\n'; |
1885 | OS << "\tCoveredBySubregs: " << R.CoveredBySubRegs << '\n'; |
1886 | OS << "\tHasDisjunctSubRegs: " << R.HasDisjunctSubRegs << '\n'; |
1887 | for (std::pair<CodeGenSubRegIndex *, CodeGenRegister *> P : |
1888 | R.getSubRegs()) { |
1889 | OS << "\tSubReg " << P.first->getName() << " = " << P.second->getName() |
1890 | << '\n'; |
1891 | } |
1892 | } |
1893 | } |
1894 | |
1895 | static TableGen::Emitter::OptClass<RegisterInfoEmitter> |
1896 | X("gen-register-info" , "Generate registers and register classes info" ); |
1897 | |