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.

llvm-svn: 167190
This commit is contained in:
Jakob Stoklund Olesen 2012-11-01 00:32:10 +00:00
parent 17a434c0ae
commit 4498c89d5f
2 changed files with 115 additions and 29 deletions

View File

@ -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

View File

@ -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<CodeGenSubRegIndex*> &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<CodeGenSubRegIndex*> 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<unsigned, 4> RowMap;
SmallVector<SmallVector<CodeGenSubRegIndex*, 4>, 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()) {