forked from OSchip/llvm-project
[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:
parent
e225e770f7
commit
e9f22fd429
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -22,5 +22,5 @@
|
|||
|
||||
using namespace llvm;
|
||||
|
||||
RISCVRegisterBankInfo::RISCVRegisterBankInfo(const TargetRegisterInfo &TRI)
|
||||
: RISCVGenRegisterBankInfo() {}
|
||||
RISCVRegisterBankInfo::RISCVRegisterBankInfo(unsigned HwMode)
|
||||
: RISCVGenRegisterBankInfo(HwMode) {}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)) {
|
||||
|
|
Loading…
Reference in New Issue