Table-generated register pressure fixes.

Handle mixing allocatable and unallocatable register gracefully.
Simplify the pruning of register unit sets.

llvm-svn: 154474
This commit is contained in:
Andrew Trick 2012-04-11 03:19:15 +00:00
parent 3ef01cdb2e
commit 0d94c73c26
1 changed files with 47 additions and 24 deletions

View File

@ -945,22 +945,34 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets,
// For simplicitly make the SetID the same as EnumValue. // For simplicitly make the SetID the same as EnumValue.
IntEqClasses UberSetIDs(Registers.size()+1); IntEqClasses UberSetIDs(Registers.size()+1);
std::set<unsigned> AllocatableRegs;
for (unsigned i = 0, e = RegBank.getRegClasses().size(); i != e; ++i) { for (unsigned i = 0, e = RegBank.getRegClasses().size(); i != e; ++i) {
CodeGenRegisterClass *RegClass = RegBank.getRegClasses()[i]; CodeGenRegisterClass *RegClass = RegBank.getRegClasses()[i];
if (!RegClass->Allocatable)
continue;
const CodeGenRegister::Set &Regs = RegClass->getMembers(); const CodeGenRegister::Set &Regs = RegClass->getMembers();
if (Regs.empty()) continue; if (Regs.empty())
continue;
unsigned USetID = UberSetIDs.findLeader((*Regs.begin())->EnumValue); unsigned USetID = UberSetIDs.findLeader((*Regs.begin())->EnumValue);
assert(USetID && "register number 0 is invalid"); assert(USetID && "register number 0 is invalid");
// combine non-allocatable classes AllocatableRegs.insert((*Regs.begin())->EnumValue);
if (!RegClass->Allocatable) {
UberSetIDs.join(0, USetID);
USetID = 0;
}
for (CodeGenRegister::Set::const_iterator I = llvm::next(Regs.begin()), for (CodeGenRegister::Set::const_iterator I = llvm::next(Regs.begin()),
E = Regs.end(); I != E; ++I) E = Regs.end(); I != E; ++I) {
AllocatableRegs.insert((*I)->EnumValue);
UberSetIDs.join(USetID, (*I)->EnumValue); UberSetIDs.join(USetID, (*I)->EnumValue);
}
}
// Combine non-allocatable regs.
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
unsigned RegNum = Registers[i]->EnumValue;
if (AllocatableRegs.count(RegNum))
continue;
UberSetIDs.join(0, RegNum);
} }
UberSetIDs.compress(); UberSetIDs.compress();
@ -1155,29 +1167,34 @@ void CodeGenRegBank::pruneUnitSets() {
assert(RegClassUnitSets.empty() && "this invalidates RegClassUnitSets"); assert(RegClassUnitSets.empty() && "this invalidates RegClassUnitSets");
// Form an equivalence class of UnitSets with no significant difference. // Form an equivalence class of UnitSets with no significant difference.
IntEqClasses RepUnitSetIDs(RegUnitSets.size()); // Populate PrunedUnitSets with each equivalence class's superset.
std::vector<RegUnitSet> PrunedUnitSets;
for (unsigned SubIdx = 0, EndIdx = RegUnitSets.size(); for (unsigned SubIdx = 0, EndIdx = RegUnitSets.size();
SubIdx != EndIdx; ++SubIdx) { SubIdx != EndIdx; ++SubIdx) {
const RegUnitSet &SubSet = RegUnitSets[SubIdx]; const RegUnitSet &SubSet = RegUnitSets[SubIdx];
for (unsigned SuperIdx = 0; SuperIdx != EndIdx; ++SuperIdx) { unsigned SuperIdx = 0;
for (; SuperIdx != EndIdx; ++SuperIdx) {
if (SuperIdx == SubIdx) if (SuperIdx == SubIdx)
continue; continue;
const RegUnitSet *SuperSet = 0;
const RegUnitSet &SuperSet = RegUnitSets[SuperIdx]; if (SuperIdx > SubIdx)
if (isRegUnitSubSet(SubSet.Units, SuperSet.Units) SuperSet = &RegUnitSets[SuperIdx];
&& (SubSet.Units.size() + 3 > SuperSet.Units.size())) { else {
RepUnitSetIDs.join(SubIdx, SuperIdx); // Compare with already-pruned sets.
if (SuperIdx >= PrunedUnitSets.size())
continue;
SuperSet = &PrunedUnitSets[SuperIdx];
}
if (isRegUnitSubSet(SubSet.Units, SuperSet->Units)
&& (SubSet.Units.size() + 3 > SuperSet->Units.size())) {
break;
} }
} }
} if (SuperIdx != EndIdx)
RepUnitSetIDs.compress(); continue;
PrunedUnitSets.resize(PrunedUnitSets.size()+1);
// Populate PrunedUnitSets with each equivalence class's superset. PrunedUnitSets.back().Name = RegUnitSets[SubIdx].Name;
std::vector<RegUnitSet> PrunedUnitSets(RepUnitSetIDs.getNumClasses()); PrunedUnitSets.back().Units.swap(RegUnitSets[SubIdx].Units);
for (unsigned i = 0, e = RegUnitSets.size(); i != e; ++i) {
RegUnitSet &SuperSet = PrunedUnitSets[RepUnitSetIDs[i]];
if (SuperSet.Units.size() < RegUnitSets[i].Units.size())
SuperSet = RegUnitSets[i];
} }
RegUnitSets.swap(PrunedUnitSets); RegUnitSets.swap(PrunedUnitSets);
} }
@ -1195,6 +1212,8 @@ void CodeGenRegBank::computeRegUnitSets() {
const ArrayRef<CodeGenRegisterClass*> &RegClasses = getRegClasses(); const ArrayRef<CodeGenRegisterClass*> &RegClasses = getRegClasses();
unsigned NumRegClasses = RegClasses.size(); unsigned NumRegClasses = RegClasses.size();
for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) {
if (!RegClasses[RCIdx]->Allocatable)
continue;
// Speculatively grow the RegUnitSets to hold the new set. // Speculatively grow the RegUnitSets to hold the new set.
RegUnitSets.resize(RegUnitSets.size() + 1); RegUnitSets.resize(RegUnitSets.size() + 1);
@ -1253,12 +1272,15 @@ void CodeGenRegBank::computeRegUnitSets() {
} }
} }
// Iteratively prune unit sets again after inferring supersets. // Iteratively prune unit sets after inferring supersets.
pruneUnitSets(); pruneUnitSets();
// For each register class, list the UnitSets that are supersets. // For each register class, list the UnitSets that are supersets.
RegClassUnitSets.resize(NumRegClasses); RegClassUnitSets.resize(NumRegClasses);
for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) {
if (!RegClasses[RCIdx]->Allocatable)
continue;
// Recompute the sorted list of units in this class. // Recompute the sorted list of units in this class.
std::vector<unsigned> RegUnits; std::vector<unsigned> RegUnits;
buildRegUnitSet(RegClasses[RCIdx]->getMembers(), RegUnits); buildRegUnitSet(RegClasses[RCIdx]->getMembers(), RegUnits);
@ -1273,6 +1295,7 @@ void CodeGenRegBank::computeRegUnitSets() {
if (isRegUnitSubSet(RegUnits, RegUnitSets[USIdx].Units)) if (isRegUnitSubSet(RegUnits, RegUnitSets[USIdx].Units))
RegClassUnitSets[RCIdx].push_back(USIdx); RegClassUnitSets[RCIdx].push_back(USIdx);
} }
assert(!RegClassUnitSets[RCIdx].empty() && "missing unit set for regclass");
} }
} }