diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/MCA/Context.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/MCA/HardwareUnits/Scheduler.cpp | 28 | ||||
| -rw-r--r-- | llvm/lib/MCA/Stages/ExecuteStage.cpp | 43 |
3 files changed, 70 insertions, 4 deletions
diff --git a/llvm/lib/MCA/Context.cpp b/llvm/lib/MCA/Context.cpp index 18489ccdf1f..8de675389df 100644 --- a/llvm/lib/MCA/Context.cpp +++ b/llvm/lib/MCA/Context.cpp @@ -42,7 +42,8 @@ Context::createDefaultPipeline(const PipelineOptions &Opts, InstrBuilder &IB, auto Fetch = llvm::make_unique<EntryStage>(SrcMgr); auto Dispatch = llvm::make_unique<DispatchStage>(STI, MRI, Opts.DispatchWidth, *RCU, *PRF); - auto Execute = llvm::make_unique<ExecuteStage>(*HWS); + auto Execute = + llvm::make_unique<ExecuteStage>(*HWS, Opts.EnableBottleneckAnalysis); auto Retire = llvm::make_unique<RetireStage>(*RCU, *PRF); // Pass the ownership of all the hardware units to this Context. diff --git a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp index 1a428ac10a0..5b2527b886e 100644 --- a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp +++ b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp @@ -183,9 +183,9 @@ InstRef Scheduler::select() { 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); + Instruction &IS = *IR.getInstruction(); + uint64_t BusyResourceMask = Resources->checkAvailability(IS.getDesc()); + IS.setCriticalResourceMask(BusyResourceMask); BusyResourceUnits |= BusyResourceMask; if (!BusyResourceMask) QueueIndex = I; @@ -227,6 +227,28 @@ void Scheduler::updateIssuedSet(SmallVectorImpl<InstRef> &Executed) { IssuedSet.resize(IssuedSet.size() - RemovedElements); } +uint64_t Scheduler::analyzeResourcePressure(SmallVectorImpl<InstRef> &Insts) { + Insts.insert(Insts.end(), ReadySet.begin(), ReadySet.end()); + return BusyResourceUnits; +} + +void Scheduler::analyzeDataDependencies(SmallVectorImpl<InstRef> &RegDeps, + SmallVectorImpl<InstRef> &MemDeps) { + const auto EndIt = PendingSet.end() - NumDispatchedToThePendingSet; + for (InstRef &IR : make_range(PendingSet.begin(), EndIt)) { + Instruction &IS = *IR.getInstruction(); + if (Resources->checkAvailability(IS.getDesc())) + continue; + + if (IS.isReady() || + (IS.isMemOp() && LSU.isReady(IR) != IR.getSourceIndex())) { + MemDeps.emplace_back(IR); + } else { + RegDeps.emplace_back(IR); + } + } +} + void Scheduler::cycleEvent(SmallVectorImpl<ResourceRef> &Freed, SmallVectorImpl<InstRef> &Executed, SmallVectorImpl<InstRef> &Ready) { diff --git a/llvm/lib/MCA/Stages/ExecuteStage.cpp b/llvm/lib/MCA/Stages/ExecuteStage.cpp index 27ac8f8306b..49210e06cd4 100644 --- a/llvm/lib/MCA/Stages/ExecuteStage.cpp +++ b/llvm/lib/MCA/Stages/ExecuteStage.cpp @@ -54,6 +54,7 @@ Error ExecuteStage::issueInstruction(InstRef &IR) { SmallVector<std::pair<ResourceRef, ResourceCycles>, 4> Used; SmallVector<InstRef, 4> Ready; HWS.issueInstruction(IR, Used, Ready); + NumIssuedOpcodes += IR.getInstruction()->getDesc().NumMicroOps; notifyReservedOrReleasedBuffers(IR, /* Reserved */ false); @@ -89,6 +90,8 @@ Error ExecuteStage::cycleStart() { SmallVector<InstRef, 4> Ready; HWS.cycleEvent(Freed, Executed, Ready); + NumDispatchedOpcodes = 0; + NumIssuedOpcodes = 0; for (const ResourceRef &RR : Freed) notifyResourceAvailable(RR); @@ -106,6 +109,45 @@ Error ExecuteStage::cycleStart() { return issueReadyInstructions(); } +Error ExecuteStage::cycleEnd() { + if (!EnablePressureEvents) + return ErrorSuccess(); + + // Always conservatively report any backpressure events if the dispatch logic + // was stalled due to unavailable scheduler resources. + if (!HWS.hadTokenStall() && NumDispatchedOpcodes <= NumIssuedOpcodes) + return ErrorSuccess(); + + SmallVector<InstRef, 8> Insts; + uint64_t Mask = HWS.analyzeResourcePressure(Insts); + if (Mask) { + LLVM_DEBUG(dbgs() << "[E] Backpressure increased because of unavailable " + "pipeline resources: " + << format_hex(Mask, 16) << '\n'); + HWPressureEvent Ev(HWPressureEvent::RESOURCES, Insts, Mask); + notifyEvent(Ev); + return ErrorSuccess(); + } + + SmallVector<InstRef, 8> RegDeps; + SmallVector<InstRef, 8> MemDeps; + HWS.analyzeDataDependencies(RegDeps, MemDeps); + if (RegDeps.size()) { + LLVM_DEBUG( + dbgs() << "[E] Backpressure increased by register dependencies\n"); + HWPressureEvent Ev(HWPressureEvent::REGISTER_DEPS, RegDeps); + notifyEvent(Ev); + } + + if (MemDeps.size()) { + LLVM_DEBUG(dbgs() << "[E] Backpressure increased by memory dependencies\n"); + HWPressureEvent Ev(HWPressureEvent::MEMORY_DEPS, MemDeps); + notifyEvent(Ev); + } + + return ErrorSuccess(); +} + #ifndef NDEBUG static void verifyInstructionEliminated(const InstRef &IR) { const Instruction &Inst = *IR.getInstruction(); @@ -147,6 +189,7 @@ Error ExecuteStage::execute(InstRef &IR) { // be released after MCIS is issued, and all the ResourceCycles for those // units have been consumed. bool IsReadyInstruction = HWS.dispatch(IR); + NumDispatchedOpcodes += IR.getInstruction()->getDesc().NumMicroOps; notifyReservedOrReleasedBuffers(IR, /* Reserved */ true); if (!IsReadyInstruction) return ErrorSuccess(); |

