diff --git a/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h --- a/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h @@ -29,18 +29,23 @@ private: unsigned ID; const char *Name; - unsigned Size; + const unsigned *Sizes; BitVector ContainedRegClasses; - /// Sentinel value used to recognize register bank not properly + /// HwMode of the target. Not initialized by the constructor, initialized + /// within generated RegisterBankInfo class constructor. + unsigned HwMode; + + /// Sentinel values used to recognize register bank not properly /// initialized yet. static const unsigned InvalidID; + static const unsigned InvalidHwMode; /// Only the RegisterBankInfo can initialize RegisterBank properly. friend RegisterBankInfo; public: - RegisterBank(unsigned ID, const char *Name, unsigned Size, + RegisterBank(unsigned ID, const char *Name, const unsigned *Sizes, const uint32_t *CoveredClasses, unsigned NumRegClasses); /// Get the identifier of this register bank. @@ -51,7 +56,7 @@ const char *getName() const { return Name; } /// Get the maximal size in bits that fits in this register bank. - unsigned getSize() const { return Size; } + unsigned getSize() const { return Sizes[HwMode]; } /// Check whether this instance is ready to be used. bool isValid() const; diff --git a/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h --- a/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -415,7 +415,8 @@ /// Create a RegisterBankInfo that can accommodate up to \p NumRegBanks /// RegisterBank instances. - RegisterBankInfo(RegisterBank **RegBanks, unsigned NumRegBanks); + RegisterBankInfo(RegisterBank **RegBanks, unsigned NumRegBanks, + unsigned HwMode); /// This constructor is meaningless. /// It just provides a default constructor that can be used at link time diff --git a/llvm/lib/CodeGen/GlobalISel/RegisterBank.cpp b/llvm/lib/CodeGen/GlobalISel/RegisterBank.cpp --- a/llvm/lib/CodeGen/GlobalISel/RegisterBank.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegisterBank.cpp @@ -19,11 +19,12 @@ using namespace llvm; const unsigned RegisterBank::InvalidID = UINT_MAX; +const unsigned RegisterBank::InvalidHwMode = UINT_MAX; RegisterBank::RegisterBank( - unsigned ID, const char *Name, unsigned Size, + unsigned ID, const char *Name, const unsigned *Sizes, const uint32_t *CoveredClasses, unsigned NumRegClasses) - : ID(ID), Name(Name), Size(Size) { + : ID(ID), Name(Name), Sizes(Sizes), HwMode(InvalidHwMode) { ContainedRegClasses.resize(NumRegClasses); ContainedRegClasses.setBitsInMask(CoveredClasses); } @@ -63,7 +64,8 @@ } bool RegisterBank::isValid() const { - return ID != InvalidID && Name != nullptr && Size != 0 && + return ID != InvalidID && Name != nullptr && Sizes != nullptr && + HwMode != InvalidID && // A register bank that does not cover anything is useless. !ContainedRegClasses.empty(); } diff --git a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp --- a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp @@ -56,8 +56,11 @@ // RegisterBankInfo implementation. //------------------------------------------------------------------------------ RegisterBankInfo::RegisterBankInfo(RegisterBank **RegBanks, - unsigned NumRegBanks) + unsigned NumRegBanks, unsigned HwMode) : RegBanks(RegBanks), NumRegBanks(NumRegBanks) { + // Initialize HwMode for all RegBanks + for (unsigned Idx = 0, End = getNumRegBanks(); Idx != End; ++Idx) + RegBanks[Idx]->HwMode = HwMode; #ifndef NDEBUG for (unsigned Idx = 0, End = getNumRegBanks(); Idx != End; ++Idx) { assert(RegBanks[Idx] != nullptr && "Invalid RegisterBank"); diff --git a/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.h --- a/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.h +++ b/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.h @@ -31,7 +31,7 @@ /// This class provides the information for the target register banks. class RISCVRegisterBankInfo final : public RISCVGenRegisterBankInfo { public: - RISCVRegisterBankInfo(const TargetRegisterInfo &TRI); + RISCVRegisterBankInfo(unsigned HwMode); }; } // end namespace llvm #endif diff --git a/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.cpp @@ -22,5 +22,5 @@ using namespace llvm; -RISCVRegisterBankInfo::RISCVRegisterBankInfo(const TargetRegisterInfo &TRI) - : RISCVGenRegisterBankInfo() {} +RISCVRegisterBankInfo::RISCVRegisterBankInfo(unsigned HwMode) + : RISCVGenRegisterBankInfo(HwMode) {} diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp --- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp @@ -56,7 +56,7 @@ CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering())); Legalizer.reset(new RISCVLegalizerInfo(*this)); - auto *RBI = new RISCVRegisterBankInfo(*getRegisterInfo()); + auto *RBI = new RISCVRegisterBankInfo(getHwMode()); RegBankInfo.reset(RBI); InstSelector.reset(createRISCVInstructionSelector( *static_cast(&TM), *this, *RBI)); diff --git a/llvm/utils/TableGen/RegisterBankEmitter.cpp b/llvm/utils/TableGen/RegisterBankEmitter.cpp --- a/llvm/utils/TableGen/RegisterBankEmitter.cpp +++ b/llvm/utils/TableGen/RegisterBankEmitter.cpp @@ -37,12 +37,12 @@ /// The register classes that are covered by the register bank. RegisterClassesTy RCs; - /// The register class with the largest register size. - const CodeGenRegisterClass *RCWithLargestRegsSize; + /// The register classes with the largest register size for each HwMode. + std::vector RCsWithLargestRegSize; public: - RegisterBank(const Record &TheDef) - : TheDef(TheDef), RCs(), RCWithLargestRegsSize(nullptr) {} + RegisterBank(const Record &TheDef, unsigned NumModeIds) + : TheDef(TheDef), RCs(), RCsWithLargestRegSize(NumModeIds) {} /// Get the human-readable name for the bank. StringRef getName() const { return TheDef.getValueAsString("Name"); } @@ -54,6 +54,10 @@ return (TheDef.getName() + "CoverageData").str(); } + std::string getSizesArrayName() const { + return (TheDef.getName() + "Sizes").str(); + } + /// Get the name of the global instance variable. StringRef getInstanceVarName() const { return TheDef.getName(); } @@ -83,18 +87,20 @@ // 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->RSI.get(DefaultMode).SpillSize < - RC->RSI.get(DefaultMode).SpillSize) - RCWithLargestRegsSize = RC; - assert(RCWithLargestRegsSize && "RC was nullptr?"); - + unsigned NumModeIds = RCsWithLargestRegSize.size(); + for (unsigned M = 0; M < NumModeIds; ++M) { + if (RCsWithLargestRegSize[M] == nullptr) + RCsWithLargestRegSize[M] = RC; + else if (RCsWithLargestRegSize[M]->RSI.get(M).SpillSize < + RC->RSI.get(M).SpillSize) + RCsWithLargestRegSize[M] = RC; + assert(RCsWithLargestRegSize[M] && "RC was nullptr?"); + } RCs.emplace_back(RC); } - const CodeGenRegisterClass *getRCWithLargestRegsSize() const { - return RCWithLargestRegsSize; + const CodeGenRegisterClass *getRCWithLargestRegsSize(unsigned HwMode) const { + return RCsWithLargestRegSize[HwMode]; } iterator_range @@ -147,7 +153,7 @@ OS << "private:\n" << " static RegisterBank *RegBanks[];\n\n" << "protected:\n" - << " " << TargetName << "GenRegisterBankInfo();\n" + << " " << TargetName << "GenRegisterBankInfo(unsigned HwMode = 0);\n" << "\n"; } @@ -213,6 +219,7 @@ raw_ostream &OS, StringRef TargetName, std::vector &Banks) { const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank(); + const CodeGenHwModes &CGH = Target.getHwModes(); OS << "namespace llvm {\n" << "namespace " << TargetName << " {\n"; @@ -240,14 +247,30 @@ } OS << "\n"; + unsigned NumModeIds = CGH.getNumModeIds(); + for (const auto &Bank : Banks) { + OS << "const unsigned " << Bank.getSizesArrayName() << "[] = {\n"; + for (unsigned M = 0; M < NumModeIds; ++M) { + const CodeGenRegisterClass &RC = *Bank.getRCWithLargestRegsSize(M); + unsigned Size = RC.RSI.get(M).SpillSize; + OS << " // Mode = " << M << " ("; + if (M == 0) + OS << "Default"; + else + OS << CGH.getMode(M).Name; + OS << ")\n"; + OS << " " << Size << ",\n"; + } + OS << "};\n"; + } + OS << "\n"; + for (const auto &Bank : Banks) { std::string QualifiedBankID = (TargetName + "::" + Bank.getEnumeratorName()).str(); - const CodeGenRegisterClass &RC = *Bank.getRCWithLargestRegsSize(); - unsigned Size = RC.RSI.get(DefaultMode).SpillSize; OS << "RegisterBank " << Bank.getInstanceVarName() << "(/* ID */ " << QualifiedBankID << ", /* Name */ \"" << Bank.getName() - << "\", /* Size */ " << Size << ", " + << "\", /* Sizes */ " << Bank.getInstanceVarName() << "Sizes, " << "/* CoveredRegClasses */ " << Bank.getCoverageArrayName() << ", /* NumRegClasses */ " << RegisterClassHierarchy.getRegClasses().size() << ");\n"; @@ -262,9 +285,9 @@ OS << "};\n\n"; OS << TargetName << "GenRegisterBankInfo::" << TargetName - << "GenRegisterBankInfo()\n" + << "GenRegisterBankInfo(unsigned HwMode)\n" << " : RegisterBankInfo(RegBanks, " << TargetName - << "::NumRegisterBanks) {\n" + << "::NumRegisterBanks, HwMode) {\n" << " // Assert that RegBank indices match their ID's\n" << "#ifndef NDEBUG\n" << " unsigned Index = 0;\n" @@ -278,11 +301,12 @@ void RegisterBankEmitter::run(raw_ostream &OS) { StringRef TargetName = Target.getName(); const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank(); + const CodeGenHwModes &CGH = Target.getHwModes(); std::vector Banks; for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) { SmallPtrSet VisitedRCs; - RegisterBank Bank(*V); + RegisterBank Bank(*V, CGH.getNumModeIds()); for (const CodeGenRegisterClass *RC : Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) {