/// 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(RegisterBank **RegBanks, unsigned NumRegBanks);
/// This constructor is meaningless.
llvm_unreachable("This constructor should not be executed");
}
- /// 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 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,
- const TargetRegisterInfo &TRI);
+ void setRegBankData(unsigned ID, const char *Name, unsigned Size,
+ const uint32_t *CoveredClasses);
/// Get the register bank identified by \p ID.
RegisterBank &getRegBank(unsigned ID) {
bool RegisterBank::verify(const TargetRegisterInfo &TRI) const {
assert(isValid() && "Invalid register bank");
- assert(ContainedRegClasses.size() == TRI.getNumRegClasses() &&
- "TRI does not match the initialization process?");
for (unsigned RCId = 0, End = TRI.getNumRegClasses(); RCId != End; ++RCId) {
const TargetRegisterClass &RC = *TRI.getRegClass(RCId);
return true;
}
-void RegisterBankInfo::createRegisterBank(unsigned ID, const char *Name) {
- DEBUG(dbgs() << "Create register bank: " << ID << " with name \"" << Name
- << "\"\n");
- 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, unsigned RCId,
- const TargetRegisterInfo &TRI) {
+void RegisterBankInfo::setRegBankData(unsigned ID, const char *Name,
+ unsigned Size,
+ const uint32_t *CoveredClasses) {
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<unsigned, 8> 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.ID = ID;
+ RB.Name = Name;
+ RB.Size = Size;
+ RB.ContainedRegClasses.resize(200);
+ RB.ContainedRegClasses.setBitsInMask(CoveredClasses);
}
const RegisterBank *
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;
RegisterBank FPRRegBank;
RegisterBank CCRRegBank;
if (AlreadyInit)
return;
AlreadyInit = true;
- // Initialize the GPR bank.
- 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, "GPR", 64, AArch64::GPRCoverageData);
const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID);
(void)RBGPR;
assert(&AArch64::GPRRegBank == &RBGPR &&
"Subclass not added?");
assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
- // Initialize the FPR bank.
- 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, "FPR", 512, AArch64::FPRCoverageData);
+
const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID);
(void)RBFPR;
assert(&AArch64::FPRRegBank == &RBFPR &&
"FPRs should hold up to 512-bit via QQQQ sequence");
// Initialize the CCR bank.
- createRegisterBank(AArch64::CCRRegBankID, "CCR");
- addRegBankCoverage(AArch64::CCRRegBankID, AArch64::CCRRegClassID, TRI);
+ setRegBankData(AArch64::CCRRegBankID, "CCR", 32, AArch64::CCRCoverageData);
const RegisterBank &RBCCR = getRegBank(AArch64::CCRRegBankID);
(void)RBCCR;
assert(&AArch64::CCRRegBank == &RBCCR &&
// into an ARMGenRegisterBankInfo.def (similar to AArch64).
namespace llvm {
namespace ARM {
+const uint32_t GPRCoverageData[] = {
+ // Classes 0-31
+ (1u << ARM::GPRRegClassID) | (1u << ARM::GPRwithAPSRRegClassID) |
+ (1u << ARM::GPRnopcRegClassID) | (1u << ARM::rGPRRegClassID) |
+ (1u << ARM::hGPRRegClassID) | (1u << ARM::tGPRRegClassID) |
+ (1u << ARM::GPRnopc_and_hGPRRegClassID) |
+ (1u << ARM::hGPR_and_rGPRRegClassID) | (1u << ARM::tcGPRRegClassID) |
+ (1u << ARM::tGPR_and_tcGPRRegClassID) | (1u << ARM::GPRspRegClassID) |
+ (1u << ARM::hGPR_and_tcGPRRegClassID),
+ // Classes 32-63
+ 0,
+ // Classes 64-96
+ 0,
+ // FIXME: Some of 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 97-128
+ 0,
+ // Classes 129-160
+ 0,
+ // Classes 161-192
+ 0,
+ // Classes 193-224
+ 0,
+};
+
RegisterBank GPRRegBank;
RegisterBank *RegBanks[] = {&GPRRegBank};
AlreadyInit = true;
// Initialize the GPR bank.
- createRegisterBank(ARM::GPRRegBankID, "GPRB");
-
- addRegBankCoverage(ARM::GPRRegBankID, ARM::GPRRegClassID, TRI);
- addRegBankCoverage(ARM::GPRRegBankID, ARM::GPRwithAPSRRegClassID, TRI);
+ setRegBankData(ARM::GPRRegBankID, "GPRB", 32, ARM::GPRCoverageData);
const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
(void)RBGPR;
assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");