summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MCA
diff options
context:
space:
mode:
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2019-02-20 18:01:49 +0000
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2019-02-20 18:01:49 +0000
commit3316eb5bb8025e67415796f657bfae5e5374afae (patch)
treed9c2094ef185ae5e4c7606cdd7c6c8658d4e2da1 /llvm/lib/MCA
parentdca47c659ce24413fc6fed5054c05d519a7e9a82 (diff)
downloadbcm5719-llvm-3316eb5bb8025e67415796f657bfae5e5374afae.tar.gz
bcm5719-llvm-3316eb5bb8025e67415796f657bfae5e5374afae.zip
[MCA][Scheduler] Collect resource pressure and memory dependency bottlenecks.
Every cycle, the Scheduler checks if instructions in the ReadySet can be issued to the underlying pipelines. If an instruction cannot be issued because one or more pipeline resources are unavailable, then field Instruction::CriticalResourceMask is updated with the resource identifier of the unavailable resources. If an instruction cannot be promoted from the PendingSet to the ReadySet because of a memory dependency, then field Instruction::CriticalMemDep is updated with the identifier of the dependending memory instruction. Bottleneck information is collected after every cycle for instructions that are waiting to execute. The idea is to help identify causes of bottlenecks; this information can be used in future to implement a bottleneck analysis. llvm-svn: 354490
Diffstat (limited to 'llvm/lib/MCA')
-rw-r--r--llvm/lib/MCA/HardwareUnits/Scheduler.cpp50
-rw-r--r--llvm/lib/MCA/Stages/DispatchStage.cpp3
-rw-r--r--llvm/lib/MCA/Stages/ExecuteStage.cpp4
3 files changed, 31 insertions, 26 deletions
diff --git a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp
index 33db5d24f64..d3d7234c611 100644
--- a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp
+++ b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp
@@ -109,18 +109,23 @@ bool Scheduler::promoteToReadySet(SmallVectorImpl<InstRef> &Ready) {
if (!IR)
break;
- // Check if this instruction is now ready. In case, force
- // a transition in state using method 'update()'.
+ // Check if there are still unsolved memory dependencies.
Instruction &IS = *IR.getInstruction();
- if (!IS.isReady())
- IS.updatePending();
+ if (IS.isMemOp()) {
+ unsigned CriticalMemDep = LSU.isReady(IR);
+ if (CriticalMemDep != IR.getSourceIndex()) {
+ IS.setCriticalMemDep(CriticalMemDep);
+ ++I;
+ continue;
+ }
+ }
- // Check if there are still unsolved data dependencies.
- if (!isReady(IR)) {
+ // Check if this instruction is now ready. In case, force
+ // a transition in state using method 'update()'.
+ if (!IS.isReady() && !IS.updatePending()) {
++I;
continue;
}
-
LLVM_DEBUG(dbgs() << "[SCHEDULER]: Instruction #" << IR
<< " promoted to the READY set.\n");
@@ -169,11 +174,12 @@ bool Scheduler::promoteToPendingSet() {
InstRef Scheduler::select() {
unsigned QueueIndex = ReadySet.size();
for (unsigned I = 0, E = ReadySet.size(); I != E; ++I) {
- const InstRef &IR = ReadySet[I];
+ InstRef &IR = ReadySet[I];
if (QueueIndex == ReadySet.size() ||
Strategy->compare(IR, ReadySet[QueueIndex])) {
const InstrDesc &D = IR.getInstruction()->getDesc();
uint64_t BusyResourceMask = Resources->checkAvailability(D);
+ IR.getInstruction()->updateCriticalResourceMask(BusyResourceMask);
BusyResourceUnits |= BusyResourceMask;
if (!BusyResourceMask)
QueueIndex = I;
@@ -221,10 +227,8 @@ void Scheduler::cycleEvent(SmallVectorImpl<ResourceRef> &Freed,
// Release consumed resources.
Resources->cycleEvent(Freed);
- // Propagate the cycle event to the 'Issued' and 'Wait' sets.
for (InstRef &IR : IssuedSet)
IR.getInstruction()->cycleEvent();
-
updateIssuedSet(Executed);
for (InstRef &IR : PendingSet)
@@ -236,6 +240,7 @@ void Scheduler::cycleEvent(SmallVectorImpl<ResourceRef> &Freed,
promoteToPendingSet();
promoteToReadySet(Ready);
+ NumDispatchedToThePendingSet = 0;
BusyResourceUnits = 0;
}
@@ -249,26 +254,28 @@ bool Scheduler::mustIssueImmediately(const InstRef &IR) const {
return Desc.MustIssueImmediately;
}
-void Scheduler::dispatch(const InstRef &IR) {
- const InstrDesc &Desc = IR.getInstruction()->getDesc();
+bool Scheduler::dispatch(const InstRef &IR) {
+ const Instruction &IS = *IR.getInstruction();
+ const InstrDesc &Desc = IS.getDesc();
Resources->reserveBuffers(Desc.Buffers);
// If necessary, reserve queue entries in the load-store unit (LSU).
- bool IsMemOp = Desc.MayLoad || Desc.MayStore;
- if (IsMemOp)
+ if (IS.isMemOp())
LSU.dispatch(IR);
- if (IR.getInstruction()->isPending()) {
+ if (IS.isPending()) {
LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR
<< " to the PendingSet\n");
PendingSet.push_back(IR);
- return;
+ ++NumDispatchedToThePendingSet;
+ return false;
}
- if (!isReady(IR)) {
+ if (!IS.isReady() ||
+ (IS.isMemOp() && LSU.isReady(IR) != IR.getSourceIndex())) {
LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the WaitSet\n");
WaitSet.push_back(IR);
- return;
+ return false;
}
// Don't add a zero-latency instruction to the Ready queue.
@@ -283,13 +290,8 @@ void Scheduler::dispatch(const InstRef &IR) {
LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the ReadySet\n");
ReadySet.push_back(IR);
}
-}
-bool Scheduler::isReady(const InstRef &IR) const {
- const InstrDesc &Desc = IR.getInstruction()->getDesc();
- bool IsMemOp = Desc.MayLoad || Desc.MayStore;
- return IR.getInstruction()->isReady() &&
- (!IsMemOp || LSU.isReady(IR) == IR.getSourceIndex());
+ return true;
}
} // namespace mca
diff --git a/llvm/lib/MCA/Stages/DispatchStage.cpp b/llvm/lib/MCA/Stages/DispatchStage.cpp
index a67b4612167..ade20aba018 100644
--- a/llvm/lib/MCA/Stages/DispatchStage.cpp
+++ b/llvm/lib/MCA/Stages/DispatchStage.cpp
@@ -89,6 +89,9 @@ Error DispatchStage::dispatch(InstRef IR) {
IsEliminated = PRF.tryEliminateMove(IS.getDefs()[0], IS.getUses()[0]);
}
+ if (IS.isMemOp())
+ IS.setCriticalMemDep(IR.getSourceIndex());
+
// A dependency-breaking instruction doesn't have to wait on the register
// input operands, and it is often optimized at register renaming stage.
// Update RAW dependencies if this instruction is not a dependency-breaking
diff --git a/llvm/lib/MCA/Stages/ExecuteStage.cpp b/llvm/lib/MCA/Stages/ExecuteStage.cpp
index 9e0bd26e6d0..27ac8f8306b 100644
--- a/llvm/lib/MCA/Stages/ExecuteStage.cpp
+++ b/llvm/lib/MCA/Stages/ExecuteStage.cpp
@@ -146,9 +146,9 @@ Error ExecuteStage::execute(InstRef &IR) {
// BufferSize=0 as reserved. Resources with a buffer size of zero will only
// be released after MCIS is issued, and all the ResourceCycles for those
// units have been consumed.
- HWS.dispatch(IR);
+ bool IsReadyInstruction = HWS.dispatch(IR);
notifyReservedOrReleasedBuffers(IR, /* Reserved */ true);
- if (!HWS.isReady(IR))
+ if (!IsReadyInstruction)
return ErrorSuccess();
// If we did not return early, then the scheduler is ready for execution.
OpenPOWER on IntegriCloud