xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/RegisterBankEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- RegisterBankEmitter.cpp - Generate a Register Bank 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 bank for a code generator.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "Common/CodeGenRegisters.h"
15 #include "Common/CodeGenTarget.h"
16 #include "Common/InfoByHwMode.h"
17 #include "llvm/ADT/BitVector.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/TableGen/Error.h"
20 #include "llvm/TableGen/Record.h"
21 #include "llvm/TableGen/TableGenBackend.h"
22 
23 #define DEBUG_TYPE "register-bank-emitter"
24 
25 using namespace llvm;
26 
27 namespace {
28 class RegisterBank {
29 
30   /// A vector of register classes that are included in the register bank.
31   typedef std::vector<const CodeGenRegisterClass *> RegisterClassesTy;
32 
33 private:
34   const Record &TheDef;
35 
36   /// The register classes that are covered by the register bank.
37   RegisterClassesTy RCs;
38 
39   /// The register class with the largest register size.
40   std::vector<const CodeGenRegisterClass *> RCsWithLargestRegSize;
41 
42 public:
43   RegisterBank(const Record &TheDef, unsigned NumModeIds)
44       : TheDef(TheDef), RCsWithLargestRegSize(NumModeIds) {}
45 
46   /// Get the human-readable name for the bank.
47   StringRef getName() const { return TheDef.getValueAsString("Name"); }
48   /// Get the name of the enumerator in the ID enumeration.
49   std::string getEnumeratorName() const {
50     return (TheDef.getName() + "ID").str();
51   }
52 
53   /// Get the name of the array holding the register class coverage data;
54   std::string getCoverageArrayName() const {
55     return (TheDef.getName() + "CoverageData").str();
56   }
57 
58   /// Get the name of the global instance variable.
59   StringRef getInstanceVarName() const { return TheDef.getName(); }
60 
61   const Record &getDef() const { return TheDef; }
62 
63   /// Get the register classes listed in the RegisterBank.RegisterClasses field.
64   std::vector<const CodeGenRegisterClass *>
65   getExplicitlySpecifiedRegisterClasses(
66       const CodeGenRegBank &RegisterClassHierarchy) const {
67     std::vector<const CodeGenRegisterClass *> RCs;
68     for (const auto *RCDef : getDef().getValueAsListOfDefs("RegisterClasses"))
69       RCs.push_back(RegisterClassHierarchy.getRegClass(RCDef));
70     return RCs;
71   }
72 
73   /// Add a register class to the bank without duplicates.
74   void addRegisterClass(const CodeGenRegisterClass *RC) {
75     if (llvm::is_contained(RCs, RC))
76       return;
77 
78     // FIXME? We really want the register size rather than the spill size
79     //        since the spill size may be bigger on some targets with
80     //        limited load/store instructions. However, we don't store the
81     //        register size anywhere (we could sum the sizes of the subregisters
82     //        but there may be additional bits too) and we can't derive it from
83     //        the VT's reliably due to Untyped.
84     unsigned NumModeIds = RCsWithLargestRegSize.size();
85     for (unsigned M = 0; M < NumModeIds; ++M) {
86       if (RCsWithLargestRegSize[M] == nullptr)
87         RCsWithLargestRegSize[M] = RC;
88       else if (RCsWithLargestRegSize[M]->RSI.get(M).SpillSize <
89                RC->RSI.get(M).SpillSize)
90         RCsWithLargestRegSize[M] = RC;
91       assert(RCsWithLargestRegSize[M] && "RC was nullptr?");
92     }
93 
94     RCs.emplace_back(RC);
95   }
96 
97   const CodeGenRegisterClass *getRCWithLargestRegSize(unsigned HwMode) const {
98     return RCsWithLargestRegSize[HwMode];
99   }
100 
101   iterator_range<typename RegisterClassesTy::const_iterator>
102   register_classes() const {
103     return llvm::make_range(RCs.begin(), RCs.end());
104   }
105 };
106 
107 class RegisterBankEmitter {
108 private:
109   CodeGenTarget Target;
110   RecordKeeper &Records;
111 
112   void emitHeader(raw_ostream &OS, const StringRef TargetName,
113                   const std::vector<RegisterBank> &Banks);
114   void emitBaseClassDefinition(raw_ostream &OS, const StringRef TargetName,
115                                const std::vector<RegisterBank> &Banks);
116   void emitBaseClassImplementation(raw_ostream &OS, const StringRef TargetName,
117                                    std::vector<RegisterBank> &Banks);
118 
119 public:
120   RegisterBankEmitter(RecordKeeper &R) : Target(R), Records(R) {}
121 
122   void run(raw_ostream &OS);
123 };
124 
125 } // end anonymous namespace
126 
127 /// Emit code to declare the ID enumeration and external global instance
128 /// variables.
129 void RegisterBankEmitter::emitHeader(raw_ostream &OS,
130                                      const StringRef TargetName,
131                                      const std::vector<RegisterBank> &Banks) {
132   // <Target>RegisterBankInfo.h
133   OS << "namespace llvm {\n"
134      << "namespace " << TargetName << " {\n"
135      << "enum : unsigned {\n";
136 
137   OS << "  InvalidRegBankID = ~0u,\n";
138   unsigned ID = 0;
139   for (const auto &Bank : Banks)
140     OS << "  " << Bank.getEnumeratorName() << " = " << ID++ << ",\n";
141   OS << "  NumRegisterBanks,\n"
142      << "};\n"
143      << "} // end namespace " << TargetName << "\n"
144      << "} // end namespace llvm\n";
145 }
146 
147 /// Emit declarations of the <Target>GenRegisterBankInfo class.
148 void RegisterBankEmitter::emitBaseClassDefinition(
149     raw_ostream &OS, const StringRef TargetName,
150     const std::vector<RegisterBank> &Banks) {
151   OS << "private:\n"
152      << "  static const RegisterBank *RegBanks[];\n"
153      << "  static const unsigned Sizes[];\n\n"
154      << "protected:\n"
155      << "  " << TargetName << "GenRegisterBankInfo(unsigned HwMode = 0);\n"
156      << "\n";
157 }
158 
159 /// Visit each register class belonging to the given register bank.
160 ///
161 /// A class belongs to the bank iff any of these apply:
162 /// * It is explicitly specified
163 /// * It is a subclass of a class that is a member.
164 /// * It is a class containing subregisters of the registers of a class that
165 ///   is a member. This is known as a subreg-class.
166 ///
167 /// This function must be called for each explicitly specified register class.
168 ///
169 /// \param RC The register class to search.
170 /// \param Kind A debug string containing the path the visitor took to reach RC.
171 /// \param VisitFn The action to take for each class visited. It may be called
172 ///                multiple times for a given class if there are multiple paths
173 ///                to the class.
174 static void visitRegisterBankClasses(
175     const CodeGenRegBank &RegisterClassHierarchy,
176     const CodeGenRegisterClass *RC, const Twine &Kind,
177     std::function<void(const CodeGenRegisterClass *, StringRef)> VisitFn,
178     SmallPtrSetImpl<const CodeGenRegisterClass *> &VisitedRCs) {
179 
180   // Make sure we only visit each class once to avoid infinite loops.
181   if (!VisitedRCs.insert(RC).second)
182     return;
183 
184   // Visit each explicitly named class.
185   VisitFn(RC, Kind.str());
186 
187   for (const auto &PossibleSubclass : RegisterClassHierarchy.getRegClasses()) {
188     std::string TmpKind =
189         (Kind + " (" + PossibleSubclass.getName() + ")").str();
190 
191     // Visit each subclass of an explicitly named class.
192     if (RC != &PossibleSubclass && RC->hasSubClass(&PossibleSubclass))
193       visitRegisterBankClasses(RegisterClassHierarchy, &PossibleSubclass,
194                                TmpKind + " " + RC->getName() + " subclass",
195                                VisitFn, VisitedRCs);
196 
197     // Visit each class that contains only subregisters of RC with a common
198     // subregister-index.
199     //
200     // More precisely, PossibleSubclass is a subreg-class iff Reg:SubIdx is in
201     // PossibleSubclass for all registers Reg from RC using any
202     // subregister-index SubReg
203     for (const auto &SubIdx : RegisterClassHierarchy.getSubRegIndices()) {
204       BitVector BV(RegisterClassHierarchy.getRegClasses().size());
205       PossibleSubclass.getSuperRegClasses(&SubIdx, BV);
206       if (BV.test(RC->EnumValue)) {
207         std::string TmpKind2 = (Twine(TmpKind) + " " + RC->getName() +
208                                 " class-with-subregs: " + RC->getName())
209                                    .str();
210         VisitFn(&PossibleSubclass, TmpKind2);
211       }
212     }
213   }
214 }
215 
216 void RegisterBankEmitter::emitBaseClassImplementation(
217     raw_ostream &OS, StringRef TargetName, std::vector<RegisterBank> &Banks) {
218   const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
219   const CodeGenHwModes &CGH = Target.getHwModes();
220 
221   OS << "namespace llvm {\n"
222      << "namespace " << TargetName << " {\n";
223   for (const auto &Bank : Banks) {
224     std::vector<std::vector<const CodeGenRegisterClass *>> RCsGroupedByWord(
225         (RegisterClassHierarchy.getRegClasses().size() + 31) / 32);
226 
227     for (const auto &RC : Bank.register_classes())
228       RCsGroupedByWord[RC->EnumValue / 32].push_back(RC);
229 
230     OS << "const uint32_t " << Bank.getCoverageArrayName() << "[] = {\n";
231     unsigned LowestIdxInWord = 0;
232     for (const auto &RCs : RCsGroupedByWord) {
233       OS << "    // " << LowestIdxInWord << "-" << (LowestIdxInWord + 31)
234          << "\n";
235       for (const auto &RC : RCs) {
236         OS << "    (1u << (" << RC->getQualifiedIdName() << " - "
237            << LowestIdxInWord << ")) |\n";
238       }
239       OS << "    0,\n";
240       LowestIdxInWord += 32;
241     }
242     OS << "};\n";
243   }
244   OS << "\n";
245 
246   for (const auto &Bank : Banks) {
247     std::string QualifiedBankID =
248         (TargetName + "::" + Bank.getEnumeratorName()).str();
249     OS << "constexpr RegisterBank " << Bank.getInstanceVarName() << "(/* ID */ "
250        << QualifiedBankID << ", /* Name */ \"" << Bank.getName() << "\", "
251        << "/* CoveredRegClasses */ " << Bank.getCoverageArrayName()
252        << ", /* NumRegClasses */ "
253        << RegisterClassHierarchy.getRegClasses().size() << ");\n";
254   }
255   OS << "} // end namespace " << TargetName << "\n"
256      << "\n";
257 
258   OS << "const RegisterBank *" << TargetName
259      << "GenRegisterBankInfo::RegBanks[] = {\n";
260   for (const auto &Bank : Banks)
261     OS << "    &" << TargetName << "::" << Bank.getInstanceVarName() << ",\n";
262   OS << "};\n\n";
263 
264   unsigned NumModeIds = CGH.getNumModeIds();
265   OS << "const unsigned " << TargetName << "GenRegisterBankInfo::Sizes[] = {\n";
266   for (unsigned M = 0; M < NumModeIds; ++M) {
267     OS << "    // Mode = " << M << " (";
268     if (M == DefaultMode)
269       OS << "Default";
270     else
271       OS << CGH.getMode(M).Name;
272     OS << ")\n";
273     for (const auto &Bank : Banks) {
274       const CodeGenRegisterClass &RC = *Bank.getRCWithLargestRegSize(M);
275       unsigned Size = RC.RSI.get(M).SpillSize;
276       OS << "    " << Size << ",\n";
277     }
278   }
279   OS << "};\n\n";
280 
281   OS << TargetName << "GenRegisterBankInfo::" << TargetName
282      << "GenRegisterBankInfo(unsigned HwMode)\n"
283      << "    : RegisterBankInfo(RegBanks, " << TargetName
284      << "::NumRegisterBanks, Sizes, HwMode) {\n"
285      << "  // Assert that RegBank indices match their ID's\n"
286      << "#ifndef NDEBUG\n"
287      << "  for (auto RB : enumerate(RegBanks))\n"
288      << "    assert(RB.index() == RB.value()->getID() && \"Index != ID\");\n"
289      << "#endif // NDEBUG\n"
290      << "}\n"
291      << "} // end namespace llvm\n";
292 }
293 
294 void RegisterBankEmitter::run(raw_ostream &OS) {
295   StringRef TargetName = Target.getName();
296   const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
297   const CodeGenHwModes &CGH = Target.getHwModes();
298 
299   Records.startTimer("Analyze records");
300   std::vector<RegisterBank> Banks;
301   for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) {
302     SmallPtrSet<const CodeGenRegisterClass *, 8> VisitedRCs;
303     RegisterBank Bank(*V, CGH.getNumModeIds());
304 
305     for (const CodeGenRegisterClass *RC :
306          Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
307       visitRegisterBankClasses(
308           RegisterClassHierarchy, RC, "explicit",
309           [&Bank](const CodeGenRegisterClass *RC, StringRef Kind) {
310             LLVM_DEBUG(dbgs()
311                        << "Added " << RC->getName() << "(" << Kind << ")\n");
312             Bank.addRegisterClass(RC);
313           },
314           VisitedRCs);
315     }
316 
317     Banks.push_back(Bank);
318   }
319 
320   // Warn about ambiguous MIR caused by register bank/class name clashes.
321   Records.startTimer("Warn ambiguous");
322   for (const auto &Class : RegisterClassHierarchy.getRegClasses()) {
323     for (const auto &Bank : Banks) {
324       if (Bank.getName().lower() == StringRef(Class.getName()).lower()) {
325         PrintWarning(Bank.getDef().getLoc(), "Register bank names should be "
326                                              "distinct from register classes "
327                                              "to avoid ambiguous MIR");
328         PrintNote(Bank.getDef().getLoc(), "RegisterBank was declared here");
329         PrintNote(Class.getDef()->getLoc(), "RegisterClass was declared here");
330       }
331     }
332   }
333 
334   Records.startTimer("Emit output");
335   emitSourceFileHeader("Register Bank Source Fragments", OS);
336   OS << "#ifdef GET_REGBANK_DECLARATIONS\n"
337      << "#undef GET_REGBANK_DECLARATIONS\n";
338   emitHeader(OS, TargetName, Banks);
339   OS << "#endif // GET_REGBANK_DECLARATIONS\n\n"
340      << "#ifdef GET_TARGET_REGBANK_CLASS\n"
341      << "#undef GET_TARGET_REGBANK_CLASS\n";
342   emitBaseClassDefinition(OS, TargetName, Banks);
343   OS << "#endif // GET_TARGET_REGBANK_CLASS\n\n"
344      << "#ifdef GET_TARGET_REGBANK_IMPL\n"
345      << "#undef GET_TARGET_REGBANK_IMPL\n";
346   emitBaseClassImplementation(OS, TargetName, Banks);
347   OS << "#endif // GET_TARGET_REGBANK_IMPL\n";
348 }
349 
350 static TableGen::Emitter::OptClass<RegisterBankEmitter>
351     X("gen-register-bank", "Generate registers bank descriptions");
352