From c032e2ab7cda80a2b68345801162746eb48770c0 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Tue, 26 Feb 2019 14:19:00 +0000 Subject: [PATCH] [MCA] Always check if scheduler resources are unavailable when reporting dispatch stalls. 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 | 28 ++++++++++++---------- llvm/lib/MCA/HardwareUnits/Scheduler.cpp | 12 +++++++--- llvm/lib/MCA/Stages/DispatchStage.cpp | 5 +++- .../tools/llvm-mca/X86/BtVer2/register-files-4.s | 2 +- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/llvm/include/llvm/MCA/HardwareUnits/Scheduler.h b/llvm/include/llvm/MCA/HardwareUnits/Scheduler.h index 33caf9f..429d656 100644 --- a/llvm/include/llvm/MCA/HardwareUnits/Scheduler.h +++ b/llvm/include/llvm/MCA/HardwareUnits/Scheduler.h @@ -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 RM, LSUnit &Lsu, std::unique_ptr 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; diff --git a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp index d3d7234..1a428ac 100644 --- a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp +++ b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp @@ -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: diff --git a/llvm/lib/MCA/Stages/DispatchStage.cpp b/llvm/lib/MCA/Stages/DispatchStage.cpp index ade20ab..ae3d3fd 100644 --- a/llvm/lib/MCA/Stages/DispatchStage.cpp +++ b/llvm/lib/MCA/Stages/DispatchStage.cpp @@ -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) { diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-4.s b/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-4.s index 0291ef2..6dfb87f 100644 --- a/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-4.s +++ b/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-4.s @@ -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 -- 2.7.4