diff options
-rw-r--r-- | llvm/include/llvm/MCA/HardwareUnits/Scheduler.h | 28 | ||||
-rw-r--r-- | llvm/lib/MCA/HardwareUnits/Scheduler.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/MCA/Stages/DispatchStage.cpp | 5 | ||||
-rw-r--r-- | llvm/test/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 33caf9fcc80..429d656a85d 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<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; diff --git a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp index d3d7234c611..1a428ac10a0 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 ade20aba018..ae3d3fd6743 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 0291ef2ea2b..6dfb87f15be 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 |