Remove the MCRegAliasIterator tables and compute the aliases dynamically.

The size reduction in the RegDiffLists are rather dramatic.  Here are a few
size differences for MCTargetDesc.o files (before and after) in bytes:
R600 - 36160B - 11184B - 69% reduction
ARM - 28480B - 8368B - 71% reduction
Mips - 816B - 576B - 29% reduction

One side effect of dynamically computing the aliases is that the iterator does
not guarantee that the entries are ordered or that duplicates have been removed.
The documentation implies this is a safe assumption and I found no clients that
requires these attributes (i.e., strict ordering and uniqueness).

My local LNT tester results showed no execution-time failures or significant
compile-time regressions (i.e., beyond what I would consider noise) for -O0g,
-O2 and -O3 runs on x86_64 and i386 configurations.
rdar://12906217

llvm-svn: 182783
This commit is contained in:
Chad Rosier 2013-05-28 18:08:48 +00:00
parent b58618a1e9
commit 40d29a8a9d
4 changed files with 74 additions and 90 deletions

View File

@ -99,19 +99,15 @@ public:
bool isAllocatable() const { return Allocatable; }
};
/// MCRegisterDesc - This record contains all of the information known about
/// a particular register. The Overlaps field contains a pointer to a zero
/// terminated array of registers that this register aliases, starting with
/// itself. This is needed for architectures like X86 which have AL alias AX
/// alias EAX. The SubRegs field is a zero terminated array of registers that
/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of
/// AX. The SuperRegs field is a zero terminated array of registers that are
/// super-registers of the specific register, e.g. RAX, EAX, are super-registers
/// of AX.
/// MCRegisterDesc - This record contains information about a particular
/// register. The SubRegs field is a zero terminated array of registers that
/// are sub-registers of the specific register, e.g. AL, AH are sub-registers
/// of AX. The SuperRegs field is a zero terminated array of registers that are
/// super-registers of the specific register, e.g. RAX, EAX, are
/// super-registers of AX.
///
struct MCRegisterDesc {
uint32_t Name; // Printable name for the reg (for debugging)
uint32_t Overlaps; // Overlapping registers, described above
uint32_t SubRegs; // Sub-register set, described above
uint32_t SuperRegs; // Super-register set, described above
@ -226,7 +222,6 @@ public:
// internal list pointers.
friend class MCSubRegIterator;
friend class MCSuperRegIterator;
friend class MCRegAliasIterator;
friend class MCRegUnitIterator;
friend class MCRegUnitRootIterator;
@ -437,6 +432,7 @@ public:
/// If IncludeSelf is set, Reg itself is included in the list.
class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator {
public:
MCSuperRegIterator() {}
MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI,
bool IncludeSelf = false) {
init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs);
@ -446,19 +442,6 @@ public:
}
};
/// MCRegAliasIterator enumerates all registers aliasing Reg.
/// If IncludeSelf is set, Reg itself is included in the list.
class MCRegAliasIterator : public MCRegisterInfo::DiffListIterator {
public:
MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI,
bool IncludeSelf = false) {
init(Reg, MCRI->DiffLists + MCRI->get(Reg).Overlaps);
// Initially, the iterator points to Reg itself.
if (!IncludeSelf)
++*this;
}
};
// Definition for isSuperRegister. Put it down here since it needs the
// iterator defined above in addition to the MCRegisterInfo class itself.
inline bool MCRegisterInfo::isSuperRegister(unsigned RegA, unsigned RegB) const{
@ -486,6 +469,7 @@ class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator {
public:
/// MCRegUnitIterator - Create an iterator that traverses the register units
/// in Reg.
MCRegUnitIterator() {}
MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) {
assert(Reg && "Null register has no regunits");
// Decode the RegUnits MCRegisterDesc field.
@ -519,6 +503,7 @@ class MCRegUnitRootIterator {
uint16_t Reg0;
uint16_t Reg1;
public:
MCRegUnitRootIterator() : Reg0(0), Reg1(0) {}
MCRegUnitRootIterator(unsigned RegUnit, const MCRegisterInfo *MCRI) {
assert(RegUnit < MCRI->getNumRegUnits() && "Invalid register unit");
Reg0 = MCRI->RegUnitRoots[RegUnit][0];
@ -543,6 +528,68 @@ public:
}
};
/// MCRegAliasIterator enumerates all registers aliasing Reg. If IncludeSelf is
/// set, Reg itself is included in the list. This iterator does not guarantee
/// any ordering or that entries are unique.
class MCRegAliasIterator {
private:
unsigned Reg;
const MCRegisterInfo *MCRI;
bool IncludeSelf;
MCRegUnitIterator RI;
MCRegUnitRootIterator RRI;
MCSuperRegIterator SI;
public:
MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI,
bool IncludeSelf)
: Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) {
// Initialize the iterators.
for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) {
for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) {
for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) {
if (!(!IncludeSelf && Reg == *SI))
return;
}
}
}
}
bool isValid() const {
return RI.isValid();
}
unsigned operator*() const {
assert (SI.isValid() && "Cannot dereference an invalid iterator.");
return *SI;
}
void advance() {
// Assuming SI is valid.
++SI;
if (SI.isValid()) return;
++RRI;
if (RRI.isValid()) {
SI = MCSuperRegIterator(*RRI, MCRI, true);
return;
}
++RI;
if (RI.isValid()) {
RRI = MCRegUnitRootIterator(*RI, MCRI);
SI = MCSuperRegIterator(*RRI, MCRI, true);
}
}
void operator++() {
assert(isValid() && "Cannot move off the end of the list.");
do advance();
while (!IncludeSelf && isValid() && *SI == Reg);
}
};
} // End llvm namespace
#endif

