Index: include/llvm/Target/GlobalISel/RegisterBank.td =================================================================== --- /dev/null +++ include/llvm/Target/GlobalISel/RegisterBank.td @@ -0,0 +1,16 @@ +//===- RegisterBank.td - Register bank definitions ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +class RegisterBank classes> { + string Name = name; + list RegisterClasses = classes; +} Index: include/llvm/Target/Target.td =================================================================== --- include/llvm/Target/Target.td +++ include/llvm/Target/Target.td @@ -1340,3 +1340,8 @@ // Pull in the common support for DAG isel generation. // include "llvm/Target/TargetSelectionDAG.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for GlobalISel. +// +include "llvm/Target/GlobalISel/RegisterBank.td" Index: lib/Target/AArch64/AArch64.td =================================================================== --- lib/Target/AArch64/AArch64.td +++ lib/Target/AArch64/AArch64.td @@ -124,6 +124,7 @@ //===----------------------------------------------------------------------===// include "AArch64RegisterInfo.td" +include "AArch64RegisterBanks.td" include "AArch64CallingConvention.td" //===----------------------------------------------------------------------===// Index: lib/Target/AArch64/AArch64GenRegisterBankInfo.def =================================================================== --- lib/Target/AArch64/AArch64GenRegisterBankInfo.def +++ lib/Target/AArch64/AArch64GenRegisterBankInfo.def @@ -15,100 +15,12 @@ #error "You shouldn't build this" #endif -namespace llvm { -const uint32_t GPRCoverageData[] = { - (1u << AArch64::GPR32allRegClassID) | (1u << AArch64::GPR32RegClassID) | - (1u << AArch64::GPR32spRegClassID) | - (1u << AArch64::GPR32commonRegClassID) | - (1u << AArch64::GPR32sponlyRegClassID) | - (1u << AArch64::GPR64allRegClassID) | (1u << AArch64::GPR64RegClassID) | - (1u << AArch64::GPR64spRegClassID) | - (1u << AArch64::GPR64commonRegClassID) | - (1u << AArch64::tcGPR64RegClassID) | - (1u << AArch64::GPR64sponlyRegClassID), - 0, -}; -const uint32_t FPRCoverageData[] = { - (1u << AArch64::FPR8RegClassID) | (1u << AArch64::FPR16RegClassID) | - (1u << AArch64::FPR32RegClassID) | (1u << AArch64::FPR64RegClassID) | - (1u << AArch64::DDRegClassID) | (1u << AArch64::FPR128RegClassID) | - (1u << AArch64::FPR128_loRegClassID) | (1u << AArch64::DDDRegClassID) | - (1u << AArch64::DDDDRegClassID), - (1u << (AArch64::QQRegClassID - 32)) | - (1u << (AArch64::QQ_with_qsub0_in_FPR128_loRegClassID - 32)) | - (1u << (AArch64::QQ_with_qsub1_in_FPR128_loRegClassID - 32)) | - (1u - << (AArch64:: - QQQ_with_qsub1_in_FPR128_lo_and_QQQ_with_qsub2_in_FPR128_loRegClassID - - 32)) | - (1u - << (AArch64:: - QQQ_with_qsub0_in_FPR128_lo_and_QQQ_with_qsub2_in_FPR128_loRegClassID - - 32)) | - (1u << (AArch64::QQQQRegClassID - 32)) | - (1u << (AArch64::QQQQ_with_qsub0_in_FPR128_loRegClassID - 32)) | - (1u << (AArch64::QQQQ_with_qsub1_in_FPR128_loRegClassID - 32)) | - (1u << (AArch64::QQQQ_with_qsub2_in_FPR128_loRegClassID - 32)) | - (1u << (AArch64::QQQQ_with_qsub3_in_FPR128_loRegClassID - 32)) | - (1u - << (AArch64:: - QQQQ_with_qsub0_in_FPR128_lo_and_QQQQ_with_qsub1_in_FPR128_loRegClassID - - 32)) | - (1u - << (AArch64:: - QQQQ_with_qsub1_in_FPR128_lo_and_QQQQ_with_qsub2_in_FPR128_loRegClassID - - 32)) | - (1u - << (AArch64:: - QQQQ_with_qsub2_in_FPR128_lo_and_QQQQ_with_qsub3_in_FPR128_loRegClassID - - 32)) | - (1u - << (AArch64:: - QQQQ_with_qsub0_in_FPR128_lo_and_QQQQ_with_qsub2_in_FPR128_loRegClassID - - 32)) | - (1u - << (AArch64:: - QQQQ_with_qsub1_in_FPR128_lo_and_QQQQ_with_qsub3_in_FPR128_loRegClassID - - 32)) | - (1u - << (AArch64:: - QQQQ_with_qsub0_in_FPR128_lo_and_QQQQ_with_qsub3_in_FPR128_loRegClassID - - 32)) | - (1u - << (AArch64:: - QQ_with_qsub0_in_FPR128_lo_and_QQ_with_qsub1_in_FPR128_loRegClassID - - 32)) | - (1u << (AArch64::QQQRegClassID - 32)) | - (1u << (AArch64::QQQ_with_qsub0_in_FPR128_loRegClassID - 32)) | - (1u << (AArch64::QQQ_with_qsub1_in_FPR128_loRegClassID - 32)) | - (1u << (AArch64::QQQ_with_qsub2_in_FPR128_loRegClassID - 32)) | - (1u - << (AArch64:: - QQQ_with_qsub0_in_FPR128_lo_and_QQQ_with_qsub1_in_FPR128_loRegClassID - - 32))}; -const uint32_t CCRCoverageData[] = {1u << AArch64::CCRRegClassID, 0}; - -const RegisterBank::DataTy AArch64GenRegisterBankInfo::RegisterBankData[] = { - {AArch64::GPRRegBankID, "GPR", 64, GPRCoverageData}, - {AArch64::FPRRegBankID, "FPR", 512, FPRCoverageData}, - {AArch64::CCRRegBankID, "CCR", 32, CCRCoverageData}, -}; - -RegisterBank AArch64GenRegisterBankInfo::GPRRegBank(AArch64GenRegisterBankInfo::RegisterBankData[AArch64::GPRRegBankID]); -RegisterBank AArch64GenRegisterBankInfo::FPRRegBank(AArch64GenRegisterBankInfo::RegisterBankData[AArch64::FPRRegBankID]); -RegisterBank AArch64GenRegisterBankInfo::CCRRegBank(AArch64GenRegisterBankInfo::RegisterBankData[AArch64::CCRRegBankID]); - -RegisterBank *AArch64GenRegisterBankInfo::RegBanks[] = { - &AArch64GenRegisterBankInfo::GPRRegBank, - &AArch64GenRegisterBankInfo::FPRRegBank, - &AArch64GenRegisterBankInfo::CCRRegBank}; +#define GET_TARGET_REGBANK_IMPL +#include "AArch64GenRegisterBank.inc" +namespace llvm { RegisterBankInfo::PartialMapping AArch64GenRegisterBankInfo::PartMappings[]{ /* StartIdx, Length, RegBank */ - // 0: GPR 32-bit value. - {0, 32, AArch64GenRegisterBankInfo::GPRRegBank}, - // 1: GPR 64-bit value. - {0, 64, AArch64GenRegisterBankInfo::GPRRegBank}, // 2: FPR 32-bit value. {0, 32, AArch64GenRegisterBankInfo::FPRRegBank}, // 3: FPR 64-bit value. @@ -118,21 +30,18 @@ // 5: FPR 256-bit value. {0, 256, AArch64GenRegisterBankInfo::FPRRegBank}, // 6: FPR 512-bit value. - {0, 512, AArch64GenRegisterBankInfo::FPRRegBank}}; + {0, 512, AArch64GenRegisterBankInfo::FPRRegBank}, + // 0: GPR 32-bit value. + {0, 32, AArch64GenRegisterBankInfo::GPRRegBank}, + // 1: GPR 64-bit value. + {0, 64, AArch64GenRegisterBankInfo::GPRRegBank}, +}; // ValueMappings. RegisterBankInfo::ValueMapping AArch64GenRegisterBankInfo::ValMappings[]{ /* BreakDown, NumBreakDowns */ // 3-operands instructions (all binary operations should end up with one of // those mapping). - // 0: GPR 32-bit value. <-- This must match First3OpsIdx. - {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, - {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, - {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, - // 3: GPR 64-bit value. - {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, - {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, - {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, // 6: FPR 32-bit value. {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, @@ -153,21 +62,38 @@ {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, - // Cross register bank copies. - // 21: GPR 32-bit value to FPR 32-bit value. <-- This must match - // FirstCrossRegCpyIdx. + // 0: GPR 32-bit value. <-- This must match First3OpsIdx. {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, - {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, - // 23: GPR 64-bit value to FPR 64-bit value. + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, + // 3: GPR 64-bit value. {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, - {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, + // Cross register bank copies. // 25: FPR 32-bit value to GPR 32-bit value. {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, // 27: FPR 64-bit value to GPR 64-bit value. <-- This must match // LastCrossRegCpyIdx. {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, - {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1} + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, + // + {nullptr, 1}, + {nullptr, 1}, + // + {nullptr, 1}, + {nullptr, 1}, + // + {nullptr, 1}, + {nullptr, 1}, + // 21: GPR 32-bit value to FPR 32-bit value. <-- This must match + // FirstCrossRegCpyIdx. + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, + // 23: GPR 64-bit value to FPR 64-bit value. + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, }; bool AArch64GenRegisterBankInfo::checkPartialMap(unsigned Idx, @@ -251,9 +177,9 @@ AArch64GenRegisterBankInfo::PartialMappingIdx AArch64GenRegisterBankInfo::BankIDToCopyMapIdx[]{ - PMI_FirstGPR, // GPR - PMI_FirstFPR, // FPR PMI_None, // CCR + PMI_FirstFPR, // FPR + PMI_FirstGPR, // GPR }; const RegisterBankInfo::ValueMapping * Index: lib/Target/AArch64/AArch64RegisterBankInfo.h =================================================================== --- lib/Target/AArch64/AArch64RegisterBankInfo.h +++ lib/Target/AArch64/AArch64RegisterBankInfo.h @@ -16,19 +16,13 @@ #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" +#define GET_REGBANK_DECLARATIONS +#include "AArch64GenRegisterBank.inc" + namespace llvm { class TargetRegisterInfo; -namespace AArch64 { -enum { - GPRRegBankID = 0, /// General Purpose Registers: W, X. - FPRRegBankID = 1, /// Floating Point/Vector Registers: B, H, S, D, Q. - CCRRegBankID = 2, /// Conditional register: NZCV. - NumRegisterBanks -}; -} // End AArch64 namespace. - class AArch64GenRegisterBankInfo : public RegisterBankInfo { private: static const RegisterBank::DataTy RegisterBankData[]; @@ -39,18 +33,18 @@ enum PartialMappingIdx { PMI_None = -1, - PMI_GPR32 = 1, - PMI_GPR64, - PMI_FPR32, + PMI_FPR32 = 1, PMI_FPR64, PMI_FPR128, PMI_FPR256, PMI_FPR512, + PMI_GPR32, + PMI_GPR64, PMI_FirstGPR = PMI_GPR32, PMI_LastGPR = PMI_GPR64, PMI_FirstFPR = PMI_FPR32, PMI_LastFPR = PMI_FPR512, - PMI_Min = PMI_FirstGPR, + PMI_Min = PMI_FirstFPR, }; static RegisterBank GPRRegBank; @@ -66,7 +60,7 @@ Last3OpsIdx = 18, DistanceBetweenRegBanks = 3, FirstCrossRegCpyIdx = 21, - LastCrossRegCpyIdx = 27, + LastCrossRegCpyIdx = 33, DistanceBetweenCrossRegCpy = 2 }; Index: lib/Target/AArch64/AArch64RegisterBanks.td =================================================================== --- /dev/null +++ lib/Target/AArch64/AArch64RegisterBanks.td @@ -0,0 +1,20 @@ +//=- AArch64RegisterBank.td - Describe the AArch64 Banks -----*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +/// General Purpose Registers: W, X. +def GPRRegBank : RegisterBank<"GPR", [GPR64all]>; + +/// Floating Point/Vector Registers: B, H, S, D, Q. +def FPRRegBank : RegisterBank<"FPR", [QQQQ]>; + +/// Conditional register: NZCV. +def CCRRegBank : RegisterBank<"CCR", [CCR]>; Index: lib/Target/AArch64/CMakeLists.txt =================================================================== --- lib/Target/AArch64/CMakeLists.txt +++ lib/Target/AArch64/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_TARGET_DEFINITIONS AArch64.td) +tablegen(LLVM AArch64GenRegisterBank.inc -gen-register-bank) tablegen(LLVM AArch64GenRegisterInfo.inc -gen-register-info) tablegen(LLVM AArch64GenInstrInfo.inc -gen-instr-info) tablegen(LLVM AArch64GenMCCodeEmitter.inc -gen-emitter) Index: utils/TableGen/CMakeLists.txt =================================================================== --- utils/TableGen/CMakeLists.txt +++ utils/TableGen/CMakeLists.txt @@ -26,6 +26,7 @@ IntrinsicEmitter.cpp OptParserEmitter.cpp PseudoLoweringEmitter.cpp + RegisterBankEmitter.cpp RegisterInfoEmitter.cpp SearchableTableEmitter.cpp SubtargetEmitter.cpp Index: utils/TableGen/RegisterBankEmitter.cpp =================================================================== --- /dev/null +++ utils/TableGen/RegisterBankEmitter.cpp @@ -0,0 +1,289 @@ +//===- RegisterBankEmitter.cpp - Generate a Register Bank Desc. -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting a description of a target +// register bank for a code generator. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/BitVector.h" +#include "llvm/Support/Debug.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" + +#include "CodeGenRegisters.h" + +#define DEBUG_TYPE "register-bank-emitter" + +using namespace llvm; + +namespace { +class RegisterBank { + + /// A vector of register classes. The StringRef indicates why the register + /// class is included in the register bank. + typedef std::vector RegisterClassesTy; + +private: + const Record &TheDef; + + /// The register classes that are covered by the register bank. + /// It should be noted that the StringRef in the pair only describes the first + /// reason the register class is included. There may be additional reasons. + RegisterClassesTy RCs; + + /// Used to report the register class associated with the min/max partial + /// mapping. It should be replaced when ExcludePartialMappings is removed. + const CodeGenRegisterClass *RCWithLargestRegsSize; + +public: + RegisterBank(const Record &TheDef) + : TheDef(TheDef), RCs(), RCWithLargestRegsSize(nullptr) {} + + /// Get the human-readable name for the bank. + std::string getName() const { return TheDef.getValueAsString("Name"); } + /// Get the name of the enumerator in the ID enumeration. + std::string getEnumeratorName() const { return (TheDef.getName() + "ID").str(); } + + /// Get the name of the array holding the register class coverage data; + std::string getCoverageArrayName() const { + return (TheDef.getName() + "CoverageData").str(); + } + + /// Get the name of the global instance variable. + StringRef getInstanceVarName() const { return TheDef.getName(); } + + const Record &getDef() const { return TheDef; } + + /// Get the register classes listed in the RegisterBank.RegisterClasses field. + std::vector + getExplictlySpecifiedRegisterClasses( + CodeGenRegBank &RegisterClassHierarchy) const { + std::vector RCs; + for (const auto &RCDef : getDef().getValueAsListOfDefs("RegisterClasses")) + RCs.push_back(RegisterClassHierarchy.getRegClass(RCDef)); + return RCs; + } + + /// Add a register class to the bank without duplicates. + void addRegisterClass(const CodeGenRegisterClass *RC) { + if (std::find_if(RCs.begin(), RCs.end(), + [&RC](const CodeGenRegisterClass *X) { + return X == RC; + }) != RCs.end()) + return; + + // FIXME? We really want the register size rather than the spill size + // since the spill size may be bigger on some targets with + // limited load/store instructions. However, we don't store the + // register size anywhere (we could sum the sizes of the subregisters + // but there may be additional bits too) and we can't derive it from + // the VT's reliably due to Untyped. + if (RCWithLargestRegsSize == nullptr) + RCWithLargestRegsSize = RC; + else if (RCWithLargestRegsSize->SpillSize < RC->SpillSize) + RCWithLargestRegsSize = RC; + assert(RCWithLargestRegsSize && "RC was nullptr?"); + + RCs.emplace_back(RC); + } + + const CodeGenRegisterClass *getRCWithLargestRegsSize() const { + return RCWithLargestRegsSize; + } + + iterator_range + register_classes() const { + return llvm::make_range(RCs.begin(), RCs.end()); + } +}; + +class RegisterBankEmitter { +private: + RecordKeeper &Records; + CodeGenRegBank RegisterClassHierarchy; + + void emitHeader(raw_ostream &OS, const StringRef TargetName, + const std::vector &Banks); + void emitBaseClassDefinition(raw_ostream &OS, const StringRef TargetName, + const std::vector &Banks); + void emitBaseClassImplementation(raw_ostream &OS, const StringRef TargetName, + std::vector &Banks); + +public: + RegisterBankEmitter(RecordKeeper &R) + : Records(R), RegisterClassHierarchy(Records) {} + + void run(raw_ostream &OS); +}; + +} // end anonymous namespace + +/// Emit code to declare the ID enumeration and external global instance +/// variables. +void RegisterBankEmitter::emitHeader(raw_ostream &OS, + const StringRef TargetName, + const std::vector &Banks) { + // RegisterBankInfo.h + OS << "namespace llvm {\n" + << "namespace " << TargetName << " {\n" + << "enum {\n"; + for (const auto &Bank : Banks) + OS << " " << Bank.getEnumeratorName() << ",\n"; + OS << " NumRegisterBanks,\n" + << " NoRegisterBankID = ~0U,\n"; + OS << "};\n" + << "} // end namespace " << TargetName << "\n" + << "} // end namespace llvm\n"; +} + +/// Emit declarations of the GenRegisterBankInfo class. +void RegisterBankEmitter::emitBaseClassDefinition( + raw_ostream &OS, const StringRef TargetName, + const std::vector &Banks) { +} + +/// Visit each register class belonging to the given register bank. +/// +/// A class belongs to the bank iff: +/// * It is explicitly specified +/// * It is a subclass of a class that is a member. +/// * It is a class containing subregisters of the registers of a class that +/// is a member. +/// +/// This function must be called for each explicitly specified register class. +static void visitRegisterBankClasses( + CodeGenRegBank &RegisterClassHierarchy, const CodeGenRegisterClass *RC, + const Twine Kind, + std::function visitFn) { + // Visit each explicitly named class. + visitFn(RC, Kind.str()); + + for (const auto &PossibleSubclass : RegisterClassHierarchy.getRegClasses()) { + Twine TmpKind = Kind + " (" + PossibleSubclass.getName() + ")"; + + // Visit each subclass of an explicitly named class + if (RC != &PossibleSubclass && RC->hasSubClass(&PossibleSubclass)) + visitRegisterBankClasses(RegisterClassHierarchy, &PossibleSubclass, + TmpKind + " " + RC->getName() + " subclass", + visitFn); + + // Visit each class that has a subregister of RC + for (const auto &SubIdx : RegisterClassHierarchy.getSubRegIndices()) { + BitVector BV(RegisterClassHierarchy.getRegClasses().size()); + PossibleSubclass.getSuperRegClasses(&SubIdx, BV); + if (BV.test(RC->EnumValue)) { + Twine TmpKind2 = TmpKind + " " + RC->getName() + + " class-with-subregs: " + RC->getName(); + visitFn(&PossibleSubclass, TmpKind2.str()); + } + } + } +} + +void RegisterBankEmitter::emitBaseClassImplementation( + raw_ostream &OS, StringRef TargetName, + std::vector &Banks) { + + OS << "namespace llvm {\n" + << "namespace {\n"; + for (const auto &Bank : Banks) { + std::vector> RCsGroupedByWord( + (RegisterClassHierarchy.getRegClasses().size() + 31) / 32); + + for (const auto &RC : Bank.register_classes()) + RCsGroupedByWord[RC->EnumValue / 32].push_back(RC); + + OS << "uint32_t " << Bank.getCoverageArrayName() << "[] = {\n"; + unsigned LowestIdxInWord = 0; + for (const auto &RCs : RCsGroupedByWord) { + OS << " // " << LowestIdxInWord << "-" << (LowestIdxInWord + 31) << "\n"; + for (const auto &RC : RCs) { + Twine QualifiedRegClassID = + TargetName + "::" + RC->getName() + "RegClassID"; + OS << " (1u << (" << QualifiedRegClassID << " - " + << LowestIdxInWord << ")) |\n"; + } + OS << " 0,\n"; + LowestIdxInWord += 32; + } + OS << "};\n"; + } + OS << "} // end anonymous namespace\n" + << "const RegisterBank::DataTy " << TargetName + << "GenRegisterBankInfo::RegisterBankData[] = {\n"; + for (const auto &Bank : Banks) { + Twine QualifiedBankID = TargetName + "::" + Bank.getEnumeratorName(); + unsigned Size = Bank.getRCWithLargestRegsSize()->SpillSize; + OS << " {" << QualifiedBankID << ", \"" << Bank.getName() << "\", " + << Size << ", " << Bank.getCoverageArrayName() << "},\n"; + } + OS << "};\n"; + + for (const auto &Bank : Banks) + OS << "RegisterBank " << TargetName + << "GenRegisterBankInfo::" << Bank.getInstanceVarName() << "(" + << TargetName << "GenRegisterBankInfo::RegisterBankData[" << TargetName + << "::" << Bank.getEnumeratorName() << "]);\n"; + OS << "\n"; + + OS << "RegisterBank *AArch64GenRegisterBankInfo::RegBanks[] = {\n"; + for (const auto &Bank : Banks) + OS << " &" << TargetName + << "GenRegisterBankInfo::" << Bank.getInstanceVarName() << ",\n"; + OS << "};\n" + << "} // end namespace llvm\n"; +} + +void RegisterBankEmitter::run(raw_ostream &OS) { + std::vector Targets = Records.getAllDerivedDefinitions("Target"); + if (Targets.size() != 1) + PrintFatalError("ERROR: Too many or too few subclasses of Target defined!"); + StringRef TargetName = Targets[0]->getName(); + + std::vector Banks; + for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) { + RegisterBank Bank(*V); + + for (const CodeGenRegisterClass *RC : + Bank.getExplictlySpecifiedRegisterClasses(RegisterClassHierarchy)) { + visitRegisterBankClasses( + RegisterClassHierarchy, RC, "explicit", + [&Bank](const CodeGenRegisterClass *RC, StringRef Kind) { + DEBUG(dbgs() << "Added " << RC->getName() << "(" << Kind << ")\n"); + Bank.addRegisterClass(RC); + }); + } + + Banks.push_back(Bank); + } + + emitSourceFileHeader("Register Bank Source Fragments", OS); + OS << "#ifdef GET_REGBANK_DECLARATIONS\n" + << "#undef GET_REGBANK_DECLARATIONS\n"; + emitHeader(OS, TargetName, Banks); + OS << "#endif // GET_REGBANK_DECLARATIONS\n\n" + << "#ifdef GET_TARGET_REGBANK_CLASS\n" + << "#undef GET_TARGET_REGBANK_CLASS\n"; + emitBaseClassDefinition(OS, TargetName, Banks); + OS << "#endif // GET_TARGET_REGBANK_CLASS\n\n" + << "#ifdef GET_TARGET_REGBANK_IMPL\n" + << "#undef GET_TARGET_REGBANK_IMPL\n"; + emitBaseClassImplementation(OS, TargetName, Banks); + OS << "#endif // GET_TARGET_REGBANK_IMPL\n"; +} + +namespace llvm { + +void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS) { + RegisterBankEmitter(RK).run(OS); +} + +} // end namespace llvm Index: utils/TableGen/TableGen.cpp =================================================================== --- utils/TableGen/TableGen.cpp +++ utils/TableGen/TableGen.cpp @@ -45,6 +45,7 @@ GenCTags, GenAttributes, GenSearchableTables, + GenRegisterBank, }; namespace { @@ -91,7 +92,9 @@ clEnumValN(GenAttributes, "gen-attrs", "Generate attributes"), clEnumValN(GenSearchableTables, "gen-searchable-tables", - "Generate generic binary-searchable table"))); + "Generate generic binary-searchable table"), + clEnumValN(GenRegisterBank, "gen-register-bank", + "Generate registers bank descriptions"))); cl::opt Class("class", cl::desc("Print Enum list for this class"), @@ -177,6 +180,9 @@ case GenSearchableTables: EmitSearchableTables(Records, OS); break; + case GenRegisterBank: + EmitRegisterBank(Records, OS); + break; } return false; Index: utils/TableGen/TableGenBackends.h =================================================================== --- utils/TableGen/TableGenBackends.h +++ utils/TableGen/TableGenBackends.h @@ -80,6 +80,7 @@ void EmitCTags(RecordKeeper &RK, raw_ostream &OS); void EmitAttributes(RecordKeeper &RK, raw_ostream &OS); void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS); +void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace