[llvm] r354490 - [MCA][Scheduler] Collect resource pressure and memory dependency bottlenecks.

Andrea Di Biagio via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 20 10:01:50 PST 2019


Author: adibiagio
Date: Wed Feb 20 10:01:49 2019
New Revision: 354490

URL: http://llvm.org/viewvc/llvm-project?rev=354490&view=rev
Log:
[MCA][Scheduler] Collect resource pressure and memory dependency bottlenecks.

Every cycle, the Scheduler checks if instructions in the ReadySet can be issued
to the underlying pipelines. If an instruction cannot be issued because one or
more pipeline resources are unavailable, then field
Instruction::CriticalResourceMask is updated with the resource identifier of the
unavailable resources.

If an instruction cannot be promoted from the PendingSet to the ReadySet because
of a memory dependency, then field Instruction::CriticalMemDep is updated with
the identifier of the dependending memory instruction.

Bottleneck information is collected after every cycle for instructions that are
waiting to execute. The idea is to help identify causes of bottlenecks; this
information can be used in future to implement a bottleneck analysis.

Modified:
    llvm/trunk/include/llvm/MCA/HardwareUnits/Scheduler.h
    llvm/trunk/include/llvm/MCA/Instruction.h
    llvm/trunk/lib/MCA/HardwareUnits/Scheduler.cpp
    llvm/trunk/lib/MCA/Stages/DispatchStage.cpp
    llvm/trunk/lib/MCA/Stages/ExecuteStage.cpp

Modified: llvm/trunk/include/llvm/MCA/HardwareUnits/Scheduler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MCA/HardwareUnits/Scheduler.h?rev=354490&r1=354489&r2=354490&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MCA/HardwareUnits/Scheduler.h (original)
+++ llvm/trunk/include/llvm/MCA/HardwareUnits/Scheduler.h Wed Feb 20 10:01:49 2019
@@ -120,6 +120,11 @@ class Scheduler : public HardwareUnit {
   // Each bit of the mask represents an unavailable resource.
   uint64_t BusyResourceUnits;
 
+  // Counts the number of instructions dispatched during this cycle that are
+  // added to the pending set. This information is used by the bottleneck
+  // analysis when analyzing instructions in the pending set.
+  unsigned NumDispatchedToThePendingSet;
+
   /// Verify the given selection strategy and set the Strategy member
   /// accordingly.  If no strategy is provided, the DefaultSchedulerStrategy is
   /// used.
@@ -184,11 +189,7 @@ public:
   /// Returns true if instruction IR is ready to be issued to the underlying
   /// pipelines. Note that this operation cannot fail; it assumes that a
   /// previous call to method `isAvailable(IR)` returned `SC_AVAILABLE`.
-  void dispatch(const InstRef &IR);
-
-  /// Returns true if IR is ready to be executed by the underlying pipelines.
-  /// This method assumes that IR has been previously dispatched.
-  bool isReady(const InstRef &IR) const;
+  bool dispatch(const InstRef &IR);
 
   /// Issue an instruction and populates a vector of used pipeline resources,
   /// and a vector of instructions that transitioned to the ready state as a

Modified: llvm/trunk/include/llvm/MCA/Instruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MCA/Instruction.h?rev=354490&r1=354489&r2=354490&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MCA/Instruction.h (original)
+++ llvm/trunk/include/llvm/MCA/Instruction.h Wed Feb 20 10:01:49 2019
@@ -420,6 +420,7 @@ public:
   // Returns true if this instruction is a candidate for move elimination.
   bool isOptimizableMove() const { return IsOptimizableMove; }
   void setOptimizableMove() { IsOptimizableMove = true; }
+  bool isMemOp() const { return Desc.MayLoad || Desc.MayStore; }
 };
 
 /// An instruction propagated through the simulated instruction pipeline.
@@ -447,10 +448,13 @@ class Instruction : public InstructionBa
   // Retire Unit token ID for this instruction.
   unsigned RCUTokenID;
 
+  uint64_t CriticalResourceMask;
+  unsigned CriticalMemDep;
+
 public:
   Instruction(const InstrDesc &D)
       : InstructionBase(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES),
-        RCUTokenID(0) {}
+        RCUTokenID(0), CriticalResourceMask(0), CriticalMemDep(0) {}
 
   unsigned getRCUTokenID() const { return RCUTokenID; }
   int getCyclesLeft() const { return CyclesLeft; }
@@ -495,6 +499,13 @@ public:
     Stage = IS_RETIRED;
   }
 
+  void updateCriticalResourceMask(uint64_t BusyResourceUnits) {
+    CriticalResourceMask |= BusyResourceUnits;
+  }
+  uint64_t getCriticalResourceMask() const { return CriticalResourceMask; }
+  void setCriticalMemDep(unsigned IID) { CriticalMemDep = IID; }
+  unsigned getCriticalMemDep() const { return CriticalMemDep; }
+
   void cycleEvent();
 };
 

Modified: llvm/trunk/lib/MCA/HardwareUnits/Scheduler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MCA/HardwareUnits/Scheduler.cpp?rev=354490&r1=354489&r2=354490&view=diff
==============================================================================
--- llvm/trunk/lib/MCA/HardwareUnits/Scheduler.cpp (original)
+++ llvm/trunk/lib/MCA/HardwareUnits/Scheduler.cpp Wed Feb 20 10:01:49 2019
@@ -109,18 +109,23 @@ bool Scheduler::promoteToReadySet(SmallV
     if (!IR)
       break;
 
-    // Check if this instruction is now ready. In case, force
-    // a transition in state using method 'update()'.
+    // Check if there are still unsolved memory dependencies.
     Instruction &IS = *IR.getInstruction();
-    if (!IS.isReady())
-      IS.updatePending();
+    if (IS.isMemOp()) {
+      unsigned CriticalMemDep = LSU.isReady(IR);
+      if (CriticalMemDep != IR.getSourceIndex()) {
+        IS.setCriticalMemDep(CriticalMemDep);
+        ++I;
+        continue;
+      }
+    }
 
-    // Check if there are still unsolved data dependencies.
-    if (!isReady(IR)) {
+    // Check if this instruction is now ready. In case, force
+    // a transition in state using method 'update()'.
+    if (!IS.isReady() && !IS.updatePending()) {
       ++I;
       continue;
     }
-
     LLVM_DEBUG(dbgs() << "[SCHEDULER]: Instruction #" << IR
                       << " promoted to the READY set.\n");
 
@@ -169,11 +174,12 @@ bool Scheduler::promoteToPendingSet() {
 InstRef Scheduler::select() {
   unsigned QueueIndex = ReadySet.size();
   for (unsigned I = 0, E = ReadySet.size(); I != E; ++I) {
-    const InstRef &IR = ReadySet[I];
+    InstRef &IR = ReadySet[I];
     if (QueueIndex == ReadySet.size() ||
         Strategy->compare(IR, ReadySet[QueueIndex])) {
       const InstrDesc &D = IR.getInstruction()->getDesc();
       uint64_t BusyResourceMask = Resources->checkAvailability(D);
+      IR.getInstruction()->updateCriticalResourceMask(BusyResourceMask);
       BusyResourceUnits |= BusyResourceMask;
       if (!BusyResourceMask)
         QueueIndex = I;
@@ -221,10 +227,8 @@ void Scheduler::cycleEvent(SmallVectorIm
   // Release consumed resources.
   Resources->cycleEvent(Freed);
 
-  // Propagate the cycle event to the 'Issued' and 'Wait' sets.
   for (InstRef &IR : IssuedSet)
     IR.getInstruction()->cycleEvent();
-
   updateIssuedSet(Executed);
 
   for (InstRef &IR : PendingSet)
@@ -236,6 +240,7 @@ void Scheduler::cycleEvent(SmallVectorIm
   promoteToPendingSet();
   promoteToReadySet(Ready);
 
+  NumDispatchedToThePendingSet = 0;
   BusyResourceUnits = 0;
 }
 
@@ -249,26 +254,28 @@ bool Scheduler::mustIssueImmediately(con
   return Desc.MustIssueImmediately;
 }
 
-void Scheduler::dispatch(const InstRef &IR) {
-  const InstrDesc &Desc = IR.getInstruction()->getDesc();
+bool Scheduler::dispatch(const InstRef &IR) {
+  const Instruction &IS = *IR.getInstruction();
+  const InstrDesc &Desc = IS.getDesc();
   Resources->reserveBuffers(Desc.Buffers);
 
   // If necessary, reserve queue entries in the load-store unit (LSU).
-  bool IsMemOp = Desc.MayLoad || Desc.MayStore;
-  if (IsMemOp)
+  if (IS.isMemOp())
     LSU.dispatch(IR);
 
-  if (IR.getInstruction()->isPending()) {
+  if (IS.isPending()) {
     LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR
                       << " to the PendingSet\n");
     PendingSet.push_back(IR);
-    return;
+    ++NumDispatchedToThePendingSet;
+    return false;
   }
 
-  if (!isReady(IR)) {
+  if (!IS.isReady() ||
+      (IS.isMemOp() && LSU.isReady(IR) != IR.getSourceIndex())) {
     LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the WaitSet\n");
     WaitSet.push_back(IR);
-    return;
+    return false;
   }
 
   // Don't add a zero-latency instruction to the Ready queue.
@@ -283,13 +290,8 @@ void Scheduler::dispatch(const InstRef &
     LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the ReadySet\n");
     ReadySet.push_back(IR);
   }
-}
 
-bool Scheduler::isReady(const InstRef &IR) const {
-  const InstrDesc &Desc = IR.getInstruction()->getDesc();
-  bool IsMemOp = Desc.MayLoad || Desc.MayStore;
-  return IR.getInstruction()->isReady() &&
-         (!IsMemOp || LSU.isReady(IR) == IR.getSourceIndex());
+  return true;
 }
 
 } // namespace mca

Modified: llvm/trunk/lib/MCA/Stages/DispatchStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MCA/Stages/DispatchStage.cpp?rev=354490&r1=354489&r2=354490&view=diff
==============================================================================
--- llvm/trunk/lib/MCA/Stages/DispatchStage.cpp (original)
+++ llvm/trunk/lib/MCA/Stages/DispatchStage.cpp Wed Feb 20 10:01:49 2019
@@ -89,6 +89,9 @@ Error DispatchStage::dispatch(InstRef IR
     IsEliminated = PRF.tryEliminateMove(IS.getDefs()[0], IS.getUses()[0]);
   }
 
+  if (IS.isMemOp())
+    IS.setCriticalMemDep(IR.getSourceIndex());
+
   // A dependency-breaking instruction doesn't have to wait on the register
   // input operands, and it is often optimized at register renaming stage.
   // Update RAW dependencies if this instruction is not a dependency-breaking

Modified: llvm/trunk/lib/MCA/Stages/ExecuteStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MCA/Stages/ExecuteStage.cpp?rev=354490&r1=354489&r2=354490&view=diff
==============================================================================
--- llvm/trunk/lib/MCA/Stages/ExecuteStage.cpp (original)
+++ llvm/trunk/lib/MCA/Stages/ExecuteStage.cpp Wed Feb 20 10:01:49 2019
@@ -146,9 +146,9 @@ Error ExecuteStage::execute(InstRef &IR)
   // BufferSize=0 as reserved. Resources with a buffer size of zero will only
   // be released after MCIS is issued, and all the ResourceCycles for those
   // units have been consumed.
-  HWS.dispatch(IR);
+  bool IsReadyInstruction = HWS.dispatch(IR);
   notifyReservedOrReleasedBuffers(IR, /* Reserved */ true);
-  if (!HWS.isReady(IR))
+  if (!IsReadyInstruction)
     return ErrorSuccess();
 
   // If we did not return early, then the scheduler is ready for execution.




More information about the llvm-commits mailing list