mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-11 21:56:15 +00:00
Replace another std::set in the core of CodeGenRegister, this time with sorted arrays.
The hot path through this region of code does lots of batch inserts into sets. By storing them as sorted arrays, we can defer the sorting to the end of the batch, which is dramatically more efficient. This reduces tblgen runtime by 25% on my worst-case target. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227682 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
35da384515
commit
41a9ae532e
@ -152,11 +152,11 @@ const std::string &CodeGenRegister::getName() const {
|
||||
namespace {
|
||||
// Iterate over all register units in a set of registers.
|
||||
class RegUnitIterator {
|
||||
CodeGenRegister::Set::const_iterator RegI, RegE;
|
||||
CodeGenRegister::Vec::const_iterator RegI, RegE;
|
||||
CodeGenRegister::RegUnitList::iterator UnitI, UnitE;
|
||||
|
||||
public:
|
||||
RegUnitIterator(const CodeGenRegister::Set &Regs):
|
||||
RegUnitIterator(const CodeGenRegister::Vec &Regs):
|
||||
RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() {
|
||||
|
||||
if (RegI != RegE) {
|
||||
@ -642,6 +642,11 @@ struct TupleExpander : SetTheory::Expander {
|
||||
// CodeGenRegisterClass
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) {
|
||||
std::sort(M.begin(), M.end(), CodeGenRegister::Less());
|
||||
M.erase(std::unique(M.begin(), M.end(), CodeGenRegister::Equal()), M.end());
|
||||
}
|
||||
|
||||
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
|
||||
: TheDef(R),
|
||||
Name(R->getName()),
|
||||
@ -675,9 +680,10 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
|
||||
for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
|
||||
Orders[0].push_back((*Elements)[i]);
|
||||
const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]);
|
||||
Members.insert(Reg);
|
||||
Members.push_back(Reg);
|
||||
TopoSigs.set(Reg->getTopoSig());
|
||||
}
|
||||
sortAndUniqueRegisters(Members);
|
||||
|
||||
// Alternative allocation orders may be subsets.
|
||||
SetTheory::RecSet Order;
|
||||
@ -719,9 +725,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
|
||||
SpillAlignment(Props.SpillAlignment),
|
||||
CopyCost(0),
|
||||
Allocatable(true) {
|
||||
for (CodeGenRegister::Set::iterator I = Members.begin(), E = Members.end();
|
||||
I != E; ++I)
|
||||
TopoSigs.set((*I)->getTopoSig());
|
||||
for (const auto R : Members)
|
||||
TopoSigs.set(R->getTopoSig());
|
||||
}
|
||||
|
||||
// Compute inherited propertied for a synthesized register class.
|
||||
@ -750,15 +755,15 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
|
||||
}
|
||||
|
||||
bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
|
||||
return Members.count(Reg);
|
||||
return std::binary_search(Members.begin(), Members.end(), Reg,
|
||||
CodeGenRegister::Less());
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
|
||||
OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
|
||||
for (CodeGenRegister::Set::const_iterator I = K.Members->begin(),
|
||||
E = K.Members->end(); I != E; ++I)
|
||||
OS << ", " << (*I)->getName();
|
||||
for (const auto R : *K.Members)
|
||||
OS << ", " << R->getName();
|
||||
return OS << " }";
|
||||
}
|
||||
}
|
||||
@ -1034,7 +1039,7 @@ void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
|
||||
// Create a synthetic sub-class if it is missing.
|
||||
CodeGenRegisterClass*
|
||||
CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
|
||||
const CodeGenRegister::Set *Members,
|
||||
const CodeGenRegister::Vec *Members,
|
||||
StringRef Name) {
|
||||
// Synthetic sub-class has the same size and alignment as RC.
|
||||
CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment);
|
||||
@ -1283,7 +1288,7 @@ namespace {
|
||||
// for which the unit weight equals the set weight. These units should not have
|
||||
// their weight increased.
|
||||
struct UberRegSet {
|
||||
CodeGenRegister::Set Regs;
|
||||
CodeGenRegister::Vec Regs;
|
||||
unsigned Weight;
|
||||
CodeGenRegister::RegUnitList SingularDeterminants;
|
||||
|
||||
@ -1312,7 +1317,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
|
||||
if (!RegClass.Allocatable)
|
||||
continue;
|
||||
|
||||
const CodeGenRegister::Set &Regs = RegClass.getMembers();
|
||||
const CodeGenRegister::Vec &Regs = RegClass.getMembers();
|
||||
if (Regs.empty())
|
||||
continue;
|
||||
|
||||
@ -1320,8 +1325,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
|
||||
assert(USetID && "register number 0 is invalid");
|
||||
|
||||
AllocatableRegs.insert((*Regs.begin())->EnumValue);
|
||||
for (CodeGenRegister::Set::const_iterator I = std::next(Regs.begin()),
|
||||
E = Regs.end(); I != E; ++I) {
|
||||
for (auto I = std::next(Regs.begin()), E = Regs.end(); I != E; ++I) {
|
||||
AllocatableRegs.insert((*I)->EnumValue);
|
||||
UberSetIDs.join(USetID, (*I)->EnumValue);
|
||||
}
|
||||
@ -1351,7 +1355,8 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
|
||||
USetID = 0;
|
||||
|
||||
UberRegSet *USet = &UberSets[USetID];
|
||||
USet->Regs.insert(&Reg);
|
||||
USet->Regs.push_back(&Reg);
|
||||
sortAndUniqueRegisters(USet->Regs);
|
||||
RegSets[i++] = USet;
|
||||
}
|
||||
}
|
||||
@ -1393,11 +1398,9 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets,
|
||||
}
|
||||
|
||||
// Find singular determinants.
|
||||
for (CodeGenRegister::Set::iterator RegI = I->Regs.begin(),
|
||||
RegE = I->Regs.end(); RegI != RegE; ++RegI) {
|
||||
if ((*RegI)->getRegUnits().count() == 1
|
||||
&& (*RegI)->getWeight(RegBank) == I->Weight) {
|
||||
I->SingularDeterminants |= (*RegI)->getRegUnits();
|
||||
for (const auto R : I->Regs) {
|
||||
if (R->getRegUnits().count() == 1 && R->getWeight(RegBank) == I->Weight) {
|
||||
I->SingularDeterminants |= R->getRegUnits();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1838,9 +1841,9 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
|
||||
continue;
|
||||
|
||||
// Compute the set intersection of RC1 and RC2.
|
||||
const CodeGenRegister::Set &Memb1 = RC1->getMembers();
|
||||
const CodeGenRegister::Set &Memb2 = RC2->getMembers();
|
||||
CodeGenRegister::Set Intersection;
|
||||
const CodeGenRegister::Vec &Memb1 = RC1->getMembers();
|
||||
const CodeGenRegister::Vec &Memb2 = RC2->getMembers();
|
||||
CodeGenRegister::Vec Intersection;
|
||||
std::set_intersection(Memb1.begin(), Memb1.end(),
|
||||
Memb2.begin(), Memb2.end(),
|
||||
std::inserter(Intersection, Intersection.begin()),
|
||||
@ -1870,19 +1873,21 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
|
||||
//
|
||||
void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
|
||||
// Map SubRegIndex to set of registers in RC supporting that SubRegIndex.
|
||||
typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Set,
|
||||
typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Vec,
|
||||
CodeGenSubRegIndex::Less> SubReg2SetMap;
|
||||
|
||||
// Compute the set of registers supporting each SubRegIndex.
|
||||
SubReg2SetMap SRSets;
|
||||
for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
|
||||
RE = RC->getMembers().end(); RI != RE; ++RI) {
|
||||
const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs();
|
||||
for (const auto R : RC->getMembers()) {
|
||||
const CodeGenRegister::SubRegMap &SRM = R->getSubRegs();
|
||||
for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
|
||||
E = SRM.end(); I != E; ++I)
|
||||
SRSets[I->first].insert(*RI);
|
||||
SRSets[I->first].push_back(R);
|
||||
}
|
||||
|
||||
for (auto I : SRSets)
|
||||
sortAndUniqueRegisters(I.second);
|
||||
|
||||
// Find matching classes for all SRSets entries. Iterate in SubRegIndex
|
||||
// numerical order to visit synthetic indices last.
|
||||
for (const auto &SubIdx : SubRegIndices) {
|
||||
@ -1927,9 +1932,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
|
||||
// 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;
|
||||
for (const auto Super : RC->getMembers()) {
|
||||
const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second;
|
||||
assert(Sub && "Missing sub-register");
|
||||
SSPairs.push_back(std::make_pair(Super, Sub));
|
||||
@ -1948,22 +1951,26 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
|
||||
if (!TopoSigs.anyCommon(SubRC.getTopoSigs()))
|
||||
continue;
|
||||
// Compute the subset of RC that maps into SubRC.
|
||||
CodeGenRegister::Set SubSet;
|
||||
CodeGenRegister::Vec SubSetVec;
|
||||
for (unsigned i = 0, e = SSPairs.size(); i != e; ++i)
|
||||
if (SubRC.contains(SSPairs[i].second))
|
||||
SubSet.insert(SSPairs[i].first);
|
||||
if (SubSet.empty())
|
||||
SubSetVec.push_back(SSPairs[i].first);
|
||||
|
||||
if (SubSetVec.empty())
|
||||
continue;
|
||||
|
||||
// RC injects completely into SubRC.
|
||||
if (SubSet.size() == SSPairs.size()) {
|
||||
sortAndUniqueRegisters(SubSetVec);
|
||||
if (SubSetVec.size() == SSPairs.size()) {
|
||||
SubRC.addSuperRegClass(&SubIdx, RC);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only a subset of RC maps into SubRC. Make sure it is represented by a
|
||||
// class.
|
||||
getOrCreateSubClass(RC, &SubSet, RC->getName() + "_with_" +
|
||||
SubIdx.getName() + "_in_" +
|
||||
SubRC.getName());
|
||||
getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" +
|
||||
SubIdx.getName() + "_in_" +
|
||||
SubRC.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -241,8 +241,16 @@ namespace llvm {
|
||||
}
|
||||
};
|
||||
|
||||
struct Equal {
|
||||
bool operator()(const CodeGenRegister *A,
|
||||
const CodeGenRegister *B) const {
|
||||
assert(A && B);
|
||||
return A->EnumValue == B->EnumValue;
|
||||
}
|
||||
};
|
||||
|
||||
// Canonically ordered set.
|
||||
typedef std::set<const CodeGenRegister*, Less> Set;
|
||||
typedef std::vector<const CodeGenRegister*> Vec;
|
||||
|
||||
private:
|
||||
bool SubRegsComplete;
|
||||
@ -268,7 +276,7 @@ namespace llvm {
|
||||
|
||||
|
||||
class CodeGenRegisterClass {
|
||||
CodeGenRegister::Set Members;
|
||||
CodeGenRegister::Vec Members;
|
||||
// Allocation orders. Order[0] always contains all registers in Members.
|
||||
std::vector<SmallVector<Record*, 16> > Orders;
|
||||
// Bit mask of sub-classes including this, indexed by their EnumValue.
|
||||
@ -389,7 +397,7 @@ namespace llvm {
|
||||
|
||||
// Get the set of registers. This set contains the same registers as
|
||||
// getOrder(0).
|
||||
const CodeGenRegister::Set &getMembers() const { return Members; }
|
||||
const CodeGenRegister::Vec &getMembers() const { return Members; }
|
||||
|
||||
// Get a bit vector of TopoSigs present in this register class.
|
||||
const BitVector &getTopoSigs() const { return TopoSigs; }
|
||||
@ -403,11 +411,11 @@ namespace llvm {
|
||||
// sub-classes. Note the ordering provided by this key is not the same as
|
||||
// the topological order used for the EnumValues.
|
||||
struct Key {
|
||||
const CodeGenRegister::Set *Members;
|
||||
const CodeGenRegister::Vec *Members;
|
||||
unsigned SpillSize;
|
||||
unsigned SpillAlignment;
|
||||
|
||||
Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0)
|
||||
Key(const CodeGenRegister::Vec *M, unsigned S = 0, unsigned A = 0)
|
||||
: Members(M), SpillSize(S), SpillAlignment(A) {}
|
||||
|
||||
Key(const CodeGenRegisterClass &RC)
|
||||
@ -525,7 +533,7 @@ namespace llvm {
|
||||
|
||||
// Create a synthetic sub-class if it is missing.
|
||||
CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC,
|
||||
const CodeGenRegister::Set *Membs,
|
||||
const CodeGenRegister::Vec *Membs,
|
||||
StringRef Name);
|
||||
|
||||
// Infer missing register classes.
|
||||
|
@ -180,7 +180,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
|
||||
<< "getRegClassWeight(const TargetRegisterClass *RC) const {\n"
|
||||
<< " static const RegClassWeight RCWeightTable[] = {\n";
|
||||
for (const auto &RC : RegBank.getRegClasses()) {
|
||||
const CodeGenRegister::Set &Regs = RC.getMembers();
|
||||
const CodeGenRegister::Vec &Regs = RC.getMembers();
|
||||
if (Regs.empty())
|
||||
OS << " {0, 0";
|
||||
else {
|
||||
|
Loading…
Reference in New Issue
Block a user