From ad0b3b21e3abea7a9e9918ae1724f7dd7376b2cf Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 1 Nov 2012 00:32:10 +0000 Subject: Generate a table-driven version of TRI::composeSubRegIndices(). Explicitly allow composition of null sub-register indices, and handle that common case in an inlinable stub. Use a compressed table implementation instead of the previous nested switches which generated pretty bad code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167190 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetRegisterInfo.h | 16 +++- utils/TableGen/RegisterInfoEmitter.cpp | 128 ++++++++++++++++++++++++------- 2 files changed, 115 insertions(+), 29 deletions(-) diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 0ccf9f4b63..afa2ee2744 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -476,6 +476,8 @@ public: /// composeSubRegIndices - Return the subregister index you get from composing /// two subregister indices. /// + /// The special null sub-register index composes as the identity. + /// /// If R:a:b is the same register as R:c, then composeSubRegIndices(a, b) /// returns c. Note that composeSubRegIndices does not tell you about illegal /// compositions. If R does not have a subreg a, or R:a does not have a subreg @@ -485,11 +487,19 @@ public: /// ssub_0:S0 - ssub_3:S3 subregs. /// If you compose subreg indices dsub_1, ssub_0 you get ssub_2. /// - virtual unsigned composeSubRegIndices(unsigned a, unsigned b) const { - // This default implementation is correct for most targets. - return b; + unsigned composeSubRegIndices(unsigned a, unsigned b) const { + if (!a) return b; + if (!b) return a; + return composeSubRegIndicesImpl(a, b); } +protected: + /// Overridden by TableGen in targets that have sub-registers. + virtual unsigned composeSubRegIndicesImpl(unsigned, unsigned) const { + llvm_unreachable("Target has no sub-registers"); + } + +public: /// getCommonSuperRegClass - Find a common super-register class if it exists. /// /// Find a register class, SuperRC and two sub-register indices, PreA and diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 273cac0c01..95b6267238 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -62,6 +62,8 @@ private: void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, const std::string &ClassName); + void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank, + const std::string &ClassName); }; } // End anonymous namespace @@ -530,6 +532,102 @@ static void printDiff16(raw_ostream &OS, uint16_t Val) { OS << Val; } +// Try to combine Idx's compose map into Vec if it is compatible. +// Return false if it's not possible. +static bool combine(const CodeGenSubRegIndex *Idx, + SmallVectorImpl &Vec) { + const CodeGenSubRegIndex::CompMap &Map = Idx->getComposites(); + for (CodeGenSubRegIndex::CompMap::const_iterator + I = Map.begin(), E = Map.end(); I != E; ++I) { + CodeGenSubRegIndex *&Entry = Vec[I->first->EnumValue - 1]; + if (Entry && Entry != I->second) + return false; + } + + // All entries are compatible. Make it so. + for (CodeGenSubRegIndex::CompMap::const_iterator + I = Map.begin(), E = Map.end(); I != E; ++I) + Vec[I->first->EnumValue - 1] = I->second; + return true; +} + +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range < 0xFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + +void +RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, + CodeGenRegBank &RegBank, + const std::string &ClName) { + ArrayRef SubRegIndices = RegBank.getSubRegIndices(); + OS << "unsigned " << ClName + << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n"; + + // Many sub-register indexes are composition-compatible, meaning that + // + // compose(IdxA, IdxB) == compose(IdxA', IdxB) + // + // for many IdxA, IdxA' pairs. Not all sub-register indexes can be composed. + // The illegal entries can be use as wildcards to compress the table further. + + // Map each Sub-register index to a compatible table row. + SmallVector RowMap; + SmallVector, 4> Rows; + + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { + unsigned Found = ~0u; + for (unsigned r = 0, re = Rows.size(); r != re; ++r) { + if (combine(SubRegIndices[i], Rows[r])) { + Found = r; + break; + } + } + if (Found == ~0u) { + Found = Rows.size(); + Rows.resize(Found + 1); + Rows.back().resize(SubRegIndices.size()); + combine(SubRegIndices[i], Rows.back()); + } + RowMap.push_back(Found); + } + + // Output the row map if there is multiple rows. + if (Rows.size() > 1) { + OS << " static const " << getMinimalTypeForRange(Rows.size()) + << " RowMap[" << SubRegIndices.size() << "] = {\n "; + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + OS << RowMap[i] << ", "; + OS << "\n };\n"; + } + + // Output the rows. + OS << " static const " << getMinimalTypeForRange(SubRegIndices.size()+1) + << " Rows[" << Rows.size() << "][" << SubRegIndices.size() << "] = {\n"; + for (unsigned r = 0, re = Rows.size(); r != re; ++r) { + OS << " { "; + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + if (Rows[r][i]) + OS << Rows[r][i]->EnumValue << ", "; + else + OS << "0, "; + OS << "},\n"; + } + OS << " };\n\n"; + + OS << " --IdxA; assert(IdxA < " << SubRegIndices.size() << ");\n" + << " --IdxB; assert(IdxB < " << SubRegIndices.size() << ");\n"; + if (Rows.size() > 1) + OS << " return Rows[RowMap[IdxA]][IdxB];\n"; + else + OS << " return Rows[0][IdxB];\n"; + OS << "}\n\n"; +} + // // runMCDesc - Print out MC register descriptions. // @@ -802,7 +900,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, << " virtual bool needsStackRealignment(const MachineFunction &) const\n" << " { return false; }\n"; if (!RegBank.getSubRegIndices().empty()) { - OS << " virtual unsigned composeSubRegIndices(unsigned, unsigned) const;\n" + OS << " virtual unsigned composeSubRegIndicesImpl" + << "(unsigned, unsigned) const;\n" << " virtual const TargetRegisterClass *" "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n"; } @@ -1054,31 +1153,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, std::string ClassName = Target.getName() + "GenRegisterInfo"; - // Emit composeSubRegIndices - if (!SubRegIndices.empty()) { - OS << "unsigned " << ClassName - << "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n" - << " switch (IdxA) {\n" - << " default:\n return IdxB;\n"; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - bool Open = false; - for (unsigned j = 0; j != e; ++j) { - CodeGenSubRegIndex *Comp = SubRegIndices[i]->compose(SubRegIndices[j]); - if (Comp && Comp != SubRegIndices[j]) { - if (!Open) { - OS << " case " << SubRegIndices[i]->getQualifiedName() - << ": switch(IdxB) {\n default: return IdxB;\n"; - Open = true; - } - OS << " case " << SubRegIndices[j]->getQualifiedName() - << ": return " << Comp->getQualifiedName() << ";\n"; - } - } - if (Open) - OS << " }\n"; - } - OS << " }\n}\n\n"; - } + if (!SubRegIndices.empty()) + emitComposeSubRegIndices(OS, RegBank, ClassName); // Emit getSubClassWithSubReg. if (!SubRegIndices.empty()) { -- cgit v1.2.3