summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/MCA/HardwareUnits/Scheduler.h28
-rw-r--r--llvm/lib/MCA/HardwareUnits/Scheduler.cpp12
-rw-r--r--llvm/lib/MCA/Stages/DispatchStage.cpp5
-rw-r--r--llvm/test/tools/llvm-mca/X86/BtVer2/register-files-4.s2
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
OpenPOWER on IntegriCloud