diff --git a/llvm/tools/llvm-mca/Dispatch.cpp b/llvm/tools/llvm-mca/Dispatch.cpp index ce329b4a00d8..d3efe69b89b6 100644 --- a/llvm/tools/llvm-mca/Dispatch.cpp +++ b/llvm/tools/llvm-mca/Dispatch.cpp @@ -362,27 +362,7 @@ bool DispatchUnit::checkRCU(unsigned Index, const InstrDesc &Desc) { } bool DispatchUnit::checkScheduler(unsigned Index, const InstrDesc &Desc) { - // If this is a zero-latency instruction, then it bypasses - // the scheduler. - HWStallEvent::GenericEventType Type = HWStallEvent::Invalid; - switch (SC->canBeDispatched(Desc)) { - case Scheduler::HWS_AVAILABLE: - return true; - case Scheduler::HWS_QUEUE_UNAVAILABLE: - Type = HWStallEvent::SchedulerQueueFull; - break; - case Scheduler::HWS_LD_QUEUE_UNAVAILABLE: - Type = HWStallEvent::LoadQueueFull; - break; - case Scheduler::HWS_ST_QUEUE_UNAVAILABLE: - Type = HWStallEvent::StoreQueueFull; - break; - case Scheduler::HWS_DISPATCH_GROUP_RESTRICTION: - Type = HWStallEvent::DispatchGroupStall; - } - - Owner->notifyStallEvent(HWStallEvent(Type, Index)); - return false; + return SC->canBeDispatched(Index, Desc); } void DispatchUnit::updateRAWDependencies(ReadState &RS, diff --git a/llvm/tools/llvm-mca/HWEventListener.h b/llvm/tools/llvm-mca/HWEventListener.h index a7949121595e..f6f5fc6763d3 100644 --- a/llvm/tools/llvm-mca/HWEventListener.h +++ b/llvm/tools/llvm-mca/HWEventListener.h @@ -97,6 +97,7 @@ public: // Generic stall events generated by the DispatchUnit. RegisterFileStall, RetireControlUnitStall, + // Generic stall events generated by the Scheduler. DispatchGroupStall, SchedulerQueueFull, LoadQueueFull, diff --git a/llvm/tools/llvm-mca/Scheduler.cpp b/llvm/tools/llvm-mca/Scheduler.cpp index c77d4b819680..6d746cb5609e 100644 --- a/llvm/tools/llvm-mca/Scheduler.cpp +++ b/llvm/tools/llvm-mca/Scheduler.cpp @@ -308,24 +308,26 @@ void Scheduler::dump() const { } #endif -Scheduler::Event Scheduler::canBeDispatched(const InstrDesc &Desc) const { - if (Desc.MayLoad && LSU->isLQFull()) - return HWS_LD_QUEUE_UNAVAILABLE; - if (Desc.MayStore && LSU->isSQFull()) - return HWS_ST_QUEUE_UNAVAILABLE; +bool Scheduler::canBeDispatched(unsigned Index, const InstrDesc &Desc) const { + HWStallEvent::GenericEventType Type = HWStallEvent::Invalid; - Scheduler::Event Event; - switch (Resources->canBeDispatched(Desc.Buffers)) { - case ResourceStateEvent::RS_BUFFER_AVAILABLE: - Event = HWS_AVAILABLE; - break; - case ResourceStateEvent::RS_BUFFER_UNAVAILABLE: - Event = HWS_QUEUE_UNAVAILABLE; - break; - case ResourceStateEvent::RS_RESERVED: - Event = HWS_DISPATCH_GROUP_RESTRICTION; + if (Desc.MayLoad && LSU->isLQFull()) + Type = HWStallEvent::LoadQueueFull; + else if (Desc.MayStore && LSU->isSQFull()) + Type = HWStallEvent::StoreQueueFull; + else { + switch (Resources->canBeDispatched(Desc.Buffers)) { + default: return true; + case ResourceStateEvent::RS_BUFFER_UNAVAILABLE: + Type = HWStallEvent::SchedulerQueueFull; + break; + case ResourceStateEvent::RS_RESERVED: + Type = HWStallEvent::DispatchGroupStall; + } } - return Event; + + Owner->notifyStallEvent(HWStallEvent(Type, Index)); + return false; } void Scheduler::issueInstruction(Instruction &IS, unsigned InstrIndex) { diff --git a/llvm/tools/llvm-mca/Scheduler.h b/llvm/tools/llvm-mca/Scheduler.h index ad73fc7979cc..9f9422c3f1ab 100644 --- a/llvm/tools/llvm-mca/Scheduler.h +++ b/llvm/tools/llvm-mca/Scheduler.h @@ -454,42 +454,14 @@ public: void setDispatchUnit(DispatchUnit *DispUnit) { DU = DispUnit; } - /// Scheduling events. + /// Check if instruction at index Idx can be dispatched. /// /// The DispatchUnit is responsible for querying the Scheduler before /// dispatching new instructions. Queries are performed through method - /// `Scheduler::CanBeDispatched`, which returns an instance of this enum to - /// tell if the dispatch would fail or not. If scheduling resources are - /// available, and the instruction can be dispatched, then the query returns - /// HWS_AVAILABLE. A values different than HWS_AVAILABLE means that the - /// instruction cannot be dispatched during this cycle. - /// - /// Each event name starts with prefix "HWS_", and it is followed by - /// a substring which describes the reason why the Scheduler was unavailable - /// (or "AVAILABLE" if the instruction is allowed to be dispatched). - /// - /// HWS_QUEUE_UNAVAILABLE is returned if there are not enough available slots - /// in the scheduler's queue. That means, one (or more) buffered resources - /// consumed by the instruction were full. - /// - /// HWS_LD_QUEUE_UNAVAILABLE is returned when an instruction 'mayLoad', and - /// the load queue in the load/store unit (implemented by class LSUnit) is - /// full. Similarly, HWS_ST_QUEUE_UNAVAILABLE is returned when the store - /// queue is full, and the instruction to be dispatched 'mayStore'. - /// - /// HWS_DISPATCH_GROUP_RESTRICTION is only returned in special cases where the - /// instruction consumes an in-order issue/dispatch resource (i.e. a resource - /// with `BufferSize=0`), and the pipeline resource is not immediately - /// available. - enum Event { - HWS_AVAILABLE, - HWS_QUEUE_UNAVAILABLE, - HWS_DISPATCH_GROUP_RESTRICTION, - HWS_LD_QUEUE_UNAVAILABLE, - HWS_ST_QUEUE_UNAVAILABLE - }; - - Event canBeDispatched(const InstrDesc &Desc) const; + /// `Scheduler::CanBeDispatched`. If scheduling resources are available, + /// and the instruction can be dispatched, then this method returns true. + /// Otherwise, a generic HWStallEvent is notified to the listeners. + bool canBeDispatched(unsigned Idx, const InstrDesc &Desc) const; void scheduleInstruction(unsigned Idx, Instruction &MCIS); void cycleEvent(unsigned Cycle);