]> granicus.if.org Git - llvm/commitdiff
[MCA] Return a mask of busy resources from method ResourceManager::checkAvailability...
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Mon, 11 Feb 2019 14:53:04 +0000 (14:53 +0000)
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Mon, 11 Feb 2019 14:53:04 +0000 (14:53 +0000)
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

include/llvm/MCA/HardwareUnits/ResourceManager.h
include/llvm/MCA/HardwareUnits/Scheduler.h
lib/MCA/HardwareUnits/ResourceManager.cpp
lib/MCA/HardwareUnits/Scheduler.cpp

index bf78dec86a99619fa9cd78f72ba7af25033fce01..66272af8a9f08be28a2b12a9204a5828c2b30a39 100644 (file)
@@ -341,6 +341,12 @@ class ResourceManager {
   // before those become usable again.
   SmallDenseMap<ResourceRef, unsigned> 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,
index ae09aef13ffddee5a8b796ef2123fe5fa4dccbf9..53e416b16433117905267c716ea62a499d7fe2e3 100644 (file)
@@ -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;
index 4cad4f40013af0f185318618edb68a51054fcbef..da6bfd5533916cbd4d3bc5ee9ec4126e8a6541f5 100644 (file)
@@ -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<ResourceStrategy> 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<uint64_t> Buffers) {
     Resources[getResourceStateIndex(R)]->releaseBuffer();
 }
 
-bool ResourceManager::canBeIssued(const InstrDesc &Desc) const {
-  return all_of(
-      Desc.Resources, [&](const std::pair<uint64_t, const ResourceUsage> &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<uint64_t, const ResourceUsage> &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(
index 45a43ecb002169d7e6d6ddbb1045b22ea162fc03..fb1080dc02c398309d09b6147b528fa4020690aa 100644 (file)
@@ -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;
     }
   }