[MCA] Always check if scheduler resources are unavailable when reporting dispatch...
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Tue, 26 Feb 2019 14:19:00 +0000 (14:19 +0000)
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Tue, 26 Feb 2019 14:19:00 +0000 (14:19 +0000)
Dispatch stall cycles may be associated to multiple dispatch stall events.
Before this patch, each stall cycle was associated with a single stall event.
This patch also improves a couple of code comments, and adds a helper method to
query the Scheduler for dispatch stalls.

llvm-svn: 354877

llvm/include/llvm/MCA/HardwareUnits/Scheduler.h
llvm/lib/MCA/HardwareUnits/Scheduler.cpp
llvm/lib/MCA/Stages/DispatchStage.cpp
llvm/test/tools/llvm-mca/X86/BtVer2/register-files-4.s

index 33caf9f..429d656 100644 (file)
@@ -120,11 +120,14 @@ 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.
+  // Counts the number of instructions in the pending set that were dispatched
+  // during this cycle.
   unsigned NumDispatchedToThePendingSet;
 
+  // True if the previous pipeline Stage was unable to dispatch a full group of
+  // opcodes because scheduler buffers (or LS queues) were unavailable.
+  bool HadTokenStall;
+
   /// Verify the given selection strategy and set the Strategy member
   /// accordingly.  If no strategy is provided, the DefaultSchedulerStrategy is
   /// used.
@@ -161,7 +164,7 @@ public:
   Scheduler(std::unique_ptr<ResourceManager> RM, LSUnit &Lsu,
             std::unique_ptr<SchedulerStrategy> SelectStrategy)
       : LSU(Lsu), Resources(std::move(RM)), BusyResourceUnits(0),
-        NumDispatchedToThePendingSet(0) {
+        NumDispatchedToThePendingSet(0), HadTokenStall(false) {
     initializeStrategy(std::move(SelectStrategy));
   }
 
@@ -174,15 +177,12 @@ public:
     SC_DISPATCH_GROUP_STALL,
   };
 
-  /// Check if the instruction in 'IR' can be dispatched and returns an answer
-  /// in the form of a Status value.
+  /// Check if the instruction in 'IR' can be dispatched during this cycle.
+  /// Return SC_AVAILABLE if both scheduler and LS resources are available.
   ///
-  /// The DispatchStage is responsible for querying the Scheduler before
-  /// dispatching new instructions. This routine is used for performing such
-  /// a query.  If the instruction 'IR' can be dispatched, then true is
-  /// returned, otherwise false is returned with Event set to the stall type.
-  /// Internally, it also checks if the load/store unit is available.
-  Status isAvailable(const InstRef &IR) const;
+  /// This method internally sets field HadTokenStall based on the Scheduler
+  /// Status value.
+  Status isAvailable(const InstRef &IR);
 
   /// Reserves buffer and LSUnit queue resources that are necessary to issue
   /// this instruction.
@@ -235,6 +235,10 @@ public:
   bool isReadySetEmpty() const { return ReadySet.empty(); }
   bool isWaitSetEmpty() const { return WaitSet.empty(); }
 
+  // Returns true if the dispatch logic couldn't dispatch a full group due to
+  // unavailable scheduler and/or LS resources.
+  bool hadTokenStall() const { return HadTokenStall; }
+
 #ifndef NDEBUG
   // Update the ready queues.
   void dump() const;
index d3d7234..1a428ac 100644 (file)
@@ -37,10 +37,13 @@ void Scheduler::dump() const {
 }
 #endif
 
-Scheduler::Status Scheduler::isAvailable(const InstRef &IR) const {
+Scheduler::Status Scheduler::isAvailable(const InstRef &IR) {
   const InstrDesc &Desc = IR.getInstruction()->getDesc();
 
-  switch (Resources->canBeDispatched(Desc.Buffers)) {
+  ResourceStateEvent RSE = Resources->canBeDispatched(Desc.Buffers);
+  HadTokenStall = RSE != RS_BUFFER_AVAILABLE;
+
+  switch (RSE) {
   case ResourceStateEvent::RS_BUFFER_UNAVAILABLE:
     return Scheduler::SC_BUFFERS_FULL;
   case ResourceStateEvent::RS_RESERVED:
@@ -50,7 +53,10 @@ Scheduler::Status Scheduler::isAvailable(const InstRef &IR) const {
   }
 
   // Give lower priority to LSUnit stall events.
-  switch (LSU.isAvailable(IR)) {
+  LSUnit::Status LSS = LSU.isAvailable(IR);
+  HadTokenStall = LSS != LSUnit::LSU_AVAILABLE;
+
+  switch (LSS) {
   case LSUnit::LSU_LQUEUE_FULL:
     return Scheduler::SC_LOAD_QUEUE_FULL;
   case LSUnit::LSU_SQUEUE_FULL:
index ade20ab..ae3d3fd 100644 (file)
@@ -59,7 +59,10 @@ bool DispatchStage::checkRCU(const InstRef &IR) const {
 }
 
 bool DispatchStage::canDispatch(const InstRef &IR) const {
-  return checkRCU(IR) && checkPRF(IR) && checkNextStage(IR);
+  bool CanDispatch = checkRCU(IR);
+  CanDispatch &= checkPRF(IR);
+  CanDispatch &= checkNextStage(IR);
+  return CanDispatch;
 }
 
 Error DispatchStage::dispatch(InstRef IR) {
index 0291ef2..6dfb87f 100644 (file)
@@ -27,7 +27,7 @@ idiv %eax
 # CHECK:      Dynamic Dispatch Stall Cycles:
 # CHECK-NEXT: RAT     - Register unavailable:                      6  (1.1%)
 # CHECK-NEXT: RCU     - Retire tokens unavailable:                 0
-# CHECK-NEXT: SCHEDQ  - Scheduler full:                            0
+# CHECK-NEXT: SCHEDQ  - Scheduler full:                            5  (0.9%)
 # CHECK-NEXT: LQ      - Load queue full:                           0
 # CHECK-NEXT: SQ      - Store queue full:                          0
 # CHECK-NEXT: GROUP   - Static restrictions on the dispatch group: 0