Skip to content

Commit

Permalink
[TableGen][GlobalISel] Account for HwMode in RegisterBank register sizes
Browse files Browse the repository at this point in the history
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
  • Loading branch information
lewis-revill committed Mar 18, 2020
1 parent e225e77 commit e9f22fd
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 33 deletions.
13 changes: 9 additions & 4 deletions llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h
Expand Up @@ -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.
Expand All @@ -51,7 +56,7 @@ class RegisterBank {
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;
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
Expand Up @@ -415,7 +415,8 @@ class RegisterBankInfo {

/// 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
Expand Down
8 changes: 5 additions & 3 deletions llvm/lib/CodeGen/GlobalISel/RegisterBank.cpp
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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();
}
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp
Expand Up @@ -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");
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/RISCV/RISCVRegisterBankInfo.cpp
Expand Up @@ -22,5 +22,5 @@

using namespace llvm;

RISCVRegisterBankInfo::RISCVRegisterBankInfo(const TargetRegisterInfo &TRI)
: RISCVGenRegisterBankInfo() {}
RISCVRegisterBankInfo::RISCVRegisterBankInfo(unsigned HwMode)
: RISCVGenRegisterBankInfo(HwMode) {}
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/RISCVRegisterBankInfo.h
Expand Up @@ -31,7 +31,7 @@ class RISCVGenRegisterBankInfo : public RegisterBankInfo {
/// 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
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/RISCVSubtarget.cpp
Expand Up @@ -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));
Expand Down
64 changes: 44 additions & 20 deletions llvm/utils/TableGen/RegisterBankEmitter.cpp
Expand Up @@ -37,12 +37,12 @@ class RegisterBank {
/// 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"); }
Expand All @@ -54,6 +54,10 @@ class RegisterBank {
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(); }

Expand Down Expand Up @@ -83,18 +87,20 @@ class RegisterBank {
// 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>
Expand Down Expand Up @@ -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";
}

Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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";
Expand All @@ -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"
Expand All @@ -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)) {
Expand Down

0 comments on commit e9f22fd

Please sign in to comment.