CostPerUse(R->getValueAsInt("CostPerUse")),
CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
SubRegsComplete(false),
- SuperRegsComplete(false)
+ SuperRegsComplete(false),
+ TopoSig(~0u)
{}
void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
}
}
-void CodeGenRegister::computeSuperRegs() {
+void CodeGenRegister::computeSuperRegs(CodeGenRegBank &RegBank) {
// Only visit each register once.
if (SuperRegsComplete)
return;
// lists will be topologically ordered.
for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
I != E; ++I)
- I->second->computeSuperRegs();
+ I->second->computeSuperRegs(RegBank);
// Now add this as a super-register on all sub-registers.
+ // Also compute the TopoSigId in post-order.
+ TopoSigId Id;
for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
I != E; ++I) {
+ // Topological signature computed from SubIdx, TopoId(SubReg).
+ // Loops and idempotent indices have TopoSig = ~0u.
+ Id.push_back(I->first->EnumValue);
+ Id.push_back(I->second->TopoSig);
+
if (I->second == this)
continue;
// Don't add duplicate entries.
continue;
I->second->SuperRegs.push_back(this);
}
+ TopoSig = RegBank.getTopoSig(Id);
}
void
//===----------------------------------------------------------------------===//
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
- : TheDef(R), Name(R->getName()), EnumValue(-1) {
+ : TheDef(R),
+ Name(R->getName()),
+ TopoSigs(RegBank.getNumTopoSigs()),
+ EnumValue(-1) {
// Rename anonymous register classes.
if (R->getName().size() > 9 && R->getName()[9] == '.') {
static unsigned AnonCounter = 0;
// Default allocation order always contains all registers.
for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
Orders[0].push_back((*Elements)[i]);
- Members.insert(RegBank.getReg((*Elements)[i]));
+ const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]);
+ Members.insert(Reg);
+ TopoSigs.set(Reg->getTopoSig());
}
// Alternative allocation orders may be subsets.
// After the sub-register graph is complete, compute the topologically
// ordered SuperRegs list.
for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- Registers[i]->computeSuperRegs();
+ Registers[i]->computeSuperRegs(*this);
// Native register units are associated with a leaf register. They've all been
// discovered now.
}
void CodeGenRegBank::computeComposites() {
+ // Keep track of TopoSigs visited. We only need to visit each TopoSig once,
+ // and many registers will share TopoSigs on regular architectures.
+ BitVector TopoSigs(getNumTopoSigs());
+
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
CodeGenRegister *Reg1 = Registers[i];
+
+ // Skip identical subreg structures already processed.
+ if (TopoSigs.test(Reg1->getTopoSig()))
+ continue;
+ TopoSigs.set(Reg1->getTopoSig());
+
const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs();
for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(),
e1 = SRM1.end(); i1 != e1; ++i1) {
unsigned FirstSubRegRC) {
SmallVector<std::pair<const CodeGenRegister*,
const CodeGenRegister*>, 16> SSPairs;
+ BitVector TopoSigs(getNumTopoSigs());
// Iterate in SubRegIndex numerical order to visit synthetic indices last.
for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
// Build list of (Super, Sub) pairs for this SubIdx.
SSPairs.clear();
+ TopoSigs.reset();
for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
RE = RC->getMembers().end(); RI != RE; ++RI) {
const CodeGenRegister *Super = *RI;
const CodeGenRegister *Sub = Super->getSubRegs().find(SubIdx)->second;
assert(Sub && "Missing sub-register");
SSPairs.push_back(std::make_pair(Super, Sub));
+ TopoSigs.set(Sub->getTopoSig());
}
// Iterate over sub-register class candidates. Ignore classes created by
for (unsigned rci = FirstSubRegRC, rce = RegClasses.size(); rci != rce;
++rci) {
CodeGenRegisterClass *SubRC = RegClasses[rci];
+ // Topological shortcut: SubRC members have the wrong shape.
+ if (!TopoSigs.anyCommon(SubRC->getTopoSigs()))
+ continue;
// Compute the subset of RC that maps into SubRC.
CodeGenRegister::Set SubSet;
for (unsigned i = 0, e = SSPairs.size(); i != e; ++i)
/// CodeGenSubRegIndex - Represents a sub-register index.
class CodeGenSubRegIndex {
Record *const TheDef;
- const unsigned EnumValue;
public:
+ const unsigned EnumValue;
+
CodeGenSubRegIndex(Record *R, unsigned Enum);
const std::string &getName() const;
// Add this as a super-register to all sub-registers after the sub-register
// graph has been built.
- void computeSuperRegs();
+ void computeSuperRegs(CodeGenRegBank&);
const SubRegMap &getSubRegs() const {
assert(SubRegsComplete && "Must precompute sub-registers");
return SuperRegs;
}
+ // Get the topological signature of this register. This is a small integer
+ // less than RegBank.getNumTopoSigs(). Registers with the same TopoSig have
+ // identical sub-register structure. That is, they support the same set of
+ // sub-register indices mapping to the same kind of sub-registers
+ // (TopoSig-wise).
+ unsigned getTopoSig() const {
+ assert(SuperRegsComplete && "TopoSigs haven't been computed yet.");
+ return TopoSig;
+ }
+
// List of register units in ascending order.
typedef SmallVector<unsigned, 16> RegUnitList;
private:
bool SubRegsComplete;
bool SuperRegsComplete;
+ unsigned TopoSig;
// The sub-registers explicit in the .td file form a tree.
SmallVector<CodeGenSubRegIndex*, 8> ExplicitSubRegIndices;
DenseMap<CodeGenSubRegIndex*,
SmallPtrSet<CodeGenRegisterClass*, 8> > SuperRegClasses;
+ // Bit vector of TopoSigs for the registers in this class. This will be
+ // very sparse on regular architectures.
+ BitVector TopoSigs;
+
public:
unsigned EnumValue;
std::string Namespace;
// getOrder(0).
const CodeGenRegister::Set &getMembers() const { return Members; }
+ // Get a bit vector of TopoSigs present in this register class.
+ const BitVector &getTopoSigs() const { return TopoSigs; }
+
// Populate a unique sorted list of units from a register set.
void buildRegUnitSet(std::vector<unsigned> &RegUnits) const;
std::vector<unsigned> Units;
};
+ // Base vector for identifying TopoSigs. The contents uniquely identify a
+ // TopoSig, only computeSuperRegs needs to know how.
+ typedef SmallVector<unsigned, 16> TopoSigId;
+
// CodeGenRegBank - Represent a target's registers and the relations between
// them.
class CodeGenRegBank {
unsigned NumNativeRegUnits;
unsigned NumRegUnits; // # native + adopted register units.
+ std::map<TopoSigId, unsigned> TopoSigs;
+
// Map each register unit to a weight (for register pressure).
// Includes native and adopted register units.
std::vector<unsigned> RegUnitWeights;
return Reg->EnumValue - 1;
}
+ // Return the number of allocated TopoSigs. The first TopoSig representing
+ // leaf registers is allocated number 0.
+ unsigned getNumTopoSigs() const {
+ return TopoSigs.size();
+ }
+
+ // Find or create a TopoSig for the given TopoSigId.
+ // This function is only for use by CodeGenRegister::computeSuperRegs().
+ // Others should simply use Reg->getTopoSig().
+ unsigned getTopoSig(const TopoSigId &Id) {
+ return TopoSigs.insert(std::make_pair(Id, TopoSigs.size())).first->second;
+ }
+
// Create a new non-native register unit that can be adopted by a register
// to increase its pressure. Note that NumNativeRegUnits is not increased.
unsigned newRegUnit(unsigned Weight) {