View File

@ -526,55 +526,6 @@ CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet,
OSet.insert(I->second);
}
// Compute overlapping registers.
//
// The standard set is all super-registers and all sub-registers, but the
// target description can add arbitrary overlapping registers via the 'Aliases'
// field. This complicates things, but we can compute overlapping sets using
// the following rules:
//
// 1. The relation overlap(A, B) is reflexive and symmetric but not transitive.
//
// 2. overlap(A, B) implies overlap(A, S) for all S in supers(B).
//
// Alternatively:
//
// overlap(A, B) iff there exists:
// A' in { A, subregs(A) } and B' in { B, subregs(B) } such that:
// A' = B' or A' in aliases(B') or B' in aliases(A').
//
// Here subregs(A) is the full flattened sub-register set returned by
// A.getSubRegs() while aliases(A) is simply the special 'Aliases' field in the
// description of register A.
//
// This also implies that registers with a common sub-register are considered
// overlapping. This can happen when forming register pairs:
//
// P0 = (R0, R1)
// P1 = (R1, R2)
// P2 = (R2, R3)
//
// In this case, we will infer an overlap between P0 and P1 because of the
// shared sub-register R1. There is no overlap between P0 and P2.
//
void CodeGenRegister::computeOverlaps(CodeGenRegister::Set &Overlaps,
const CodeGenRegBank &RegBank) const {
assert(!RegUnits.empty() && "Compute register units before overlaps.");
// Register units are assigned such that the overlapping registers are the
// super-registers of the root registers of the register units.
for (unsigned rui = 0, rue = RegUnits.size(); rui != rue; ++rui) {
const RegUnit &RU = RegBank.getRegUnit(RegUnits[rui]);
ArrayRef<const CodeGenRegister*> Roots = RU.getRoots();
for (unsigned ri = 0, re = Roots.size(); ri != re; ++ri) {
const CodeGenRegister *Root = Roots[ri];
Overlaps.insert(Root);
ArrayRef<const CodeGenRegister*> Supers = Root->getSuperRegs();
Overlaps.insert(Supers.begin(), Supers.end());
}
}
}
// Get the sum of this register's unit weights.
unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const {
unsigned Weight = 0;

View File

@ -205,9 +205,6 @@ namespace llvm {
// Canonically ordered set.
typedef std::set<const CodeGenRegister*, Less> Set;
// Compute the set of registers overlapping this.
void computeOverlaps(Set &Overlaps, const CodeGenRegBank&) const;
private:
bool SubRegsComplete;
bool SuperRegsComplete;

View File

@ -703,15 +703,14 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters();
// The lists of sub-registers, super-registers, and overlaps all go in the
// same array. That allows us to share suffixes.
// The lists of sub-registers and super-registers go in the same array. That
// allows us to share suffixes.
typedef std::vector<const CodeGenRegister*> RegVec;
// Differentially encoded lists.
SequenceToOffsetTable<DiffVec> DiffSeqs;
SmallVector<DiffVec, 4> SubRegLists(Regs.size());
SmallVector<DiffVec, 4> SuperRegLists(Regs.size());
SmallVector<DiffVec, 4> OverlapLists(Regs.size());
SmallVector<DiffVec, 4> RegUnitLists(Regs.size());
SmallVector<unsigned, 4> RegUnitInitScale(Regs.size());
@ -747,15 +746,6 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
SuperRegList.begin(), SuperRegList.end());
DiffSeqs.add(SuperRegLists[i]);
// The list of overlaps doesn't need to have any particular order, and Reg
// itself must be omitted.
DiffVec &OverlapList = OverlapLists[i];
CodeGenRegister::Set OSet;
Reg->computeOverlaps(OSet, RegBank);
OSet.erase(Reg);
diffEncode(OverlapList, Reg->EnumValue, OSet.begin(), OSet.end());
DiffSeqs.add(OverlapList);
// Differentially encode the register unit list, seeded by register number.
// First compute a scale factor that allows more diff-lists to be reused:
//
@ -808,13 +798,12 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "extern const MCRegisterDesc " << TargetName
<< "RegDesc[] = { // Descriptors\n";
OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n";
OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0 },\n";
// Emit the register descriptors now.
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
const CodeGenRegister *Reg = Regs[i];
OS << " { " << RegStrings.get(Reg->getName()) << ", "
<< DiffSeqs.get(OverlapLists[i]) << ", "
<< DiffSeqs.get(SubRegLists[i]) << ", "
<< DiffSeqs.get(SuperRegLists[i]) << ", "
<< SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", "