[TableGen][GlobalISel] Account for HwMode in RegisterBank register sizes

This patch generates TableGen descriptions for the specified register
banks which contain a list of register sizes corresponding to the
available HwModes. The appropriate size is used during codegen according
to the current HwMode. As this HwMode was not available on generation,
it is set upon construction of the RegisterBankInfo class. Targets
simply need to provide the HwMode argument to the
<target>GenRegisterBankInfo constructor.

The RISC-V RegisterBankInfo constructor has been updated accordingly
(plus an unused argument removed).

Differential Revision: https://reviews.llvm.org/D76007
This commit is contained in:
lewis-revill 2020-03-18 19:50:40 +00:00
parent e225e770f7
commit e9f22fd429
8 changed files with 68 additions and 33 deletions

View File

@ -29,18 +29,23 @@ class RegisterBank {
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 @@ public:
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;

View File

@ -415,7 +415,8 @@ protected:
/// 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

View File

@ -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::covers(const TargetRegisterClass &RC) const {
}
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();
}

View File

@ -56,8 +56,11 @@ const unsigned RegisterBankInfo::InvalidMappingID = UINT_MAX - 1;
// 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");

View File

@ -22,5 +22,5 @@
using namespace llvm;
RISCVRegisterBankInfo::RISCVRegisterBankInfo(const TargetRegisterInfo &TRI)
: RISCVGenRegisterBankInfo() {}
RISCVRegisterBankInfo::RISCVRegisterBankInfo(unsigned HwMode)
: RISCVGenRegisterBankInfo(HwMode) {}

View File

@ -31,7 +31,7 @@ protected:
/// 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

View File

@ -56,7 +56,7 @@ RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
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<const RISCVTargetMachine *>(&TM), *this, *RBI));

View File

@ -37,12 +37,12 @@ private:
/// 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<const CodeGenRegisterClass *> 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 @@ public:
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 @@ public:
// 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<typename RegisterClassesTy::const_iterator>
@ -147,7 +153,7 @@ void RegisterBankEmitter::emitBaseClassDefinition(
OS << "private:\n"
<< " static RegisterBank *RegBanks[];\n\n"
<< "protected:\n"
<< " " << TargetName << "GenRegisterBankInfo();\n"
<< " " << TargetName << "GenRegisterBankInfo(unsigned HwMode = 0);\n"
<< "\n";
}
@ -213,6 +219,7 @@ void RegisterBankEmitter::emitBaseClassImplementation(
raw_ostream &OS, StringRef TargetName,
std::vector<RegisterBank> &Banks) {
const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
const CodeGenHwModes &CGH = Target.getHwModes();
OS << "namespace llvm {\n"
<< "namespace " << TargetName << " {\n";
@ -240,14 +247,30 @@ void RegisterBankEmitter::emitBaseClassImplementation(
}
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 @@ void RegisterBankEmitter::emitBaseClassImplementation(
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::emitBaseClassImplementation(
void RegisterBankEmitter::run(raw_ostream &OS) {
StringRef TargetName = Target.getName();
const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
const CodeGenHwModes &CGH = Target.getHwModes();
std::vector<RegisterBank> Banks;
for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) {
SmallPtrSet<const CodeGenRegisterClass *, 8> VisitedRCs;
RegisterBank Bank(*V);
RegisterBank Bank(*V, CGH.getNumModeIds());
for (const CodeGenRegisterClass *RC :
Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) {