[MCA] Improved handling of in-order issue/dispatch resources.

Added field 'MustIssueImmediately' to the instruction descriptor of instructions
that only consume in-order issue/dispatch processor resources.
This speeds up queries from the hardware Scheduler, and gives an average ~5%
speedup on a release build.

No functional change intended.

llvm-svn: 350397
This commit is contained in:
Andrea Di Biagio 2019-01-04 15:08:38 +00:00
parent 7ee2285625
commit 3f4b54850f
5 changed files with 19 additions and 25 deletions

View File

@ -389,10 +389,6 @@ public:
// Release a previously reserved processor resource.
void releaseResource(uint64_t ResourceID);
// Returns true if all resources are in-order, and there is at least one
// resource which is a dispatch hazard (BufferSize = 0).
bool mustIssueImmediately(const InstrDesc &Desc) const;
bool canBeIssued(const InstrDesc &Desc) const;
void issueInstruction(

View File

@ -337,6 +337,10 @@ struct InstrDesc {
bool BeginGroup;
bool EndGroup;
// True if all buffered resources are in-order, and there is at least one
// buffer which is a dispatch hazard (BufferSize = 0).
bool MustIssueImmediately;
// A zero latency instruction doesn't consume any scheduler resources.
bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }

View File

@ -267,24 +267,6 @@ bool ResourceManager::canBeIssued(const InstrDesc &Desc) const {
});
}
// Returns true if all resources are in-order, and there is at least one
// resource which is a dispatch hazard (BufferSize = 0).
bool ResourceManager::mustIssueImmediately(const InstrDesc &Desc) const {
if (!canBeIssued(Desc))
return false;
bool AllInOrderResources = all_of(Desc.Buffers, [&](uint64_t BufferMask) {
unsigned Index = getResourceStateIndex(BufferMask);
const ResourceState &Resource = *Resources[Index];
return Resource.isInOrder() || Resource.isADispatchHazard();
});
if (!AllInOrderResources)
return false;
return any_of(Desc.Buffers, [&](uint64_t BufferMask) {
return Resources[getResourceStateIndex(BufferMask)]->isADispatchHazard();
});
}
void ResourceManager::issueInstruction(
const InstrDesc &Desc,
SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &Pipes) {

View File

@ -199,11 +199,13 @@ void Scheduler::cycleEvent(SmallVectorImpl<ResourceRef> &Freed,
}
bool Scheduler::mustIssueImmediately(const InstRef &IR) const {
const InstrDesc &Desc = IR.getInstruction()->getDesc();
if (Desc.isZeroLatency())
return true;
// Instructions that use an in-order dispatch/issue processor resource must be
// issued immediately to the pipeline(s). Any other in-order buffered
// resources (i.e. BufferSize=1) is consumed.
const InstrDesc &Desc = IR.getInstruction()->getDesc();
return Desc.isZeroLatency() || Resources->mustIssueImmediately(Desc);
return Desc.MustIssueImmediately;
}
void Scheduler::dispatch(const InstRef &IR) {

View File

@ -59,12 +59,20 @@ static void initializeUsedResources(InstrDesc &ID,
unsigned NumProcResources = SM.getNumProcResourceKinds();
APInt Buffers(NumProcResources, 0);
bool AllInOrderResources = true;
bool AnyDispatchHazards = false;
for (unsigned I = 0, E = SCDesc.NumWriteProcResEntries; I < E; ++I) {
const MCWriteProcResEntry *PRE = STI.getWriteProcResBegin(&SCDesc) + I;
const MCProcResourceDesc &PR = *SM.getProcResource(PRE->ProcResourceIdx);
uint64_t Mask = ProcResourceMasks[PRE->ProcResourceIdx];
if (PR.BufferSize != -1)
if (PR.BufferSize < 0) {
AllInOrderResources = false;
} else {
Buffers.setBit(PRE->ProcResourceIdx);
AnyDispatchHazards |= (PR.BufferSize == 0);
AllInOrderResources &= (PR.BufferSize <= 1);
}
CycleSegment RCy(0, PRE->Cycles, false);
Worklist.emplace_back(ResourcePlusCycles(Mask, ResourceUsage(RCy)));
if (PR.SuperIdx) {
@ -73,6 +81,8 @@ static void initializeUsedResources(InstrDesc &ID,
}
}
ID.MustIssueImmediately = AllInOrderResources && AnyDispatchHazards;
// Sort elements by mask popcount, so that we prioritize resource units over
// resource groups, and smaller groups over larger groups.
sort(Worklist, [](const ResourcePlusCycles &A, const ResourcePlusCycles &B) {