Index: include/llvm/CodeGen/TargetRegisterInfo.h =================================================================== --- include/llvm/CodeGen/TargetRegisterInfo.h +++ include/llvm/CodeGen/TargetRegisterInfo.h @@ -667,8 +667,12 @@ public: /// Register class iterators - regclass_iterator regclass_begin() const { return RegClassBegin; } - regclass_iterator regclass_end() const { return RegClassEnd; } + regclass_iterator regclass_begin() const { + return RegClassBegin + (RegClassEnd - RegClassBegin) * hwMode.get("RegClass"); + } + regclass_iterator regclass_end() const { + return RegClassEnd + (RegClassEnd - RegClassBegin) * hwMode.get("RegClass"); + } iterator_range regclasses() const { return make_range(regclass_begin(), regclass_end()); } @@ -681,7 +685,7 @@ /// See class MCOperandInfo. const TargetRegisterClass *getRegClass(unsigned i) const { assert(i < getNumRegClasses() && "Register Class ID out of range"); - return RegClassBegin[i]; + return RegClassBegin[getNumRegClasses() * hwMode.get("RegClass") + i]; } /// Returns the name of the register class. Index: include/llvm/MC/MCRegisterInfo.h =================================================================== --- include/llvm/MC/MCRegisterInfo.h +++ include/llvm/MC/MCRegisterInfo.h @@ -431,8 +431,12 @@ /// number. int getCodeViewRegNum(unsigned RegNum) const; - regclass_iterator regclass_begin() const { return Classes; } - regclass_iterator regclass_end() const { return Classes+NumClasses; } + regclass_iterator regclass_begin() const { + return NumClasses * hwMode.get("RegClass") + Classes; + } + regclass_iterator regclass_end() const { + return NumClasses * hwMode.get("RegClass") + Classes + NumClasses; + } iterator_range regclasses() const { return make_range(regclass_begin(), regclass_end()); } @@ -445,7 +449,7 @@ /// value. See class MCOperandInfo. const MCRegisterClass& getRegClass(unsigned i) const { assert(i < getNumRegClasses() && "Register Class ID out of range"); - return Classes[i]; + return Classes[NumClasses * hwMode.get("RegClass") + i]; } const char *getRegClassName(const MCRegisterClass *Class) const { Index: include/llvm/Target/Target.td =================================================================== --- include/llvm/Target/Target.td +++ include/llvm/Target/Target.td @@ -287,6 +287,14 @@ string DiagnosticString = ""; } +// This class provides a choice to switch RegisterClass in runtime depending +// on active HwMode. Useful for instructions which exist on 32/64bit platform +// where they differ by RegisterClass. Reduces the ammount of code in TableGen. +class RegisterClassByHwMode Ms = [], list Ts = []> + : HwModeSelect { + list Objects = Ts; +} + // The memberList in a RegisterClass is a dag of set operations. TableGen // evaluates these set operations and expand them into register lists. These // are the most common operation, see test/TableGen/SetTheory.td for more Index: utils/TableGen/InfoByHwMode.h =================================================================== --- utils/TableGen/InfoByHwMode.h +++ utils/TableGen/InfoByHwMode.h @@ -16,7 +16,10 @@ #define LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H #include "CodeGenHwModes.h" +#include "CodeGenRegisters.h" +#include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineValueType.h" +#include "llvm/TableGen/Record.h" #include #include @@ -26,6 +29,8 @@ namespace llvm { struct CodeGenHwModes; +struct CodeGenRegBank; +struct CodeGenRegisterClass; class Record; class raw_ostream; @@ -173,6 +178,11 @@ void writeToStream(raw_ostream &OS) const; }; +struct RegClassByHwMode : public InfoByHwMode { + RegClassByHwMode(Record *R, const CodeGenHwModes &CGH, + const CodeGenRegBank &RegBank); +}; + raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T); Index: utils/TableGen/InfoByHwMode.cpp =================================================================== --- utils/TableGen/InfoByHwMode.cpp +++ utils/TableGen/InfoByHwMode.cpp @@ -188,6 +188,22 @@ OS << '}'; } +RegClassByHwMode::RegClassByHwMode(Record *R, const CodeGenHwModes &CGH, + const CodeGenRegBank &RegBank) { + const HwModeSelect &MS = CGH.getHwModeSelect(R); + const auto &RegisterClasses = RegBank.getRegClasses(); + + for (const HwModeSelect::PairType &P : MS.Items) { + for (const auto &RC : RegisterClasses) { + if (RC.getName() == P.second->getName()) { + auto I = Map.insert({P.first, &RC}); + assert(I.second && "Duplicate entry?"); + (void)I; + } + } + } +} + namespace llvm { raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T) { T.writeToStream(OS); Index: utils/TableGen/RegisterInfoEmitter.cpp =================================================================== --- utils/TableGen/RegisterInfoEmitter.cpp +++ utils/TableGen/RegisterInfoEmitter.cpp @@ -1033,18 +1033,37 @@ OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; - for (const auto &RC : RegisterClasses) { - assert(isInt<8>(RC.CopyCost) && "Copy cost too large."); - uint32_t RegSize = 0; - if (RC.RSI.isSimple()) - RegSize = RC.RSI.getSimple().RegSize; - OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, " - << RegClassStrings.get(RC.getName()) << ", " - << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " - << RC.getQualifiedName() + "RegClassID" << ", " - << RegSize/8 << ", " - << RC.CopyCost << ", " - << ( RC.Allocatable ? "true" : "false" ) << " },\n"; + const CodeGenHwModes &CGH = Target.getHwModes(); + unsigned NumModes = CGH.getNumModeIds("RegClass"); + + for (unsigned M = 0; M < NumModes; ++M) { + OS << " // Mode = " << M << " ("; + if (M == 0) + OS << "Default"; + else + OS << CGH.getMode(M, "RegClass").Name; + OS << ")\n"; + + for (const auto &iRC : RegisterClasses) { + const auto *tmpRC = &iRC; + if (iRC.getDef() && iRC.getDef()->isSubClassOf("RegisterClassByHwMode")) { + RegClassByHwMode regClassByHwMode(iRC.getDef(), CGH, RegBank); + tmpRC = regClassByHwMode.get(M); + } + const auto &RC = *tmpRC; + + assert(isInt<8>(RC.CopyCost) && "Copy cost too large."); + uint32_t RegSize = 0; + if (RC.RSI.isSimple()) + RegSize = RC.RSI.getSimple().RegSize; + OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, " + << RegClassStrings.get(RC.getName()) << ", " + << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " + << RC.getQualifiedName() + "RegClassID" << ", " + << RegSize/8 << ", " + << RC.CopyCost << ", " + << ( RC.Allocatable ? "true" : "false" ) << " },\n"; + } } OS << "};\n\n"; @@ -1386,11 +1405,28 @@ OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n"; } - + NumModes = CGH.getNumModeIds("RegClass"); OS << "\nnamespace {\n"; OS << " const TargetRegisterClass* const RegisterClasses[] = {\n"; - for (const auto &RC : RegisterClasses) - OS << " &" << RC.getQualifiedName() << "RegClass,\n"; + for (unsigned M = 0; M < NumModes; ++M) { + OS << " // Mode = " << M << " ("; + if (M == 0) + OS << "Default"; + else + OS << CGH.getMode(M, "RegClass").Name; + OS << ")\n"; + + for (const auto &iRC : RegisterClasses) { + const auto *tmpRC = &iRC; + if (iRC.getDef() && iRC.getDef()->isSubClassOf("RegisterClassByHwMode")) { + RegClassByHwMode regClassByHwMode(iRC.getDef(), CGH, RegBank); + tmpRC = regClassByHwMode.get(M); + } + const auto &RC = *tmpRC; + + OS << " &" << RC.getQualifiedName() << "RegClass,\n"; + } + } OS << " };\n"; OS << "} // end anonymous namespace\n"; @@ -1425,30 +1461,49 @@ OS << "const TargetRegisterClass *" << ClassName << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)" << " const {\n"; + const CodeGenHwModes &CGH = Target.getHwModes(); + unsigned NumModes = CGH.getNumModeIds("RegClass"); // Use the smallest type that can hold a regclass ID with room for a // sentinel. - if (RegisterClasses.size() < UINT8_MAX) + if (RegisterClasses.size() * NumModes < UINT8_MAX) OS << " static const uint8_t Table["; - else if (RegisterClasses.size() < UINT16_MAX) + else if (RegisterClasses.size() * NumModes < UINT16_MAX) OS << " static const uint16_t Table["; else PrintFatalError("Too many register classes."); - OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; - for (const auto &RC : RegisterClasses) { - OS << " {\t// " << RC.getName() << "\n"; - for (auto &Idx : SubRegIndices) { - if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx)) - OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName() - << " -> " << SRC->getName() << "\n"; - else - OS << " 0,\t// " << Idx.getName() << "\n"; + OS << RegisterClasses.size() * NumModes << "][" << SubRegIndicesSize << "] = {\n"; + for (unsigned M = 0; M < NumModes; ++M) { + OS << " // Mode = " << M << " ("; + if (M == 0) + OS << "Default"; + else + OS << CGH.getMode(M, "RegClass").Name; + OS << ")\n"; + + for (const auto &iRC : RegisterClasses) { + const auto *tmpRC = &iRC; + if (iRC.getDef() && iRC.getDef()->isSubClassOf("RegisterClassByHwMode")) { + RegClassByHwMode regClassByHwMode(iRC.getDef(), CGH, RegBank); + tmpRC = regClassByHwMode.get(M); + } + const auto &RC = *tmpRC; + + OS << " {\t// " << RC.getName() << "\n"; + for (auto &Idx : SubRegIndices) { + if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx)) + OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName() + << " -> " << SRC->getName() << "\n"; + else + OS << " 0,\t// " << Idx.getName() << "\n"; + } + OS << " },\n"; } - OS << " },\n"; } OS << " };\n assert(RC && \"Missing regclass\");\n" << " if (!Idx) return RC;\n --Idx;\n" << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" - << " unsigned TV = Table[RC->getID()][Idx];\n" + << " unsigned TV = Table[" << RegisterClasses.size() + << " * hwMode.get(\"VarReg\") + RC->getID()][Idx];\n" << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; }