[llvm] TableGen support for RegisterBankInfo (PR #71357)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 16 16:44:38 PST 2023
================
@@ -289,6 +299,141 @@ void RegisterBankEmitter::emitBaseClassImplementation(
<< "} // end namespace llvm\n";
}
+// TableGen already had some RegisterBankInfo support:
+// TargetGenRegisterBankInfo(), RegBankIDs enum, RegBanks and Sizes.
+// This emitter adds support for PartialMappings, PartialMappingIdx
+// and BankIDToCopyMapIdx.
+//
+// The original implementation was supposed to infer RegisterClasses.
+// But since that wasn't finished, backends instead embedded hand crafted
+// tables and enums. This emitter generates them from .td files
+// but requires that the .td files fully describe their RegisterBanks.
+//
+// These tables and enums are enabled by GET_REGBANKINFO_DECLARATIONS,
+// GET_REGBANKINFO_PARTIALMAPPINGS and GET_REGBANKINFO_VALUEMAPPINGS
+//
+// This was discussed in https://discourse.llvm.org/t/74459
+void RegisterBankEmitter::emitRBIHeader(
+ raw_ostream &OS, StringRef TargetName,
+ const std::vector<RegisterBank> &Banks) {
+ const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
+
+ OS << "namespace llvm {\n"
+ << "namespace " << TargetName << " {\n"
+ << "enum PartialMappingIdx {\n"
+ << " PMI_None = -1,\n";
+
+ // Banks and Register Classes are *not* emitted in their original text order
+ int ID = 0;
+ for (const auto &Bank : Banks) {
+ for (const CodeGenRegisterClass *RC :
+ Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
+ OS << " PMI_" << RC->getName() << " = " << ID++ << ",\n";
+ }
+ }
+ OS << "};\n";
+ OS << "} // end namespace " << TargetName << "\n"
+ << "} // end namespace llvm\n";
+}
+
+void RegisterBankEmitter::emitRBIPartialMappings(
+ raw_ostream &OS, StringRef TargetName,
+ const std::vector<RegisterBank> &Banks) {
+ const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
+
+ OS << "namespace llvm {\n"
+ << "namespace " << TargetName << " {\n"
+ << "const RegisterBankInfo::PartialMapping PartialMappings[] = {\n";
+ for (const auto &Bank : Banks) {
+ for (const CodeGenRegisterClass *RC :
+ Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
+ if (!RC->RSI.isSimple()) {
+ OS << " #error non-Simple() RegisterClass " << RC->getName() << "\n";
+ } else if (RC->getValueTypes()[0].getSimple() == MVT::Untyped) {
+ OS << " #error Untyped RegisterClass " << RC->getName() << "\n";
+ } else {
+ // StartIdx is currently 0 in all of the in-tree backends
+ OS << " { 0, " << RC->RSI.getSimple().RegSize << ", "
+ << Bank.getInstanceVarName() << " },\n";
+ }
+ }
+ }
+ OS << "};\n\n";
+
+ // emit PartialMappingIdx of the first Register Class of each Register Bank
+ OS << "const PartialMappingIdx BankIDToFirstRegisterClassIdx[] = {\n";
+ for (const auto &Bank : Banks) {
+ OS << " PMI_"
+ << Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)[0]
+ ->getName()
+ << ",\n";
+ }
+ OS << "};\n\n";
+
+ // emit count of Register Classes of each Register Bank
+ OS << "const int BankIDToRegisterClassCount[] = {\n";
+ for (const auto &Bank : Banks) {
+ OS << " "
+ << Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)
+ .size()
+ << ",\n";
+ }
+ OS << "};\n\n";
+
+ OS << "} // end namespace " << TargetName << "\n"
+ << "} // end namespace llvm\n";
+}
+
+// This supports ValueMappings for the simple cases.
+// For the complex cases, GET_REGBANKINFO_VALUEMAPPINGS should be left
+// undefined and the ValueMapping tables and enums must be hand crafted.
+void RegisterBankEmitter::emitRBIValueMappings(
+ raw_ostream &OS, StringRef TargetName,
+ const std::vector<RegisterBank> &Banks) {
+ const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
+
+ OS << "namespace llvm {\n"
+ << "namespace " << TargetName << " {\n"
+ << "const RegisterBankInfo::ValueMapping ValueMappings[] = {\n"
+ << " { nullptr, 0 },\n";
+ for (const auto &Bank : Banks) {
+ for (const CodeGenRegisterClass *RC :
+ Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
+ if (!RC->RSI.isSimple()) {
+ OS << " #error non-Simple() RegisterClass " << RC->getName() << "\n";
+ } else if (RC->getValueTypes()[0].getSimple() == MVT::Untyped) {
+ OS << " #error Untyped RegisterClass " << RC->getName() << "\n";
+ } else {
+ OS << " { &PartialMappings[PMI_" << RC->getName() << "], 1},\n"
+ << " { &PartialMappings[PMI_" << RC->getName() << "], 1},\n"
+ << " { &PartialMappings[PMI_" << RC->getName() << "], 1},\n";
+ }
+ }
+ }
+ OS << "};\n\n";
+
+ OS << "enum ValueMappingIdx = {\n"
+ << " VMI_Invalid = 0,\n";
+ int Offset = 1;
+ for (const auto &Bank : Banks) {
+ for (const CodeGenRegisterClass *RC :
+ Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
+ if (!RC->RSI.isSimple()) {
+ OS << " #error non-Simple() RegisterClass " << RC->getName() << "\n";
+ } else if (RC->getValueTypes()[0].getSimple() == MVT::Untyped) {
+ OS << " #error Untyped RegisterClass " << RC->getName() << "\n";
----------------
arsenm wrote:
'\n' calls a different operator<< which is usually inlined vs. one that usually isn't. "\n" is more expensive
https://github.com/llvm/llvm-project/pull/71357
More information about the llvm-commits
mailing list