Index: include/llvm/CodeGen/GlobalISel/RegisterBank.h =================================================================== --- include/llvm/CodeGen/GlobalISel/RegisterBank.h +++ include/llvm/CodeGen/GlobalISel/RegisterBank.h @@ -27,10 +27,15 @@ /// Two instances of RegisterBank must have different ID. /// This property is enforced by the RegisterBankInfo class. class RegisterBank { +public: + typedef struct { + unsigned Size; + } DataTy; + private: unsigned ID; const char *Name; - unsigned Size; + DataTy Data; BitVector ContainedRegClasses; /// Sentinel value used to recognize register bank not properly @@ -55,7 +60,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 Data.Size; } /// Check whether this instance is ready to be used. bool isValid() const; Index: include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h =================================================================== --- include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -406,23 +406,8 @@ /// \pre \p ID < NumRegBanks. void createRegisterBank(unsigned ID, const char *Name); - /// Add \p RCId to the set of register class that the register bank, - /// identified \p ID, covers. - /// This method transitively adds all the sub classes and the subreg-classes - /// of \p RCId to the set of covered register classes. - /// It also adjusts the size of the register bank to reflect the maximal - /// size of a value that can be hold into that register bank. - /// - /// \note This method does *not* add the super classes of \p RCId. - /// The rationale is if \p ID covers the registers of \p RCId, that - /// does not necessarily mean that \p ID covers the set of registers - /// of RCId's superclasses. - /// This method does *not* add the superreg classes as well for consistents. - /// The expected use is to add the coverage top-down with respect to the - /// register hierarchy. - /// - /// \todo TableGen should just generate the BitSet vector for us. - void addRegBankCoverage(unsigned ID, unsigned RCId, + void setRegBankData(unsigned ID, const RegisterBank::DataTy &Data); + void setRegBankCoverage(unsigned ID, uint64_t CoveredClasses, const TargetRegisterInfo &TRI); /// Get the register bank identified by \p ID. Index: lib/CodeGen/GlobalISel/RegisterBank.cpp =================================================================== --- lib/CodeGen/GlobalISel/RegisterBank.cpp +++ lib/CodeGen/GlobalISel/RegisterBank.cpp @@ -19,7 +19,7 @@ const unsigned RegisterBank::InvalidID = UINT_MAX; -RegisterBank::RegisterBank() : ID(InvalidID), Name(nullptr), Size(0) {} +RegisterBank::RegisterBank() : ID(InvalidID), Name(nullptr), Data() {} bool RegisterBank::verify(const TargetRegisterInfo &TRI) const { assert(isValid() && "Invalid register bank"); @@ -58,7 +58,7 @@ } bool RegisterBank::isValid() const { - return ID != InvalidID && Name != nullptr && Size != 0 && + return ID != InvalidID && Name != nullptr && getSize() != 0 && // A register bank that does not cover anything is useless. !ContainedRegClasses.empty(); } Index: lib/CodeGen/GlobalISel/RegisterBankInfo.cpp =================================================================== --- lib/CodeGen/GlobalISel/RegisterBankInfo.cpp +++ lib/CodeGen/GlobalISel/RegisterBankInfo.cpp @@ -90,97 +90,18 @@ RegBank.Name = Name; } -void RegisterBankInfo::addRegBankCoverage(unsigned ID, unsigned RCId, +void RegisterBankInfo::setRegBankData(unsigned ID, const RegisterBank::DataTy &Data) { + RegisterBank &RB = getRegBank(ID); + RB.Data = Data; +} + +void RegisterBankInfo::setRegBankCoverage(unsigned ID, uint64_t CoveredClasses, const TargetRegisterInfo &TRI) { + uint32_t Mask[] = {(uint32_t)CoveredClasses, + (uint32_t)(CoveredClasses >> 32)}; RegisterBank &RB = getRegBank(ID); - unsigned NbOfRegClasses = TRI.getNumRegClasses(); - - DEBUG(dbgs() << "Add coverage for: " << RB << '\n'); - - // Check if RB is underconstruction. - if (!RB.isValid()) - RB.ContainedRegClasses.resize(NbOfRegClasses); - else if (RB.covers(*TRI.getRegClass(RCId))) - // If RB already covers this register class, there is nothing - // to do. - return; - - BitVector &Covered = RB.ContainedRegClasses; - SmallVector WorkList; - - WorkList.push_back(RCId); - Covered.set(RCId); - - unsigned &MaxSize = RB.Size; - do { - unsigned RCId = WorkList.pop_back_val(); - - const TargetRegisterClass &CurRC = *TRI.getRegClass(RCId); - - DEBUG(dbgs() << "Examine: " << TRI.getRegClassName(&CurRC) - << "(Size*8: " << (CurRC.getSize() * 8) << ")\n"); - - // Remember the biggest size in bits. - MaxSize = std::max(MaxSize, CurRC.getSize() * 8); - - // Walk through all sub register classes and push them into the worklist. - bool First = true; - for (BitMaskClassIterator It(CurRC.getSubClassMask(), TRI); It.isValid(); - ++It) { - unsigned SubRCId = It.getID(); - if (!Covered.test(SubRCId)) { - if (First) - DEBUG(dbgs() << " Enqueue sub-class: "); - DEBUG(dbgs() << TRI.getRegClassName(TRI.getRegClass(SubRCId)) << ", "); - WorkList.push_back(SubRCId); - // Remember that we saw the sub class. - Covered.set(SubRCId); - First = false; - } - } - if (!First) - DEBUG(dbgs() << '\n'); - - // Push also all the register classes that can be accessed via a - // subreg index, i.e., its subreg-class (which is different than - // its subclass). - // - // Note: It would probably be faster to go the other way around - // and have this method add only super classes, since this - // information is available in a more efficient way. However, it - // feels less natural for the client of this APIs plus we will - // TableGen the whole bitset at some point, so compile time for - // the initialization is not very important. - First = true; - for (unsigned SubRCId = 0; SubRCId < NbOfRegClasses; ++SubRCId) { - if (Covered.test(SubRCId)) - continue; - bool Pushed = false; - const TargetRegisterClass *SubRC = TRI.getRegClass(SubRCId); - for (SuperRegClassIterator SuperRCIt(SubRC, &TRI); SuperRCIt.isValid(); - ++SuperRCIt) { - if (Pushed) - break; - for (BitMaskClassIterator It(SuperRCIt.getMask(), TRI); It.isValid(); - ++It) { - unsigned SuperRCId = It.getID(); - if (SuperRCId == RCId) { - if (First) - DEBUG(dbgs() << " Enqueue subreg-class: "); - DEBUG(dbgs() << TRI.getRegClassName(SubRC) << ", "); - WorkList.push_back(SubRCId); - // Remember that we saw the sub class. - Covered.set(SubRCId); - Pushed = true; - First = false; - break; - } - } - } - } - if (!First) - DEBUG(dbgs() << '\n'); - } while (!WorkList.empty()); + RB.ContainedRegClasses.resize(TRI.getNumRegClasses()); + RB.ContainedRegClasses.setBitsInMask(Mask); } const RegisterBank * Index: lib/Target/AArch64/AArch64RegisterBankInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64RegisterBankInfo.cpp +++ lib/Target/AArch64/AArch64RegisterBankInfo.cpp @@ -30,6 +30,10 @@ #error "You shouldn't build this" #endif +const RegisterBank::DataTy GPRData = {64}; +const RegisterBank::DataTy FPRData = {512}; +const RegisterBank::DataTy CCRData = {32}; + AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo &TRI) : RegisterBankInfo(AArch64::RegBanks, AArch64::NumRegisterBanks) { static bool AlreadyInit = false; @@ -45,7 +49,20 @@ createRegisterBank(AArch64::GPRRegBankID, "GPR"); // The GPR register bank is fully defined by all the registers in // GR64all + its subclasses. - addRegBankCoverage(AArch64::GPRRegBankID, AArch64::GPR64allRegClassID, TRI); + setRegBankData(AArch64::GPRRegBankID, GPRData); + setRegBankCoverage(AArch64::GPRRegBankID, + (1ull << AArch64::GPR32allRegClassID) | + (1ull << AArch64::GPR32RegClassID) | + (1ull << AArch64::GPR32spRegClassID) | + (1ull << AArch64::GPR32commonRegClassID) | + (1ull << AArch64::GPR32sponlyRegClassID) | + (1ull << AArch64::GPR64allRegClassID) | + (1ull << AArch64::GPR64RegClassID) | + (1ull << AArch64::GPR64spRegClassID) | + (1ull << AArch64::GPR64commonRegClassID) | + (1ull << AArch64::tcGPR64RegClassID) | + (1ull << AArch64::GPR64sponlyRegClassID), + TRI); const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID); (void)RBGPR; assert(&AArch64::GPRRegBank == &RBGPR && @@ -58,7 +75,46 @@ createRegisterBank(AArch64::FPRRegBankID, "FPR"); // The FPR register bank is fully defined by all the registers in // GR64all + its subclasses. - addRegBankCoverage(AArch64::FPRRegBankID, AArch64::QQQQRegClassID, TRI); + setRegBankData(AArch64::FPRRegBankID, FPRData); + setRegBankCoverage( + AArch64::FPRRegBankID, + (1ull << AArch64::FPR8RegClassID) | (1ull << AArch64::FPR16RegClassID) | + (1ull << AArch64::FPR32RegClassID) | (1ull << AArch64::FPR64RegClassID) | + (1ull << AArch64::DDRegClassID) | (1ull << AArch64::FPR128RegClassID) | + (1ull << AArch64::FPR128_loRegClassID) | (1ull << AArch64::DDDRegClassID) | + (1ull << AArch64::DDDDRegClassID) | (1ull << AArch64::QQRegClassID) | + (1ull << AArch64::QQ_with_qsub0_in_FPR128_loRegClassID) | + (1ull << AArch64::QQ_with_qsub1_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQ_with_qsub0_in_FPR128_lo_and_QQ_with_qsub1_in_FPR128_loRegClassID) | + (1ull << AArch64::QQQRegClassID) | + (1ull << AArch64::QQQ_with_qsub0_in_FPR128_loRegClassID) | + (1ull << AArch64::QQQ_with_qsub1_in_FPR128_loRegClassID) | + (1ull << AArch64::QQQ_with_qsub2_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQQ_with_qsub0_in_FPR128_lo_and_QQQ_with_qsub1_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQQ_with_qsub1_in_FPR128_lo_and_QQQ_with_qsub2_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQQ_with_qsub0_in_FPR128_lo_and_QQQ_with_qsub2_in_FPR128_loRegClassID) | + (1ull << AArch64::QQQQRegClassID) | + (1ull << AArch64::QQQQ_with_qsub0_in_FPR128_loRegClassID) | + (1ull << AArch64::QQQQ_with_qsub1_in_FPR128_loRegClassID) | + (1ull << AArch64::QQQQ_with_qsub2_in_FPR128_loRegClassID) | + (1ull << AArch64::QQQQ_with_qsub3_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQQQ_with_qsub0_in_FPR128_lo_and_QQQQ_with_qsub1_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQQQ_with_qsub1_in_FPR128_lo_and_QQQQ_with_qsub2_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQQQ_with_qsub2_in_FPR128_lo_and_QQQQ_with_qsub3_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQQQ_with_qsub0_in_FPR128_lo_and_QQQQ_with_qsub2_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQQQ_with_qsub1_in_FPR128_lo_and_QQQQ_with_qsub3_in_FPR128_loRegClassID) | + (1ull << AArch64:: + QQQQ_with_qsub0_in_FPR128_lo_and_QQQQ_with_qsub3_in_FPR128_loRegClassID), + TRI); const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID); (void)RBFPR; assert(&AArch64::FPRRegBank == &RBFPR && @@ -72,7 +128,9 @@ // Initialize the CCR bank. createRegisterBank(AArch64::CCRRegBankID, "CCR"); - addRegBankCoverage(AArch64::CCRRegBankID, AArch64::CCRRegClassID, TRI); + setRegBankData(AArch64::CCRRegBankID, CCRData); + setRegBankCoverage(AArch64::CCRRegBankID, 1ull << AArch64::CCRRegClassID, + TRI); const RegisterBank &RBCCR = getRegBank(AArch64::CCRRegBankID); (void)RBCCR; assert(&AArch64::CCRRegBank == &RBCCR &&