MachineModel: Add a ProcResGroup class.

This allows abitrary groups of processor resources. Using something in
a subset automatically counts againts the superset. Currently, this
only works if the superset is also a ProcResGroup as opposed to a
SuperUnit.

This allows SandyBridge to be expressed naturally, which will be
checked in shortly.

def SBPort01 : ProcResGroup<[SBPort0, SBPort1]>;
def SBPort15 : ProcResGroup<[SBPort1, SBPort5]>;
def SBPort23  : ProcResGroup<[SBPort2, SBPort3]>;
def SBPort015 : ProcResGroup<[SBPort0, SBPort1, SBPort5]>;

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177112 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick 2013-03-14 21:21:50 +00:00
parent 0cc52c67db
commit 1754aca83a
3 changed files with 97 additions and 12 deletions

View File

@ -133,6 +133,11 @@ def EponymousProcResourceKind : ProcResourceKind;
class ProcResource<int num> : ProcResourceKind,
ProcResourceUnits<EponymousProcResourceKind, num>;
class ProcResGroup<list<ProcResource> resources> : ProcResourceKind {
list<ProcResource> Resources = resources;
SchedMachineModel SchedModel = ?;
}
// A target architecture may define SchedReadWrite types and associate
// them with instruction operands.
class SchedReadWrite;

View File

@ -1542,6 +1542,20 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
ProcUnitDef = *RI;
}
}
RecVec ProcResGroups = Records.getAllDerivedDefinitions("ProcResGroup");
for (RecIter RI = ProcResGroups.begin(), RE = ProcResGroups.end();
RI != RE; ++RI) {
if (*RI == ProcResKind
&& (*RI)->getValueAsDef("SchedModel") == PM.ModelDef) {
if (ProcUnitDef) {
PrintFatalError((*RI)->getLoc(),
"Multiple ProcessorResourceUnits associated with "
+ ProcResKind->getName());
}
ProcUnitDef = *RI;
}
}
if (!ProcUnitDef) {
PrintFatalError(ProcResKind->getLoc(),
"No ProcessorResources associated with "
@ -1563,6 +1577,9 @@ void CodeGenSchedModels::addProcResource(Record *ProcResKind,
return;
PM.ProcResourceDefs.push_back(ProcResUnits);
if (ProcResUnits->isSubClassOf("ProcResGroup"))
return;
if (!ProcResUnits->getValueInit("Super")->isComplete())
return;

View File

@ -87,6 +87,8 @@ class SubtargetEmitter {
const CodeGenProcModel &ProcModel);
Record *FindReadAdvance(const CodeGenSchedRW &SchedRead,
const CodeGenProcModel &ProcModel);
void ExpandProcResources(RecVec &PRVec, std::vector<int64_t> &Cycles,
const CodeGenProcModel &ProcModel);
void GenSchedClassTables(const CodeGenProcModel &ProcModel,
SchedClassTables &SchedTables);
void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
@ -631,13 +633,29 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
Record *PRDef = ProcModel.ProcResourceDefs[i];
// Find the SuperIdx
unsigned SuperIdx = 0;
Record *SuperDef = 0;
if (PRDef->getValueInit("Super")->isComplete()) {
SuperDef =
SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel);
SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
unsigned SuperIdx = 0;
unsigned NumUnits = 0;
bool IsBuffered = true;
if (PRDef->isSubClassOf("ProcResGroup")) {
RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources");
for (RecIter RUI = ResUnits.begin(), RUE = ResUnits.end();
RUI != RUE; ++RUI) {
if (!NumUnits)
IsBuffered = (*RUI)->getValueAsBit("Buffered");
else if(IsBuffered != (*RUI)->getValueAsBit("Buffered"))
PrintFatalError(PRDef->getLoc(),
"Mixing buffered and unbuffered resources.");
NumUnits += (*RUI)->getValueAsInt("NumUnits");
}
}
else {
// Find the SuperIdx
if (PRDef->getValueInit("Super")->isComplete()) {
SuperDef = SchedModels.findProcResUnits(
PRDef->getValueAsDef("Super"), ProcModel);
SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
}
}
// Emit the ProcResourceDesc
if (i+1 == e)
@ -645,8 +663,8 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
OS << " {DBGFIELD(\"" << PRDef->getName() << "\") ";
if (PRDef->getName().size() < 15)
OS.indent(15 - PRDef->getName().size());
OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx << ", "
<< PRDef->getValueAsBit("Buffered") << "}" << Sep << " // #" << i+1;
OS << NumUnits << ", " << SuperIdx << ", "
<< IsBuffered << "}" << Sep << " // #" << i+1;
if (SuperDef)
OS << ", Super=" << SuperDef->getName();
OS << "\n";
@ -763,6 +781,51 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
return ResDef;
}
// Expand an explicit list of processor resources into a full list of implied
// resource groups that cover them.
//
// FIXME: Effectively consider a super-resource a group that include all of its
// subresources to allow mixing and matching super-resources and groups.
//
// FIXME: Warn if two overlapping groups don't have a common supergroup.
void SubtargetEmitter::ExpandProcResources(RecVec &PRVec,
std::vector<int64_t> &Cycles,
const CodeGenProcModel &ProcModel) {
// Default to 1 resource cycle.
Cycles.resize(PRVec.size(), 1);
for (unsigned i = 0, e = PRVec.size(); i != e; ++i) {
RecVec SubResources;
if (PRVec[i]->isSubClassOf("ProcResGroup")) {
SubResources = PRVec[i]->getValueAsListOfDefs("Resources");
std::sort(SubResources.begin(), SubResources.end(), LessRecord());
}
else {
SubResources.push_back(PRVec[i]);
}
for (RecIter PRI = ProcModel.ProcResourceDefs.begin(),
PRE = ProcModel.ProcResourceDefs.end();
PRI != PRE; ++PRI) {
if (*PRI == PRVec[i] || !(*PRI)->isSubClassOf("ProcResGroup"))
continue;
RecVec SuperResources = (*PRI)->getValueAsListOfDefs("Resources");
std::sort(SuperResources.begin(), SuperResources.end(), LessRecord());
RecIter SubI = SubResources.begin(), SubE = SubResources.end();
RecIter SuperI = SuperResources.begin(), SuperE = SuperResources.end();
for ( ; SubI != SubE && SuperI != SuperE; ++SuperI) {
if (*SubI < *SuperI)
break;
else if (*SuperI < *SubI)
continue;
++SubI;
}
if (SubI == SubE) {
PRVec.push_back(*PRI);
Cycles.push_back(Cycles[i]);
}
}
}
}
// Generate the SchedClass table for this processor and update global
// tables. Must be called for each processor in order.
void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
@ -884,15 +947,15 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
std::vector<int64_t> Cycles =
WriteRes->getValueAsListOfInts("ResourceCycles");
ExpandProcResources(PRVec, Cycles, ProcModel);
for (unsigned PRIdx = 0, PREnd = PRVec.size();
PRIdx != PREnd; ++PRIdx) {
MCWriteProcResEntry WPREntry;
WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
if (Cycles.size() > PRIdx)
WPREntry.Cycles = Cycles[PRIdx];
else
WPREntry.Cycles = 1;
WPREntry.Cycles = Cycles[PRIdx];
// If this resource is already used in this sequence, add the current
// entry's cycles so that the same resource appears to be used
// serially, rather than multiple parallel uses. This is important for