From 845d2c0c776abce551d16f7b1b7dc1f4d4df1a27 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 5 Oct 2011 00:35:49 +0000 Subject: [PATCH] Add TRI::getSubClassWithSubReg(RC, Idx) function. This function is used to constrain a register class to a sub-class that supports the given sub-register index. For example, getSubClassWithSubReg(GR32, sub_8bit) -> GR32_ABCD. The function will be used to compute register classes when emitting INSERT_SUBREG and EXTRACT_SUBREG nodes and for register class inflation of sub-register operations. The version provided by TableGen is usually adequate, but targets can override. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141142 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetRegisterInfo.h | 14 +++++++++ utils/TableGen/CodeGenRegisters.cpp | 20 ++++++++---- utils/TableGen/CodeGenRegisters.h | 13 ++++++++ utils/TableGen/RegisterInfoEmitter.cpp | 40 ++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 6 deletions(-) diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index bf9174cbc67..f77aa546c12 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -429,6 +429,20 @@ public: return 0; } + /// getSubClassWithSubReg - Returns the largest legal sub-class of RC that + /// supports the sub-register index Idx. + /// If no such sub-class exists, return NULL. + /// If all registers in RC already have an Idx sub-register, return RC. + /// + /// TableGen generates a version of this function that is good enough in most + /// cases. Targets can override if they have constraints that TableGen + /// doesn't understand. For example, the x86 sub_8bit sub-register index is + /// supported by the full GR32 register class in 64-bit mode, but only by the + /// GR32_ABCD regiister class in 32-bit mode. + /// + virtual const TargetRegisterClass * + getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx) const =0; + /// composeSubRegIndices - Return the subregister index you get from composing /// two subregister indices. /// diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index b7315446163..8de46152795 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -768,23 +768,31 @@ void CodeGenRegBank::computeInferredRegisterClasses() { // Find matching classes for all SRSets entries. Iterate in SubRegIndex // numerical order to visit synthetic indices last. for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - SubReg2SetMap::const_iterator I = SRSets.find(SubRegIndices[sri]); + Record *SubIdx = SubRegIndices[sri]; + SubReg2SetMap::const_iterator I = SRSets.find(SubIdx); // Unsupported SubRegIndex. Skip it. if (I == SRSets.end()) continue; - // In most cases, all RC registers support the SubRegIndex. Skip those. - if (I->second.size() == RC.getMembers().size()) + // In most cases, all RC registers support the SubRegIndex. + if (I->second.size() == RC.getMembers().size()) { + RC.setSubClassWithSubReg(SubIdx, &RC); continue; + } // This is a real subset. See if we have a matching class. CodeGenRegisterClass::Key K(&I->second, RC.SpillSize, RC.SpillAlignment); RCKeyMap::const_iterator FoundI = Key2RC.find(K); - if (FoundI != Key2RC.end()) + if (FoundI != Key2RC.end()) { + RC.setSubClassWithSubReg(SubIdx, FoundI->second); continue; + } // Class doesn't exist. - addToMaps(new CodeGenRegisterClass(RC.getName() + "_with_" + - I->first->getName(), K)); + CodeGenRegisterClass *NewRC = + new CodeGenRegisterClass(RC.getName() + "_with_" + + I->first->getName(), K); + addToMaps(NewRC); + RC.setSubClassWithSubReg(SubIdx, NewRC); } } } diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 72c8ac05025..ab3e68efc24 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -101,6 +101,9 @@ namespace llvm { // super-class. void inheritProperties(CodeGenRegBank&); + // Map SubRegIndex -> sub-class + DenseMap SubClassWithSubReg; + public: unsigned EnumValue; std::string Namespace; @@ -145,6 +148,16 @@ namespace llvm { return SubClasses.test(RC->EnumValue); } + // getSubClassWithSubReg - Returns the largest sub-class where all + // registers have a SubIdx sub-register. + CodeGenRegisterClass *getSubClassWithSubReg(Record *SubIdx) const { + return SubClassWithSubReg.lookup(SubIdx); + } + + void setSubClassWithSubReg(Record *SubIdx, CodeGenRegisterClass *SubRC) { + SubClassWithSubReg[SubIdx] = SubRC; + } + // getSubClasses - Returns a constant BitVector of subclasses indexed by // EnumValue. // The SubClasses vector includs an entry for this class. diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index f2cc36d371e..a66a78cf918 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -426,6 +426,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, << " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n" << " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n" << " unsigned composeSubRegIndices(unsigned, unsigned) const;\n" + << " const TargetRegisterClass *" + "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n" << "};\n\n"; const std::vector &SubRegIndices = RegBank.getSubRegIndices(); @@ -802,6 +804,44 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << " }\n}\n\n"; + // Emit getSubClassWithSubReg. + OS << "const TargetRegisterClass *" << ClassName + << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)" + " const {\n"; + if (SubRegIndices.empty()) { + OS << " assert(Idx == 0 && \"Target has no sub-registers\");\n" + << " return RC;\n"; + } else { + // Use the smallest type that can hold a regclass ID with room for a + // sentinel. + if (RegisterClasses.size() < UINT8_MAX) + OS << " static const uint8_t Table["; + else if (RegisterClasses.size() < UINT16_MAX) + OS << " static const uint16_t Table["; + else + throw "Too many register classes."; + OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n"; + for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { + const CodeGenRegisterClass &RC = *RegisterClasses[rci]; + OS << " {\t// " << RC.getName() << "\n"; + for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { + Record *Idx = SubRegIndices[sri]; + 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 assert(RC && \"Missing regclass\");\n" + << " if (!Idx) return RC;\n --Idx;\n" + << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" + << " unsigned TV = Table[RC->getID()][Idx];\n" + << " return TV ? getRegClass(TV - 1) : 0;\n"; + } + OS << "}\n\n"; + // Emit the constructor of the class... OS << "extern MCRegisterDesc " << TargetName << "RegDesc[];\n";