mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-16 11:24:39 +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:
@@ -152,11 +152,11 @@ const std::string &CodeGenRegister::getName() const {
|
|||||||
namespace {
|
namespace {
|
||||||
// Iterate over all register units in a set of registers.
|
// Iterate over all register units in a set of registers.
|
||||||
class RegUnitIterator {
|
class RegUnitIterator {
|
||||||
CodeGenRegister::Set::const_iterator RegI, RegE;
|
CodeGenRegister::Vec::const_iterator RegI, RegE;
|
||||||
CodeGenRegister::RegUnitList::iterator UnitI, UnitE;
|
CodeGenRegister::RegUnitList::iterator UnitI, UnitE;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RegUnitIterator(const CodeGenRegister::Set &Regs):
|
RegUnitIterator(const CodeGenRegister::Vec &Regs):
|
||||||
RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() {
|
RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() {
|
||||||
|
|
||||||
if (RegI != RegE) {
|
if (RegI != RegE) {
|
||||||
@@ -642,6 +642,11 @@ struct TupleExpander : SetTheory::Expander {
|
|||||||
// CodeGenRegisterClass
|
// 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)
|
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
|
||||||
: TheDef(R),
|
: TheDef(R),
|
||||||
Name(R->getName()),
|
Name(R->getName()),
|
||||||
@@ -675,9 +680,10 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
|
|||||||
for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
|
for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
|
||||||
Orders[0].push_back((*Elements)[i]);
|
Orders[0].push_back((*Elements)[i]);
|
||||||
const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]);
|
const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]);
|
||||||
Members.insert(Reg);
|
Members.push_back(Reg);
|
||||||
TopoSigs.set(Reg->getTopoSig());
|
TopoSigs.set(Reg->getTopoSig());
|
||||||
}
|
}
|
||||||
|
sortAndUniqueRegisters(Members);
|
||||||
|
|
||||||
// Alternative allocation orders may be subsets.
|
// Alternative allocation orders may be subsets.
|
||||||
SetTheory::RecSet Order;
|
SetTheory::RecSet Order;
|
||||||
@@ -719,9 +725,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
|
|||||||
SpillAlignment(Props.SpillAlignment),
|
SpillAlignment(Props.SpillAlignment),
|
||||||
CopyCost(0),
|
CopyCost(0),
|
||||||
Allocatable(true) {
|
Allocatable(true) {
|
||||||
for (CodeGenRegister::Set::iterator I = Members.begin(), E = Members.end();
|
for (const auto R : Members)
|
||||||
I != E; ++I)
|
TopoSigs.set(R->getTopoSig());
|
||||||
TopoSigs.set((*I)->getTopoSig());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute inherited propertied for a synthesized register class.
|
// Compute inherited propertied for a synthesized register class.
|
||||||
@@ -750,15 +755,15 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
|
bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
|
||||||
return Members.count(Reg);
|
return std::binary_search(Members.begin(), Members.end(), Reg,
|
||||||
|
CodeGenRegister::Less());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
|
raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
|
||||||
OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
|
OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
|
||||||
for (CodeGenRegister::Set::const_iterator I = K.Members->begin(),
|
for (const auto R : *K.Members)
|
||||||
E = K.Members->end(); I != E; ++I)
|
OS << ", " << R->getName();
|
||||||
OS << ", " << (*I)->getName();
|
|
||||||
return OS << " }";
|
return OS << " }";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1034,7 +1039,7 @@ void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
|
|||||||
// Create a synthetic sub-class if it is missing.
|
// Create a synthetic sub-class if it is missing.
|
||||||
CodeGenRegisterClass*
|
CodeGenRegisterClass*
|
||||||
CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
|
CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
|
||||||
const CodeGenRegister::Set *Members,
|
const CodeGenRegister::Vec *Members,
|
||||||
StringRef Name) {
|
StringRef Name) {
|
||||||
// Synthetic sub-class has the same size and alignment as RC.
|
// Synthetic sub-class has the same size and alignment as RC.
|
||||||
CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment);
|
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
|
// for which the unit weight equals the set weight. These units should not have
|
||||||
// their weight increased.
|
// their weight increased.
|
||||||
struct UberRegSet {
|
struct UberRegSet {
|
||||||
CodeGenRegister::Set Regs;
|
CodeGenRegister::Vec Regs;
|
||||||
unsigned Weight;
|
unsigned Weight;
|
||||||
CodeGenRegister::RegUnitList SingularDeterminants;
|
CodeGenRegister::RegUnitList SingularDeterminants;
|
||||||
|
|
||||||
@@ -1312,7 +1317,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
|
|||||||
if (!RegClass.Allocatable)
|
if (!RegClass.Allocatable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const CodeGenRegister::Set &Regs = RegClass.getMembers();
|
const CodeGenRegister::Vec &Regs = RegClass.getMembers();
|
||||||
if (Regs.empty())
|
if (Regs.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -1320,8 +1325,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
|
|||||||
assert(USetID && "register number 0 is invalid");
|
assert(USetID && "register number 0 is invalid");
|
||||||
|
|
||||||
AllocatableRegs.insert((*Regs.begin())->EnumValue);
|
AllocatableRegs.insert((*Regs.begin())->EnumValue);
|
||||||
for (CodeGenRegister::Set::const_iterator I = std::next(Regs.begin()),
|
for (auto I = std::next(Regs.begin()), E = Regs.end(); I != E; ++I) {
|
||||||
E = Regs.end(); I != E; ++I) {
|
|
||||||
AllocatableRegs.insert((*I)->EnumValue);
|
AllocatableRegs.insert((*I)->EnumValue);
|
||||||
UberSetIDs.join(USetID, (*I)->EnumValue);
|
UberSetIDs.join(USetID, (*I)->EnumValue);
|
||||||
}
|
}
|
||||||
@@ -1351,7 +1355,8 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
|
|||||||
USetID = 0;
|
USetID = 0;
|
||||||
|
|
||||||
UberRegSet *USet = &UberSets[USetID];
|
UberRegSet *USet = &UberSets[USetID];
|
||||||
USet->Regs.insert(&Reg);
|
USet->Regs.push_back(&Reg);
|
||||||
|
sortAndUniqueRegisters(USet->Regs);
|
||||||
RegSets[i++] = USet;
|
RegSets[i++] = USet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1393,11 +1398,9 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find singular determinants.
|
// Find singular determinants.
|
||||||
for (CodeGenRegister::Set::iterator RegI = I->Regs.begin(),
|
for (const auto R : I->Regs) {
|
||||||
RegE = I->Regs.end(); RegI != RegE; ++RegI) {
|
if (R->getRegUnits().count() == 1 && R->getWeight(RegBank) == I->Weight) {
|
||||||
if ((*RegI)->getRegUnits().count() == 1
|
I->SingularDeterminants |= R->getRegUnits();
|
||||||
&& (*RegI)->getWeight(RegBank) == I->Weight) {
|
|
||||||
I->SingularDeterminants |= (*RegI)->getRegUnits();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1838,9 +1841,9 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Compute the set intersection of RC1 and RC2.
|
// Compute the set intersection of RC1 and RC2.
|
||||||
const CodeGenRegister::Set &Memb1 = RC1->getMembers();
|
const CodeGenRegister::Vec &Memb1 = RC1->getMembers();
|
||||||
const CodeGenRegister::Set &Memb2 = RC2->getMembers();
|
const CodeGenRegister::Vec &Memb2 = RC2->getMembers();
|
||||||
CodeGenRegister::Set Intersection;
|
CodeGenRegister::Vec Intersection;
|
||||||
std::set_intersection(Memb1.begin(), Memb1.end(),
|
std::set_intersection(Memb1.begin(), Memb1.end(),
|
||||||
Memb2.begin(), Memb2.end(),
|
Memb2.begin(), Memb2.end(),
|
||||||
std::inserter(Intersection, Intersection.begin()),
|
std::inserter(Intersection, Intersection.begin()),
|
||||||
@@ -1870,19 +1873,21 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
|
|||||||
//
|
//
|
||||||
void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
|
void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
|
||||||
// Map SubRegIndex to set of registers in RC supporting that SubRegIndex.
|
// 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;
|
CodeGenSubRegIndex::Less> SubReg2SetMap;
|
||||||
|
|
||||||
// Compute the set of registers supporting each SubRegIndex.
|
// Compute the set of registers supporting each SubRegIndex.
|
||||||
SubReg2SetMap SRSets;
|
SubReg2SetMap SRSets;
|
||||||
for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
|
for (const auto R : RC->getMembers()) {
|
||||||
RE = RC->getMembers().end(); RI != RE; ++RI) {
|
const CodeGenRegister::SubRegMap &SRM = R->getSubRegs();
|
||||||
const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs();
|
|
||||||
for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
|
for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
|
||||||
E = SRM.end(); I != E; ++I)
|
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
|
// Find matching classes for all SRSets entries. Iterate in SubRegIndex
|
||||||
// numerical order to visit synthetic indices last.
|
// numerical order to visit synthetic indices last.
|
||||||
for (const auto &SubIdx : SubRegIndices) {
|
for (const auto &SubIdx : SubRegIndices) {
|
||||||
@@ -1927,9 +1932,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
|
|||||||
// Build list of (Super, Sub) pairs for this SubIdx.
|
// Build list of (Super, Sub) pairs for this SubIdx.
|
||||||
SSPairs.clear();
|
SSPairs.clear();
|
||||||
TopoSigs.reset();
|
TopoSigs.reset();
|
||||||
for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(),
|
for (const auto Super : RC->getMembers()) {
|
||||||
RE = RC->getMembers().end(); RI != RE; ++RI) {
|
|
||||||
const CodeGenRegister *Super = *RI;
|
|
||||||
const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second;
|
const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second;
|
||||||
assert(Sub && "Missing sub-register");
|
assert(Sub && "Missing sub-register");
|
||||||
SSPairs.push_back(std::make_pair(Super, Sub));
|
SSPairs.push_back(std::make_pair(Super, Sub));
|
||||||
@@ -1948,22 +1951,26 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
|
|||||||
if (!TopoSigs.anyCommon(SubRC.getTopoSigs()))
|
if (!TopoSigs.anyCommon(SubRC.getTopoSigs()))
|
||||||
continue;
|
continue;
|
||||||
// Compute the subset of RC that maps into SubRC.
|
// 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)
|
for (unsigned i = 0, e = SSPairs.size(); i != e; ++i)
|
||||||
if (SubRC.contains(SSPairs[i].second))
|
if (SubRC.contains(SSPairs[i].second))
|
||||||
SubSet.insert(SSPairs[i].first);
|
SubSetVec.push_back(SSPairs[i].first);
|
||||||
if (SubSet.empty())
|
|
||||||
|
if (SubSetVec.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// RC injects completely into SubRC.
|
// RC injects completely into SubRC.
|
||||||
if (SubSet.size() == SSPairs.size()) {
|
sortAndUniqueRegisters(SubSetVec);
|
||||||
|
if (SubSetVec.size() == SSPairs.size()) {
|
||||||
SubRC.addSuperRegClass(&SubIdx, RC);
|
SubRC.addSuperRegClass(&SubIdx, RC);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only a subset of RC maps into SubRC. Make sure it is represented by a
|
// Only a subset of RC maps into SubRC. Make sure it is represented by a
|
||||||
// class.
|
// class.
|
||||||
getOrCreateSubClass(RC, &SubSet, RC->getName() + "_with_" +
|
getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" +
|
||||||
SubIdx.getName() + "_in_" +
|
SubIdx.getName() + "_in_" +
|
||||||
SubRC.getName());
|
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.
|
// Canonically ordered set.
|
||||||
typedef std::set<const CodeGenRegister*, Less> Set;
|
typedef std::vector<const CodeGenRegister*> Vec;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool SubRegsComplete;
|
bool SubRegsComplete;
|
||||||
@@ -268,7 +276,7 @@ namespace llvm {
|
|||||||
|
|
||||||
|
|
||||||
class CodeGenRegisterClass {
|
class CodeGenRegisterClass {
|
||||||
CodeGenRegister::Set Members;
|
CodeGenRegister::Vec Members;
|
||||||
// Allocation orders. Order[0] always contains all registers in Members.
|
// Allocation orders. Order[0] always contains all registers in Members.
|
||||||
std::vector<SmallVector<Record*, 16> > Orders;
|
std::vector<SmallVector<Record*, 16> > Orders;
|
||||||
// Bit mask of sub-classes including this, indexed by their EnumValue.
|
// 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
|
// Get the set of registers. This set contains the same registers as
|
||||||
// getOrder(0).
|
// 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.
|
// Get a bit vector of TopoSigs present in this register class.
|
||||||
const BitVector &getTopoSigs() const { return TopoSigs; }
|
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
|
// sub-classes. Note the ordering provided by this key is not the same as
|
||||||
// the topological order used for the EnumValues.
|
// the topological order used for the EnumValues.
|
||||||
struct Key {
|
struct Key {
|
||||||
const CodeGenRegister::Set *Members;
|
const CodeGenRegister::Vec *Members;
|
||||||
unsigned SpillSize;
|
unsigned SpillSize;
|
||||||
unsigned SpillAlignment;
|
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) {}
|
: Members(M), SpillSize(S), SpillAlignment(A) {}
|
||||||
|
|
||||||
Key(const CodeGenRegisterClass &RC)
|
Key(const CodeGenRegisterClass &RC)
|
||||||
@@ -525,7 +533,7 @@ namespace llvm {
|
|||||||
|
|
||||||
// Create a synthetic sub-class if it is missing.
|
// Create a synthetic sub-class if it is missing.
|
||||||
CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC,
|
CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC,
|
||||||
const CodeGenRegister::Set *Membs,
|
const CodeGenRegister::Vec *Membs,
|
||||||
StringRef Name);
|
StringRef Name);
|
||||||
|
|
||||||
// Infer missing register classes.
|
// Infer missing register classes.
|
||||||
|
@@ -180,7 +180,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
|
|||||||
<< "getRegClassWeight(const TargetRegisterClass *RC) const {\n"
|
<< "getRegClassWeight(const TargetRegisterClass *RC) const {\n"
|
||||||
<< " static const RegClassWeight RCWeightTable[] = {\n";
|
<< " static const RegClassWeight RCWeightTable[] = {\n";
|
||||||
for (const auto &RC : RegBank.getRegClasses()) {
|
for (const auto &RC : RegBank.getRegClasses()) {
|
||||||
const CodeGenRegister::Set &Regs = RC.getMembers();
|
const CodeGenRegister::Vec &Regs = RC.getMembers();
|
||||||
if (Regs.empty())
|
if (Regs.empty())
|
||||||
OS << " {0, 0";
|
OS << " {0, 0";
|
||||||
else {
|
else {
|
||||||
|
Reference in New Issue
Block a user