Index: llvm/trunk/include/llvm/CodeGen/GlobalISel/RegisterBank.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/GlobalISel/RegisterBank.h +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/RegisterBank.h @@ -42,7 +42,7 @@ public: RegisterBank(unsigned ID, const char *Name, unsigned Size, - const uint32_t *ContainedRegClasses); + const uint32_t *ContainedRegClasses, unsigned NumRegClasses); /// Get the identifier of this register bank. unsigned getID() const { return ID; } Index: llvm/trunk/include/llvm/Target/GlobalISel/RegisterBank.td =================================================================== --- llvm/trunk/include/llvm/Target/GlobalISel/RegisterBank.td +++ llvm/trunk/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: llvm/trunk/include/llvm/Target/Target.td =================================================================== --- llvm/trunk/include/llvm/Target/Target.td +++ llvm/trunk/include/llvm/Target/Target.td @@ -1344,4 +1344,5 @@ //===----------------------------------------------------------------------===// // Pull in the common support for Global ISel generation. // +include "llvm/Target/GlobalISel/RegisterBank.td" include "llvm/Target/TargetGlobalISel.td" Index: llvm/trunk/lib/CodeGen/GlobalISel/RegisterBank.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/RegisterBank.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/RegisterBank.cpp @@ -19,10 +19,11 @@ const unsigned RegisterBank::InvalidID = UINT_MAX; -RegisterBank::RegisterBank(unsigned ID, const char *Name, unsigned Size, - const uint32_t *CoveredClasses) +RegisterBank::RegisterBank( + unsigned ID, const char *Name, unsigned Size, + const uint32_t *CoveredClasses, unsigned NumRegClasses) : ID(ID), Name(Name), Size(Size) { - ContainedRegClasses.resize(200); + ContainedRegClasses.resize(NumRegClasses); ContainedRegClasses.setBitsInMask(CoveredClasses); } Index: llvm/trunk/lib/Target/AArch64/AArch64.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64.td +++ llvm/trunk/lib/Target/AArch64/AArch64.td @@ -127,6 +127,7 @@ //===----------------------------------------------------------------------===// include "AArch64RegisterInfo.td" +include "AArch64RegisterBanks.td" include "AArch64CallingConvention.td" //===----------------------------------------------------------------------===// Index: llvm/trunk/lib/Target/AArch64/AArch64GenRegisterBankInfo.def =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64GenRegisterBankInfo.def +++ llvm/trunk/lib/Target/AArch64/AArch64GenRegisterBankInfo.def @@ -16,204 +16,81 @@ #endif namespace llvm { -namespace AArch64 { - -const uint32_t GPRCoverageData[] = { - // Classes 0-31 - (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), - // Classes 32-63 - 0, - // FIXME: The entries below this point can be safely removed once this is - // tablegenerated. It's only needed because of the hardcoded register class - // limit. - // Classes 64-96 - 0, - // Classes 97-128 - 0, - // Classes 129-160 - 0, - // Classes 161-192 - 0, - // Classes 193-224 - 0, -}; - -const uint32_t FPRCoverageData[] = { - // Classes 0-31 - (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), - // Classes 32-63 - (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)), - // FIXME: The entries below this point can be safely removed once this - // is tablegenerated. It's only needed because of the hardcoded register - // class limit. - // Classes 64-96 - 0, - // Classes 97-128 - 0, - // Classes 129-160 - 0, - // Classes 161-192 - 0, - // Classes 193-224 - 0, -}; - -const uint32_t CCRCoverageData[] = { - // Classes 0-31 - 1u << AArch64::CCRRegClassID, - // Classes 32-63 - 0, - // FIXME: The entries below this point can be safely removed once this - // is tablegenerated. It's only needed because of the hardcoded register - // class limit. - // Classes 64-96 - 0, - // Classes 97-128 - 0, - // Classes 129-160 - 0, - // Classes 161-192 - 0, - // Classes 193-224 - 0, -}; - -RegisterBank GPRRegBank(AArch64::GPRRegBankID, "GPR", 64, GPRCoverageData); -RegisterBank FPRRegBank(AArch64::FPRRegBankID, "FPR", 512, FPRCoverageData); -RegisterBank CCRRegBank(AArch64::CCRRegBankID, "CCR", 32, CCRCoverageData); -} // end namespace AArch64 - -RegisterBank *AArch64GenRegisterBankInfo::RegBanks[] = { - &AArch64::GPRRegBank, &AArch64::FPRRegBank, &AArch64::CCRRegBank}; - RegisterBankInfo::PartialMapping AArch64GenRegisterBankInfo::PartMappings[]{ /* StartIdx, Length, RegBank */ - // 0: GPR 32-bit value. - {0, 32, AArch64::GPRRegBank}, - // 1: GPR 64-bit value. - {0, 64, AArch64::GPRRegBank}, - // 2: FPR 32-bit value. + // 0: FPR 32-bit value. {0, 32, AArch64::FPRRegBank}, - // 3: FPR 64-bit value. + // 1: FPR 64-bit value. {0, 64, AArch64::FPRRegBank}, - // 4: FPR 128-bit value. + // 2: FPR 128-bit value. {0, 128, AArch64::FPRRegBank}, - // 5: FPR 256-bit value. + // 3: FPR 256-bit value. {0, 256, AArch64::FPRRegBank}, - // 6: FPR 512-bit value. - {0, 512, AArch64::FPRRegBank}}; + // 4: FPR 512-bit value. + {0, 512, AArch64::FPRRegBank}, + // 5: GPR 32-bit value. + {0, 32, AArch64::GPRRegBank}, + // 6: GPR 64-bit value. + {0, 64, AArch64::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. + // 0: FPR 32-bit value. <-- This must match First3OpsIdx. {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, - // 9: FPR 64-bit value. + // 3: FPR 64-bit value. {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, - // 12: FPR 128-bit value. + // 6: FPR 128-bit value. {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR128 - PMI_Min], 1}, - // 15: FPR 256-bit value. + // 9: FPR 256-bit value. {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR256 - PMI_Min], 1}, - // 18: FPR 512-bit value. <-- This must match Last3OpsIdx. + // 12: FPR 512-bit value. {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR512 - PMI_Min], 1}, + // 15: GPR 32-bit value. + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, + // 18: GPR 64-bit value. <-- This must match Last3OpsIdx. + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, // Cross register bank copies. - // 21: GPR 32-bit value to FPR 32-bit value. <-- This must match + // 21: FPR 32-bit value to GPR 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_GPR32 - PMI_Min], 1}, + // 23: FPR 64-bit value to GPR 64-bit value. {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, - // 25: FPR 32-bit value to GPR 32-bit value. - {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, + // 25: FPR 128-bit value to GPR 128-bit value (invalid) + {nullptr, 1}, + {nullptr, 1}, + // 27: FPR 256-bit value to GPR 256-bit value (invalid) + {nullptr, 1}, + {nullptr, 1}, + // 29: FPR 512-bit value to GPR 512-bit value (invalid) + {nullptr, 1}, + {nullptr, 1}, + // 31: GPR 32-bit value to FPR 32-bit value. {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, - // 27: FPR 64-bit value to GPR 64-bit value. <-- This must match + {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, + // 33: GPR 64-bit value to FPR 64-bit value. <-- This must match // LastCrossRegCpyIdx. + {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, {&AArch64GenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, - {&AArch64GenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1} }; bool AArch64GenRegisterBankInfo::checkPartialMap(unsigned Idx, @@ -301,9 +178,9 @@ AArch64GenRegisterBankInfo::PartialMappingIdx AArch64GenRegisterBankInfo::BankIDToCopyMapIdx[]{ - PMI_FirstGPR, // GPR - PMI_FirstFPR, // FPR PMI_None, // CCR + PMI_FirstFPR, // FPR + PMI_FirstGPR, // GPR }; const RegisterBankInfo::ValueMapping * Index: llvm/trunk/lib/Target/AArch64/AArch64RegisterBankInfo.h =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64RegisterBankInfo.h +++ llvm/trunk/lib/Target/AArch64/AArch64RegisterBankInfo.h @@ -16,40 +16,30 @@ #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 RegisterBank *RegBanks[]; - protected: - AArch64GenRegisterBankInfo(); 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 RegisterBankInfo::PartialMapping PartMappings[]; @@ -61,7 +51,7 @@ Last3OpsIdx = 18, DistanceBetweenRegBanks = 3, FirstCrossRegCpyIdx = 21, - LastCrossRegCpyIdx = 27, + LastCrossRegCpyIdx = 33, DistanceBetweenCrossRegCpy = 2 }; @@ -90,6 +80,9 @@ /// register bank with a size of \p Size. static const RegisterBankInfo::ValueMapping * getCopyMapping(unsigned DstBankID, unsigned SrcBankID, unsigned Size); + +#define GET_TARGET_REGBANK_CLASS +#include "AArch64GenRegisterBank.inc" }; /// This class provides the information for the target register banks. Index: llvm/trunk/lib/Target/AArch64/AArch64RegisterBankInfo.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64RegisterBankInfo.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64RegisterBankInfo.cpp @@ -21,6 +21,9 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" +#define GET_TARGET_REGBANK_IMPL +#include "AArch64GenRegisterBank.inc" + // This file will be TableGen'ed at some point. #include "AArch64GenRegisterBankInfo.def" @@ -30,9 +33,6 @@ #error "You shouldn't build this" #endif -AArch64GenRegisterBankInfo::AArch64GenRegisterBankInfo() - : RegisterBankInfo(RegBanks, AArch64::NumRegisterBanks) {} - AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo &TRI) : AArch64GenRegisterBankInfo() { static bool AlreadyInit = false; Index: llvm/trunk/lib/Target/AArch64/AArch64RegisterBanks.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64RegisterBanks.td +++ llvm/trunk/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: llvm/trunk/lib/Target/AArch64/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Target/AArch64/CMakeLists.txt +++ llvm/trunk/lib/Target/AArch64/CMakeLists.txt @@ -14,6 +14,7 @@ tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler) tablegen(LLVM AArch64GenSystemOperands.inc -gen-searchable-tables) if(LLVM_BUILD_GLOBAL_ISEL) + tablegen(LLVM AArch64GenRegisterBank.inc -gen-register-bank) tablegen(LLVM AArch64GenGlobalISel.inc -gen-global-isel) endif() Index: llvm/trunk/lib/Target/ARM/ARMRegisterBankInfo.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMRegisterBankInfo.cpp +++ llvm/trunk/lib/Target/ARM/ARMRegisterBankInfo.cpp @@ -55,7 +55,9 @@ 0, }; -RegisterBank GPRRegBank(ARM::GPRRegBankID, "GPRB", 32, ARM::GPRCoverageData); +// FIXME: The 200 will be replaced by the number of register classes when this is +// tablegenerated. +RegisterBank GPRRegBank(ARM::GPRRegBankID, "GPRB", 32, ARM::GPRCoverageData, 200); RegisterBank *RegBanks[] = {&GPRRegBank}; RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank}; Index: llvm/trunk/llvm/Target/GlobalISel/RegisterBank.td =================================================================== --- llvm/trunk/llvm/Target/GlobalISel/RegisterBank.td +++ llvm/trunk/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: llvm/trunk/utils/TableGen/CMakeLists.txt =================================================================== --- llvm/trunk/utils/TableGen/CMakeLists.txt +++ llvm/trunk/utils/TableGen/CMakeLists.txt @@ -27,6 +27,7 @@ IntrinsicEmitter.cpp OptParserEmitter.cpp PseudoLoweringEmitter.cpp + RegisterBankEmitter.cpp RegisterInfoEmitter.cpp SearchableTableEmitter.cpp SubtargetEmitter.cpp Index: llvm/trunk/utils/TableGen/RegisterBankEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/RegisterBankEmitter.cpp +++ llvm/trunk/utils/TableGen/RegisterBankEmitter.cpp @@ -0,0 +1,309 @@ +//===- 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 that are included in the register bank. + typedef std::vector RegisterClassesTy; + +private: + const Record &TheDef; + + /// The register classes that are covered by the register bank. + RegisterClassesTy RCs; + + /// The register class with the largest register size. + 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" + << "};\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) { + OS << "private:\n" + << " static RegisterBank *RegBanks[];\n\n" + << "protected:\n" + << " " << TargetName << "GenRegisterBankInfo();\n" + << "\n"; +} + +/// Visit each register class belonging to the given register bank. +/// +/// A class belongs to the bank iff any of these apply: +/// * 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 is known as a subreg-class. +/// +/// This function must be called for each explicitly specified register class. +/// +/// \param RC The register class to search. +/// \param Kind A debug string containing the path the visitor took to reach RC. +/// \param VisitFn The action to take for each class visited. It may be called +/// multiple times for a given class if there are multiple paths +/// to the 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 contains only subregisters of RC with a common + // subregister-index. + // + // More precisely, PossibleSubclass is a subreg-class iff Reg:SubIdx is in + // PossibleSubclass for all registers Reg from RC using any + // subregister-index SubReg + 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 " << TargetName << " {\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 << "const 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 << "\n"; + + for (const auto &Bank : Banks) { + Twine QualifiedBankID = TargetName + "::" + Bank.getEnumeratorName(); + unsigned Size = Bank.getRCWithLargestRegsSize()->SpillSize; + OS << "RegisterBank " << Bank.getInstanceVarName() << "(/* ID */ " + << QualifiedBankID << ", /* Name */ \"" << Bank.getName() + << "\", /* Size */ " << Size << ", " + << "/* CoveredRegClasses */ " << Bank.getCoverageArrayName() + << ", /* NumRegClasses */ " + << RegisterClassHierarchy.getRegClasses().size() << ");\n"; + } + OS << "} // end namespace " << TargetName << "\n" + << "\n"; + + OS << "RegisterBank *" << TargetName + << "GenRegisterBankInfo::RegBanks[] = {\n"; + for (const auto &Bank : Banks) + OS << " &" << TargetName << "::" << Bank.getInstanceVarName() << ",\n"; + OS << "};\n\n"; + + OS << TargetName << "GenRegisterBankInfo::" << TargetName + << "GenRegisterBankInfo()\n" + << " : RegisterBankInfo(RegBanks, " << TargetName + << "::NumRegisterBanks) {\n" + << " // Assert that RegBank indices match their ID's\n" + << " unsigned Index = 0;\n" + << "#ifndef NDEBUG\n" + << " for (const auto &RB : RegBanks)\n" + << " assert(Index++ == RB->getID() && \"Index != ID\");\n" + << "#endif // NDEBUG\n" + << "}\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: llvm/trunk/utils/TableGen/TableGen.cpp =================================================================== --- llvm/trunk/utils/TableGen/TableGen.cpp +++ llvm/trunk/utils/TableGen/TableGen.cpp @@ -46,6 +46,7 @@ GenAttributes, GenSearchableTables, GenGlobalISel, + GenRegisterBank, }; namespace { @@ -94,7 +95,9 @@ clEnumValN(GenSearchableTables, "gen-searchable-tables", "Generate generic binary-searchable table"), clEnumValN(GenGlobalISel, "gen-global-isel", - "Generate GlobalISel selector"))); + "Generate GlobalISel selector"), + clEnumValN(GenRegisterBank, "gen-register-bank", + "Generate registers bank descriptions"))); cl::opt Class("class", cl::desc("Print Enum list for this class"), @@ -182,6 +185,8 @@ break; case GenGlobalISel: EmitGlobalISel(Records, OS); + case GenRegisterBank: + EmitRegisterBank(Records, OS); break; } Index: llvm/trunk/utils/TableGen/TableGenBackends.h =================================================================== --- llvm/trunk/utils/TableGen/TableGenBackends.h +++ llvm/trunk/utils/TableGen/TableGenBackends.h @@ -81,6 +81,7 @@ void EmitAttributes(RecordKeeper &RK, raw_ostream &OS); void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS); void EmitGlobalISel(RecordKeeper &RK, raw_ostream &OS); +void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace