mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-11 13:44:28 +00:00
RegisterPressure API. Add support for physical register units.
At build-time register pressure was always computed in terms of register units. But the compile-time API was expressed in terms of register classes because it was intended for virtual registers (and physical register units weren't yet used anywhere in codegen). Now that the codegen uses physreg units consistently, prepare for tracking register pressure also in terms of live units, not live registers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169360 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
17cf535199
commit
eca1fcf3d2
@ -599,6 +599,9 @@ public:
|
||||
virtual const RegClassWeight &getRegClassWeight(
|
||||
const TargetRegisterClass *RC) const = 0;
|
||||
|
||||
/// Get the weight in units of pressure for this register unit.
|
||||
virtual unsigned getRegUnitWeight(unsigned RegUnit) const = 0;
|
||||
|
||||
/// Get the number of dimensions of register pressure.
|
||||
virtual unsigned getNumRegPressureSets() const = 0;
|
||||
|
||||
@ -614,6 +617,10 @@ public:
|
||||
virtual const int *getRegClassPressureSets(
|
||||
const TargetRegisterClass *RC) const = 0;
|
||||
|
||||
/// Get the dimensions of register pressure impacted by this register unit.
|
||||
/// Returns a -1 terminated array of pressure set IDs.
|
||||
virtual const int *getRegUnitPressureSets(unsigned RegUnit) const = 0;
|
||||
|
||||
/// Get a list of 'hint' registers that the register allocator should try
|
||||
/// first when allocating a physical register for the virtual register
|
||||
/// VirtReg. These registers are effectively moved to the front of the
|
||||
@ -634,6 +641,28 @@ public:
|
||||
const MachineFunction &MF,
|
||||
const VirtRegMap *VRM = 0) const;
|
||||
|
||||
/// getRawAllocationOrder - Returns the register allocation order for a
|
||||
/// specified register class with a target-dependent hint. The returned list
|
||||
/// may contain reserved registers that cannot be allocated.
|
||||
///
|
||||
/// Register allocators need only call this function to resolve
|
||||
/// target-dependent hints, but it should work without hinting as well.
|
||||
virtual ArrayRef<MCPhysReg>
|
||||
getRawAllocationOrder(const TargetRegisterClass *RC,
|
||||
unsigned HintType, unsigned HintReg,
|
||||
const MachineFunction &MF) const {
|
||||
return RC->getRawAllocationOrder(MF);
|
||||
}
|
||||
|
||||
/// ResolveRegAllocHint - Resolves the specified register allocation hint
|
||||
/// to a physical register. Returns the physical register if it is successful.
|
||||
virtual unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg,
|
||||
const MachineFunction &MF) const {
|
||||
if (Type == 0 && Reg && isPhysicalRegister(Reg))
|
||||
return Reg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// avoidWriteAfterWrite - Return true if the register allocator should avoid
|
||||
/// writing a register from RC in two consecutive instructions.
|
||||
/// This can avoid pipeline stalls on certain architectures.
|
||||
|
@ -1589,6 +1589,35 @@ void CodeGenRegBank::computeRegUnitSets() {
|
||||
}
|
||||
assert(!RegClassUnitSets[RCIdx].empty() && "missing unit set for regclass");
|
||||
}
|
||||
|
||||
// For each register unit, ensure that we have the list of UnitSets that
|
||||
// contain the unit. Normally, this matches an existing list of UnitSets for a
|
||||
// register class. If not, we create a new entry in RegClassUnitSets as a
|
||||
// "fake" register class.
|
||||
for (unsigned UnitIdx = 0, UnitEnd = NumNativeRegUnits;
|
||||
UnitIdx < UnitEnd; ++UnitIdx) {
|
||||
std::vector<unsigned> RUSets;
|
||||
for (unsigned i = 0, e = RegUnitSets.size(); i != e; ++i) {
|
||||
RegUnitSet &RUSet = RegUnitSets[i];
|
||||
if (std::find(RUSet.Units.begin(), RUSet.Units.end(), UnitIdx)
|
||||
== RUSet.Units.end())
|
||||
continue;
|
||||
RUSets.push_back(i);
|
||||
}
|
||||
unsigned RCUnitSetsIdx = 0;
|
||||
for (unsigned e = RegClassUnitSets.size();
|
||||
RCUnitSetsIdx != e; ++RCUnitSetsIdx) {
|
||||
if (RegClassUnitSets[RCUnitSetsIdx] == RUSets) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
RegUnits[UnitIdx].RegClassUnitSetsIdx = RCUnitSetsIdx;
|
||||
if (RCUnitSetsIdx == RegClassUnitSets.size()) {
|
||||
// Create a new list of UnitSets as a "fake" register class.
|
||||
RegClassUnitSets.resize(RCUnitSetsIdx + 1);
|
||||
RegClassUnitSets[RCUnitSetsIdx].swap(RUSets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenRegBank::computeDerivedInfo() {
|
||||
|
@ -403,7 +403,11 @@ namespace llvm {
|
||||
// these two registers and their super-registers.
|
||||
const CodeGenRegister *Roots[2];
|
||||
|
||||
RegUnit() : Weight(0) { Roots[0] = Roots[1] = 0; }
|
||||
// Index into RegClassUnitSets where we can find the list of UnitSets that
|
||||
// contain this unit.
|
||||
unsigned RegClassUnitSetsIdx;
|
||||
|
||||
RegUnit() : Weight(0), RegClassUnitSetsIdx(0) { Roots[0] = Roots[1] = 0; }
|
||||
|
||||
ArrayRef<const CodeGenRegister*> getRoots() const {
|
||||
assert(!(Roots[1] && !Roots[0]) && "Invalid roots array");
|
||||
@ -462,6 +466,10 @@ namespace llvm {
|
||||
|
||||
// Map RegisterClass index to the index of the RegUnitSet that contains the
|
||||
// class's units and any inferred RegUnit supersets.
|
||||
//
|
||||
// NOTE: This could grow beyond the number of register classes when we map
|
||||
// register units to lists of unit sets. If the list of unit sets does not
|
||||
// already exist for a register class, we create a new entry in this vector.
|
||||
std::vector<std::vector<unsigned> > RegClassUnitSets;
|
||||
|
||||
// Add RC to *2RC maps.
|
||||
@ -615,6 +623,13 @@ namespace llvm {
|
||||
return RegUnitSets[Idx];
|
||||
}
|
||||
|
||||
// The number of pressure set lists may be larget than the number of
|
||||
// register classes if some register units appeared in a list of sets that
|
||||
// did not correspond to an existing register class.
|
||||
unsigned getNumRegClassPressureSetLists() const {
|
||||
return RegClassUnitSets.size();
|
||||
}
|
||||
|
||||
// Get a list of pressure set IDs for a register class. Liveness of a
|
||||
// register in this class impacts each pressure set in this list by the
|
||||
// weight of the register. An exact solution requires all registers in a
|
||||
|
@ -185,6 +185,34 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
|
||||
<< " return RCWeightTable[RC->getID()];\n"
|
||||
<< "}\n\n";
|
||||
|
||||
// Reasonable targets (not ARMv7) have unit weight for all units, so don't
|
||||
// bother generating a table.
|
||||
bool RegUnitsHaveUnitWeight = true;
|
||||
for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();
|
||||
UnitIdx < UnitEnd; ++UnitIdx) {
|
||||
if (RegBank.getRegUnit(UnitIdx).Weight > 1)
|
||||
RegUnitsHaveUnitWeight = false;
|
||||
}
|
||||
OS << "/// Get the weight in units of pressure for this register unit.\n"
|
||||
<< "unsigned " << ClassName << "::\n"
|
||||
<< "getRegUnitWeight(unsigned RegUnit) const {\n";
|
||||
if (!RegUnitsHaveUnitWeight) {
|
||||
OS << " static const uint8_t RUWeightTable[] = {\n ";
|
||||
for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();
|
||||
UnitIdx < UnitEnd; ++UnitIdx) {
|
||||
const RegUnit &RU = RegBank.getRegUnit(UnitIdx);
|
||||
assert(RU.Weight < 256 && "RegUnit too heavy");
|
||||
OS << RU.Weight << ", ";
|
||||
}
|
||||
OS << "0 };\n"
|
||||
<< " return RUWeightTable[RegUnit];\n";
|
||||
}
|
||||
else {
|
||||
OS << " // All register units have unit weight.\n"
|
||||
<< " return 1;\n";
|
||||
}
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "\n"
|
||||
<< "// Get the number of dimensions of register pressure.\n"
|
||||
<< "unsigned " << ClassName << "::getNumRegPressureSets() const {\n"
|
||||
@ -215,14 +243,13 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
|
||||
<< " return PressureLimitTable[Idx];\n"
|
||||
<< "}\n\n";
|
||||
|
||||
OS << "/// Get the dimensions of register pressure "
|
||||
<< "impacted by this register class.\n"
|
||||
<< "/// Returns a -1 terminated array of pressure set IDs\n"
|
||||
<< "const int* " << ClassName << "::\n"
|
||||
<< "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"
|
||||
<< " static const int RCSetsTable[] = {\n ";
|
||||
std::vector<unsigned> RCSetStarts(NumRCs);
|
||||
for (unsigned i = 0, StartIdx = 0, e = NumRCs; i != e; ++i) {
|
||||
// This table may be larger than NumRCs if some register units needed a list
|
||||
// of unit sets that did not correspond to a register class.
|
||||
unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists();
|
||||
OS << "/// Table of pressure sets per register class or unit.\n"
|
||||
<< "static const int RCSetsTable[] = {\n ";
|
||||
std::vector<unsigned> RCSetStarts(NumRCUnitSets);
|
||||
for (unsigned i = 0, StartIdx = 0, e = NumRCUnitSets; i != e; ++i) {
|
||||
RCSetStarts[i] = StartIdx;
|
||||
ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i);
|
||||
for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(),
|
||||
@ -230,10 +257,26 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
|
||||
OS << *PSetI << ", ";
|
||||
++StartIdx;
|
||||
}
|
||||
OS << "-1, \t// " << RegBank.getRegClasses()[i]->getName() << "\n ";
|
||||
OS << "-1, \t// #" << RCSetStarts[i] << " ";
|
||||
if (i < NumRCs)
|
||||
OS << RegBank.getRegClasses()[i]->getName();
|
||||
else {
|
||||
OS << "inferred";
|
||||
for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(),
|
||||
PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) {
|
||||
OS << "~" << RegBank.getRegPressureSet(*PSetI).Name;
|
||||
}
|
||||
}
|
||||
OS << "\n ";
|
||||
++StartIdx;
|
||||
}
|
||||
OS << "-1 };\n";
|
||||
OS << "-1 };\n\n";
|
||||
|
||||
OS << "/// Get the dimensions of register pressure impacted by this "
|
||||
<< "register class.\n"
|
||||
<< "/// Returns a -1 terminated array of pressure set IDs\n"
|
||||
<< "const int* " << ClassName << "::\n"
|
||||
<< "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n";
|
||||
OS << " static const unsigned RCSetStartTable[] = {\n ";
|
||||
for (unsigned i = 0, e = NumRCs; i != e; ++i) {
|
||||
OS << RCSetStarts[i] << ",";
|
||||
@ -242,6 +285,21 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
|
||||
<< " unsigned SetListStart = RCSetStartTable[RC->getID()];\n"
|
||||
<< " return &RCSetsTable[SetListStart];\n"
|
||||
<< "}\n\n";
|
||||
|
||||
OS << "/// Get the dimensions of register pressure impacted by this "
|
||||
<< "register unit.\n"
|
||||
<< "/// Returns a -1 terminated array of pressure set IDs\n"
|
||||
<< "const int* " << ClassName << "::\n"
|
||||
<< "getRegUnitPressureSets(unsigned RegUnit) const {\n";
|
||||
OS << " static const unsigned RUSetStartTable[] = {\n ";
|
||||
for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();
|
||||
UnitIdx < UnitEnd; ++UnitIdx) {
|
||||
OS << RCSetStarts[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx] << ",";
|
||||
}
|
||||
OS << "0 };\n"
|
||||
<< " unsigned SetListStart = RUSetStartTable[RegUnit];\n"
|
||||
<< " return &RCSetsTable[SetListStart];\n"
|
||||
<< "}\n\n";
|
||||
}
|
||||
|
||||
void
|
||||
@ -907,11 +965,13 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
|
||||
}
|
||||
OS << " virtual const RegClassWeight &getRegClassWeight("
|
||||
<< "const TargetRegisterClass *RC) const;\n"
|
||||
<< " virtual unsigned getRegUnitWeight(unsigned RegUnit) const;\n"
|
||||
<< " virtual unsigned getNumRegPressureSets() const;\n"
|
||||
<< " virtual const char *getRegPressureSetName(unsigned Idx) const;\n"
|
||||
<< " virtual unsigned getRegPressureSetLimit(unsigned Idx) const;\n"
|
||||
<< " virtual const int *getRegClassPressureSets("
|
||||
<< "const TargetRegisterClass *RC) const;\n"
|
||||
<< " virtual const int *getRegUnitPressureSets(unsigned RegUnit) const;\n"
|
||||
<< "};\n\n";
|
||||
|
||||
ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
|
||||
|
Loading…
Reference in New Issue
Block a user