mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-23 01:30:19 +00:00
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:
parent
b7359e384f
commit
c8e2bb68bb
@ -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 {
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user