diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index 8eaf2fa7384..0930f514c02 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -15,7 +15,7 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H #define LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H -#include +#include // For unique_ptr. namespace llvm { class RegisterBank; @@ -24,20 +24,58 @@ class TargetRegisterInfo; /// Holds all the information related to register banks. class RegisterBankInfo { protected: + /// Hold the set of supported register banks. std::unique_ptr RegBanks; - unsigned NbOfRegBanks; + /// Total number of register banks. + unsigned NumRegBanks; - RegisterBankInfo(unsigned NbOfRegBanks); + /// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks + /// RegisterBank instances. + /// + /// \note For the verify method to succeed all the \p NumRegBanks + /// must be initialized by createRegisterBank and updated with + /// addRegBankCoverage RegisterBank. + RegisterBankInfo(unsigned NumRegBanks); virtual ~RegisterBankInfo(); + /// Create a new register bank with the given parameter and add it + /// to RegBanks. + /// \pre \p ID must not already be used. + /// \pre \p ID < NumRegBanks. + void createRegisterBank(unsigned ID, const char *Name); + + /// Add \p RC to the set of register class that the register bank + /// identified \p ID covers. + /// This method transitively adds all the sub classes of \p RC + /// 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 RC. + /// The rationale is if \p ID covers the registers of \p RC, that + /// does not necessarily mean that \p ID covers the set of registers + /// of RC's superclasses. + /// + /// \todo TableGen should just generate the BitSet vector for us. + void addRegBankCoverage(unsigned ID, const TargetRegisterClass &RC, + const TargetRegisterInfo &TRI); + + /// Get the register bank identified by \p ID. + RegisterBank &getRegBank(unsigned ID) { + assert(ID < getNumRegBanks() && "Accessing an unknown register bank"); + return RegBanks[ID]; + } + public: /// Get the register bank identified by \p ID. const RegisterBank &getRegBank(unsigned ID) const { - assert(ID < NbOfRegBanks && "Accessing an unknown register bank"); - return RegBanks[ID]; + return const_cast(this)->getRegBank(ID); } + /// Get the total number of register banks. + unsigned getNumRegBanks() const { return NumRegBanks; } + /// Get the cost of a copy from \p B to \p A, or put differently, /// get the cost of A = COPY B. virtual unsigned copyCost(const RegisterBank &A, diff --git a/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp b/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp index 1d98c993c81..8c86491ec8a 100644 --- a/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp +++ b/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp @@ -11,18 +11,91 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/GlobalISel/RegisterBank.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" #include "llvm/Target/TargetRegisterInfo.h" +#include // For std::max. + #define DEBUG_TYPE "registerbankinfo" using namespace llvm; -RegisterBankInfo::RegisterBankInfo(unsigned NbOfRegBanks) - : NbOfRegBanks(NbOfRegBanks) { - RegBanks.reset(new RegisterBank[NbOfRegBanks]); +RegisterBankInfo::RegisterBankInfo(unsigned NumRegBanks) + : NumRegBanks(NumRegBanks) { + RegBanks.reset(new RegisterBank[NumRegBanks]); } RegisterBankInfo::~RegisterBankInfo() {} -void RegisterBankInfo::verify(const TargetRegisterInfo &TRI) const {} +void RegisterBankInfo::verify(const TargetRegisterInfo &TRI) const { + for (unsigned Idx = 0, End = getNumRegBanks(); Idx != End; ++Idx) { + const RegisterBank &RegBank = getRegBank(Idx); + assert(Idx == RegBank.getID() && + "ID does not match the index in the array"); + RegBank.verify(TRI); + } +} + +void RegisterBankInfo::createRegisterBank(unsigned ID, const char *Name) { + RegisterBank &RegBank = getRegBank(ID); + assert(RegBank.getID() == RegisterBank::InvalidID && + "A register bank should be created only once"); + RegBank.ID = ID; + RegBank.Name = Name; +} + +void RegisterBankInfo::addRegBankCoverage(unsigned ID, + const TargetRegisterClass &RC, + const TargetRegisterInfo &TRI) { + RegisterBank &RB = getRegBank(ID); + unsigned NbOfRegClasses = TRI.getNumRegClasses(); + // Check if RB is underconstruction. + if (!RB.isValid()) + RB.ContainedRegClasses.resize(NbOfRegClasses); + else if (RB.contains(RC)) + // If RB already contains this register class, there is nothing + // to do. + return; + + BitVector &Covered = RB.ContainedRegClasses; + SmallVector WorkList; + + WorkList.push_back(RC.getID()); + Covered.set(RC.getID()); + + unsigned &MaxSize = RB.Size; + do { + unsigned RCId = WorkList.pop_back_val(); + + const TargetRegisterClass &CurRC = *TRI.getRegClass(RCId); + // 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. + const uint32_t *SubClassMask = CurRC.getSubClassMask(); + // The subclasses mask is broken down into chunks of uint32_t, but it still + // represents all register classes. + for (unsigned Base = 0; Base < NbOfRegClasses; Base += 32) { + unsigned Idx = Base; + for (uint32_t Mask = *SubClassMask++; Mask; Mask >>= 1, ++Idx) { + unsigned Offset = countTrailingZeros(Mask); + unsigned SubRCId = Idx + Offset; + if (!Covered.test(SubRCId)) + WorkList.push_back(SubRCId); + // Remember that we saw the sub class. + Covered.set(SubRCId); + // Move the cursor to the next sub class. + // I.e., eat up the zeros then move to the next bit. + // This last part is done as part of the loop increment. + + // By construction, Offset must be less than 32. + // Otherwise, than means Mask was zero. I.e., no UB. + Mask >>= Offset; + // Remember that we shifted the base offset. + Idx += Offset; + } + } + + } while (!WorkList.empty()); +}