Store sub-class lists as a bit vector.

This uses less memory and it reduces the complexity of sub-class
operations:

- hasSubClassEq() and friends become O(1) instead of O(N).

- getCommonSubClass() becomes O(N) instead of O(N^2).

In the future, TableGen will infer register classes.  This makes it
cheap to add them.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140898 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2011-09-30 22:19:07 +00:00
parent b7359e384f
commit c8e2bb68bb
5 changed files with 43 additions and 94 deletions

View File

@ -40,17 +40,17 @@ public:
private: private:
const MCRegisterClass *MC; const MCRegisterClass *MC;
const vt_iterator VTs; const vt_iterator VTs;
const sc_iterator SubClasses; const unsigned *SubClassMask;
const sc_iterator SuperClasses; const sc_iterator SuperClasses;
const sc_iterator SubRegClasses; const sc_iterator SubRegClasses;
const sc_iterator SuperRegClasses; const sc_iterator SuperRegClasses;
public: public:
TargetRegisterClass(const MCRegisterClass *MC, const EVT *vts, TargetRegisterClass(const MCRegisterClass *MC, const EVT *vts,
const TargetRegisterClass * const *subcs, const unsigned *subcm,
const TargetRegisterClass * const *supcs, const TargetRegisterClass * const *supcs,
const TargetRegisterClass * const *subregcs, const TargetRegisterClass * const *subregcs,
const TargetRegisterClass * const *superregcs) const TargetRegisterClass * const *superregcs)
: MC(MC), VTs(vts), SubClasses(subcs), SuperClasses(supcs), : MC(MC), VTs(vts), SubClassMask(subcm), SuperClasses(supcs),
SubRegClasses(subregcs), SuperRegClasses(superregcs) {} SubRegClasses(subregcs), SuperRegClasses(superregcs) {}
virtual ~TargetRegisterClass() {} // Allow subclasses virtual ~TargetRegisterClass() {} // Allow subclasses
@ -159,59 +159,44 @@ public:
} }
/// hasSubClass - return true if the specified TargetRegisterClass /// hasSubClass - return true if the specified TargetRegisterClass
/// is a proper subset of this TargetRegisterClass. /// is a proper sub-class of this TargetRegisterClass.
bool hasSubClass(const TargetRegisterClass *cs) const { bool hasSubClass(const TargetRegisterClass *RC) const {
for (int i = 0; SubClasses[i] != NULL; ++i) return RC != this && hasSubClassEq(RC);
if (SubClasses[i] == cs)
return true;
return false;
} }
/// hasSubClassEq - Returns true if RC is a subclass of or equal to this /// hasSubClassEq - Returns true if RC is a sub-class of or equal to this
/// class. /// class.
bool hasSubClassEq(const TargetRegisterClass *RC) const { bool hasSubClassEq(const TargetRegisterClass *RC) const {
return RC == this || hasSubClass(RC); unsigned ID = RC->getID();
} return (SubClassMask[ID / 32] >> (ID % 32)) & 1;
/// subclasses_begin / subclasses_end - Loop over all of the classes
/// that are proper subsets of this register class.
sc_iterator subclasses_begin() const {
return SubClasses;
}
sc_iterator subclasses_end() const {
sc_iterator I = SubClasses;
while (*I != NULL) ++I;
return I;
} }
/// hasSuperClass - return true if the specified TargetRegisterClass is a /// hasSuperClass - return true if the specified TargetRegisterClass is a
/// proper superset of this TargetRegisterClass. /// proper super-class of this TargetRegisterClass.
bool hasSuperClass(const TargetRegisterClass *cs) const { bool hasSuperClass(const TargetRegisterClass *RC) const {
for (int i = 0; SuperClasses[i] != NULL; ++i) return RC->hasSubClass(this);
if (SuperClasses[i] == cs)
return true;
return false;
} }
/// hasSuperClassEq - Returns true if RC is a superclass of or equal to this /// hasSuperClassEq - Returns true if RC is a super-class of or equal to this
/// class. /// class.
bool hasSuperClassEq(const TargetRegisterClass *RC) const { bool hasSuperClassEq(const TargetRegisterClass *RC) const {
return RC == this || hasSuperClass(RC); return RC->hasSubClassEq(this);
} }
/// superclasses_begin / superclasses_end - Loop over all of the classes /// getSubClassMask - Returns a bit vector of subclasses, including this one.
/// that are proper supersets of this register class. /// The vector is indexed by class IDs, see hasSubClassEq() above for how to
sc_iterator superclasses_begin() const { /// use it.
const unsigned *getSubClassMask() const {
return SubClassMask;
}
/// getSuperClasses - Returns a NULL terminated list of super-classes. The
/// classes are ordered by ID which is also a topological ordering from large
/// to small classes. The list does NOT include the current class.
sc_iterator getSuperClasses() const {
return SuperClasses; return SuperClasses;
} }
sc_iterator superclasses_end() const {
sc_iterator I = SuperClasses;
while (*I != NULL) ++I;
return I;
}
/// isASubClass - return true if this TargetRegisterClass is a subset /// isASubClass - return true if this TargetRegisterClass is a subset
/// class of at least one other TargetRegisterClass. /// class of at least one other TargetRegisterClass.
bool isASubClass() const { bool isASubClass() const {

View File

@ -353,7 +353,7 @@ const TargetRegisterClass*
ARMBaseRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) ARMBaseRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC)
const { const {
const TargetRegisterClass *Super = RC; const TargetRegisterClass *Super = RC;
TargetRegisterClass::sc_iterator I = RC->superclasses_begin(); TargetRegisterClass::sc_iterator I = RC->getSuperClasses();
do { do {
switch (Super->getID()) { switch (Super->getID()) {
case ARM::GPRRegClassID: case ARM::GPRRegClassID:

View File

@ -100,42 +100,23 @@ BitVector TargetRegisterInfo::getAllocatableSet(const MachineFunction &MF,
const TargetRegisterClass * const TargetRegisterClass *
TargetRegisterInfo::getCommonSubClass(const TargetRegisterClass *A, TargetRegisterInfo::getCommonSubClass(const TargetRegisterClass *A,
const TargetRegisterClass *B) const { const TargetRegisterClass *B) const {
// First take care of the trivial cases // First take care of the trivial cases.
if (A == B) if (A == B)
return A; return A;
if (!A || !B) if (!A || !B)
return 0; return 0;
// If B is a subclass of A, it will be handled in the loop below // Register classes are ordered topologically, so the largest common
if (B->hasSubClass(A)) // sub-class it the common sub-class with the smallest ID.
return A; const unsigned *SubA = A->getSubClassMask();
const unsigned *SubB = B->getSubClassMask();
const TargetRegisterClass *Best = 0; // We could start the search from max(A.ID, B.ID), but we are only going to
for (TargetRegisterClass::sc_iterator I = A->subclasses_begin(); // execute 2-3 iterations anyway.
const TargetRegisterClass *X = *I; ++I) { for (unsigned Base = 0, BaseE = getNumRegClasses(); Base < BaseE; Base += 32)
if (X == B) if (unsigned Common = *SubA++ & *SubB++)
return B; // B is a subclass of A return getRegClass(Base + CountTrailingZeros_32(Common));
// X must be a common subclass of A and B // No common sub-class exists.
if (!B->hasSubClass(X)) return NULL;
continue;
// A superclass is definitely better.
if (!Best || Best->hasSuperClass(X)) {
Best = X;
continue;
}
// A subclass is definitely worse
if (Best->hasSubClass(X))
continue;
// Best and *I have no super/sub class relation - pick the larger class, or
// the smaller spill size.
int nb = std::distance(Best->begin(), Best->end());
int ni = std::distance(X->begin(), X->end());
if (ni>nb || (ni==nb && X->getSize() < Best->getSize()))
Best = X;
}
return Best;
} }

View File

@ -235,7 +235,7 @@ X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A,
const TargetRegisterClass* const TargetRegisterClass*
X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) const{ X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) const{
const TargetRegisterClass *Super = RC; const TargetRegisterClass *Super = RC;
TargetRegisterClass::sc_iterator I = RC->superclasses_begin(); TargetRegisterClass::sc_iterator I = RC->getSuperClasses();
do { do {
switch (Super->getID()) { switch (Super->getID()) {
case X86::GR8RegClassID: case X86::GR8RegClassID:

View File

@ -622,26 +622,9 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Give the register class a legal C name if it's anonymous. // Give the register class a legal C name if it's anonymous.
std::string Name = RC.TheDef->getName(); std::string Name = RC.TheDef->getName();
OS << " // " << Name OS << " static const unsigned " << Name << "SubclassMask[] = { ";
<< " Register Class sub-classes...\n" printBitVectorAsHex(OS, RC.getSubClasses(), 32);
<< " static const TargetRegisterClass* const " OS << "};\n\n";
<< Name << "Subclasses[] = {\n ";
bool Empty = true;
for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
const CodeGenRegisterClass &RC2 = *RegisterClasses[rc2];
// Sub-classes are used to determine if a virtual register can be used
// as an instruction operand, or if it must be copied first.
if (rc == rc2 || !RC.hasSubClass(&RC2)) continue;
if (!Empty) OS << ", ";
OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
Empty = false;
}
OS << (!Empty ? ", " : "") << "NULL";
OS << "\n };\n\n";
} }
// Emit NULL terminated super-class lists. // Emit NULL terminated super-class lists.
@ -668,7 +651,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< Target.getName() << "MCRegisterClasses[" << Target.getName() << "MCRegisterClasses["
<< RC.getName() + "RegClassID" << "], " << RC.getName() + "RegClassID" << "], "
<< RC.getName() + "VTs" << ", " << RC.getName() + "VTs" << ", "
<< RC.getName() + "Subclasses" << ", "; << RC.getName() + "SubclassMask" << ", ";
if (RC.getSuperClasses().empty()) if (RC.getSuperClasses().empty())
OS << "NullRegClasses, "; OS << "NullRegClasses, ";
else else