From 00bde103cd412e5f1856709542f5e81049245231 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Mon, 11 Feb 2019 14:53:04 +0000 Subject: [PATCH] [MCA] Return a mask of busy resources from method ResourceManager::checkAvailability(). NFCI In case of bottlenecks caused by pipeline pressure, we want to be able to correctly report the set of problematic pipelines. This is a first step towards adding support for bottleneck hints in llvm-mca (see PR37494). No functional change intended. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353706 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../llvm/MCA/HardwareUnits/ResourceManager.h | 15 +++++++++- include/llvm/MCA/HardwareUnits/Scheduler.h | 6 ++++ lib/MCA/HardwareUnits/ResourceManager.cpp | 30 +++++++++++++------ lib/MCA/HardwareUnits/Scheduler.cpp | 3 +- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/include/llvm/MCA/HardwareUnits/ResourceManager.h b/include/llvm/MCA/HardwareUnits/ResourceManager.h index bf78dec86a9..66272af8a9f 100644 --- a/include/llvm/MCA/HardwareUnits/ResourceManager.h +++ b/include/llvm/MCA/HardwareUnits/ResourceManager.h @@ -341,6 +341,12 @@ class ResourceManager { // before those become usable again. SmallDenseMap BusyResources; + // Set of processor resource units available on the target. + uint64_t ProcResUnitMask; + + // Set of processor resource units that are available during this cycle. + uint64_t AvailableProcResUnits; + // Returns the actual resource unit that will be used. ResourceRef selectPipe(uint64_t ResourceID); @@ -388,7 +394,14 @@ public: // Release a previously reserved processor resource. void releaseResource(uint64_t ResourceID); - bool canBeIssued(const InstrDesc &Desc) const; + // Returns a zero mask if resources requested by Desc are all available during + // this cycle. It returns a non-zero mask value only if there are unavailable + // processor resources; each bit set in the mask represents a busy processor + // resource unit. + uint64_t checkAvailability(const InstrDesc &Desc) const; + + uint64_t getProcResUnitMask() const { return ProcResUnitMask; } + uint64_t getAvailableProcResUnits() const { return AvailableProcResUnits; } void issueInstruction( const InstrDesc &Desc, diff --git a/include/llvm/MCA/HardwareUnits/Scheduler.h b/include/llvm/MCA/HardwareUnits/Scheduler.h index ae09aef13ff..53e416b1643 100644 --- a/include/llvm/MCA/HardwareUnits/Scheduler.h +++ b/include/llvm/MCA/HardwareUnits/Scheduler.h @@ -194,6 +194,12 @@ public: /// resources are not available. InstRef select(); + bool arePipelinesFullyUsed() const { + return !Resources->getAvailableProcResUnits(); + } + bool isReadySetEmpty() const { return ReadySet.empty(); } + bool isWaitSetEmpty() const { return WaitSet.empty(); } + #ifndef NDEBUG // Update the ready queues. void dump() const; diff --git a/lib/MCA/HardwareUnits/ResourceManager.cpp b/lib/MCA/HardwareUnits/ResourceManager.cpp index 4cad4f40013..da6bfd55339 100644 --- a/lib/MCA/HardwareUnits/ResourceManager.cpp +++ b/lib/MCA/HardwareUnits/ResourceManager.cpp @@ -118,7 +118,8 @@ ResourceManager::ResourceManager(const MCSchedModel &SM) : Resources(SM.getNumProcResourceKinds()), Strategies(SM.getNumProcResourceKinds()), Resource2Groups(SM.getNumProcResourceKinds(), 0), - ProcResID2Mask(SM.getNumProcResourceKinds()) { + ProcResID2Mask(SM.getNumProcResourceKinds()), + ProcResUnitMask(0) { computeProcResourceMasks(SM, ProcResID2Mask); for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) { @@ -133,8 +134,10 @@ ResourceManager::ResourceManager(const MCSchedModel &SM) uint64_t Mask = ProcResID2Mask[I]; unsigned Index = getResourceStateIndex(Mask); const ResourceState &RS = *Resources[Index]; - if (!RS.isAResourceGroup()) + if (!RS.isAResourceGroup()) { + ProcResUnitMask |= Mask; continue; + } uint64_t GroupMaskIdx = 1ULL << (Index - 1); Mask -= GroupMaskIdx; @@ -146,6 +149,8 @@ ResourceManager::ResourceManager(const MCSchedModel &SM) Mask ^= Unit; } } + + AvailableProcResUnits = ProcResUnitMask; } void ResourceManager::setCustomStrategyImpl(std::unique_ptr S, @@ -199,6 +204,8 @@ void ResourceManager::use(const ResourceRef &RR) { if (RS.isReady()) return; + AvailableProcResUnits ^= RR.first; + // Notify groups that RR.first is no longer available. uint64_t Users = Resource2Groups[RSID]; while (Users) { @@ -220,6 +227,8 @@ void ResourceManager::release(const ResourceRef &RR) { if (!WasFullyUsed) return; + AvailableProcResUnits ^= RR.first; + // Notify groups that RR.first is now available again. uint64_t Users = Resource2Groups[RSID]; while (Users) { @@ -260,13 +269,16 @@ void ResourceManager::releaseBuffers(ArrayRef Buffers) { Resources[getResourceStateIndex(R)]->releaseBuffer(); } -bool ResourceManager::canBeIssued(const InstrDesc &Desc) const { - return all_of( - Desc.Resources, [&](const std::pair &E) { - unsigned NumUnits = E.second.isReserved() ? 0U : E.second.NumUnits; - unsigned Index = getResourceStateIndex(E.first); - return Resources[Index]->isReady(NumUnits); - }); +uint64_t ResourceManager::checkAvailability(const InstrDesc &Desc) const { + uint64_t BusyResourceMask = 0; + for (const std::pair &E : Desc.Resources) { + unsigned NumUnits = E.second.isReserved() ? 0U : E.second.NumUnits; + unsigned Index = getResourceStateIndex(E.first); + if (!Resources[Index]->isReady(NumUnits)) + BusyResourceMask |= E.first; + } + + return BusyResourceMask & ProcResUnitMask; } void ResourceManager::issueInstruction( diff --git a/lib/MCA/HardwareUnits/Scheduler.cpp b/lib/MCA/HardwareUnits/Scheduler.cpp index 45a43ecb002..fb1080dc02c 100644 --- a/lib/MCA/HardwareUnits/Scheduler.cpp +++ b/lib/MCA/HardwareUnits/Scheduler.cpp @@ -139,7 +139,8 @@ InstRef Scheduler::select() { if (QueueIndex == ReadySet.size() || Strategy->compare(IR, ReadySet[QueueIndex])) { const InstrDesc &D = IR.getInstruction()->getDesc(); - if (Resources->canBeIssued(D)) + uint64_t BusyResourceMask = Resources->checkAvailability(D); + if (!BusyResourceMask) QueueIndex = I; } } -- 2.40.0