Index: llvm/trunk/tools/llvm-mca/DispatchStage.h =================================================================== --- llvm/trunk/tools/llvm-mca/DispatchStage.h +++ llvm/trunk/tools/llvm-mca/DispatchStage.h @@ -19,6 +19,7 @@ #ifndef LLVM_TOOLS_LLVM_MCA_DISPATCH_STAGE_H #define LLVM_TOOLS_LLVM_MCA_DISPATCH_STAGE_H +#include "HWEventListener.h" #include "Instruction.h" #include "RegisterFile.h" #include "RetireControlUnit.h" @@ -30,7 +31,6 @@ class WriteState; class Scheduler; -class Pipeline; // Implements the hardware dispatch logic. // @@ -54,7 +54,6 @@ unsigned DispatchWidth; unsigned AvailableEntries; unsigned CarryOver; - Pipeline *Owner; const llvm::MCSubtargetInfo &STI; RetireControlUnit &RCU; RegisterFile &PRF; @@ -66,6 +65,7 @@ void dispatch(InstRef IR); void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI); + void notifyStallEvent(const HWStallEvent &Event); void notifyInstructionDispatched(const InstRef &IR, llvm::ArrayRef UsedPhysRegs); @@ -84,12 +84,12 @@ } public: - DispatchStage(Pipeline *P, const llvm::MCSubtargetInfo &Subtarget, + DispatchStage(const llvm::MCSubtargetInfo &Subtarget, const llvm::MCRegisterInfo &MRI, unsigned RegisterFileSize, unsigned MaxDispatchWidth, RetireControlUnit &R, RegisterFile &F, Scheduler &Sched) : DispatchWidth(MaxDispatchWidth), AvailableEntries(MaxDispatchWidth), - CarryOver(0U), Owner(P), STI(Subtarget), RCU(R), PRF(F), SC(Sched) {} + CarryOver(0U), STI(Subtarget), RCU(R), PRF(F), SC(Sched) {} // We can always try to dispatch, so returning false is okay in this case. // The retire stage, which controls the RCU, might have items to complete but Index: llvm/trunk/tools/llvm-mca/DispatchStage.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/DispatchStage.cpp +++ llvm/trunk/tools/llvm-mca/DispatchStage.cpp @@ -18,7 +18,6 @@ #include "DispatchStage.h" #include "HWEventListener.h" -#include "Pipeline.h" #include "Scheduler.h" #include "llvm/Support/Debug.h" @@ -31,7 +30,12 @@ void DispatchStage::notifyInstructionDispatched(const InstRef &IR, ArrayRef UsedRegs) { LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: " << IR << '\n'); - Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(IR, UsedRegs)); + notifyInstructionEvent(HWInstructionDispatchedEvent(IR, UsedRegs)); +} + +void DispatchStage::notifyStallEvent(const HWStallEvent &Event) { + for (HWEventListener *Listener : getListeners()) + Listener->onStallEvent(Event); } bool DispatchStage::checkPRF(const InstRef &IR) { @@ -43,7 +47,7 @@ const unsigned RegisterMask = PRF.isAvailable(RegDefs); // A mask with all zeroes means: register files are available. if (RegisterMask) { - Owner->notifyStallEvent(HWStallEvent(HWStallEvent::RegisterFileStall, IR)); + notifyStallEvent(HWStallEvent(HWStallEvent::RegisterFileStall, IR)); return false; } @@ -54,8 +58,7 @@ const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps; if (RCU.isAvailable(NumMicroOps)) return true; - Owner->notifyStallEvent( - HWStallEvent(HWStallEvent::RetireControlUnitStall, IR)); + notifyStallEvent(HWStallEvent(HWStallEvent::RetireControlUnitStall, IR)); return false; } @@ -63,7 +66,7 @@ HWStallEvent::GenericEventType Event; const bool Ready = SC.canBeDispatched(IR, Event); if (!Ready) - Owner->notifyStallEvent(HWStallEvent(Event, IR)); + notifyStallEvent(HWStallEvent(Event, IR)); return Ready; } Index: llvm/trunk/tools/llvm-mca/ExecuteStage.h =================================================================== --- llvm/trunk/tools/llvm-mca/ExecuteStage.h +++ llvm/trunk/tools/llvm-mca/ExecuteStage.h @@ -26,11 +26,8 @@ namespace mca { -class Pipeline; - class ExecuteStage : public Stage { // Owner will go away when we move listeners/eventing to the stages. - Pipeline *Owner; RetireControlUnit &RCU; Scheduler &HWS; @@ -40,8 +37,7 @@ void issueReadyInstructions(); public: - ExecuteStage(Pipeline *P, RetireControlUnit &R, Scheduler &S) - : Stage(), Owner(P), RCU(R), HWS(S) {} + ExecuteStage(RetireControlUnit &R, Scheduler &S) : Stage(), RCU(R), HWS(S) {} ExecuteStage(const ExecuteStage &Other) = delete; ExecuteStage &operator=(const ExecuteStage &Other) = delete; Index: llvm/trunk/tools/llvm-mca/ExecuteStage.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/ExecuteStage.cpp +++ llvm/trunk/tools/llvm-mca/ExecuteStage.cpp @@ -16,7 +16,6 @@ //===----------------------------------------------------------------------===// #include "ExecuteStage.h" -#include "Pipeline.h" #include "Scheduler.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" @@ -155,19 +154,20 @@ void ExecuteStage::notifyInstructionExecuted(const InstRef &IR) { HWS.onInstructionExecuted(IR); LLVM_DEBUG(dbgs() << "[E] Instruction Executed: " << IR << '\n'); - Owner->notifyInstructionEvent( - HWInstructionEvent(HWInstructionEvent::Executed, IR)); + notifyInstructionEvent(HWInstructionEvent(HWInstructionEvent::Executed, IR)); RCU.onInstructionExecuted(IR.getInstruction()->getRCUTokenID()); } void ExecuteStage::notifyInstructionReady(const InstRef &IR) { LLVM_DEBUG(dbgs() << "[E] Instruction Ready: " << IR << '\n'); - Owner->notifyInstructionEvent( - HWInstructionEvent(HWInstructionEvent::Ready, IR)); + notifyInstructionEvent(HWInstructionEvent(HWInstructionEvent::Ready, IR)); } void ExecuteStage::notifyResourceAvailable(const ResourceRef &RR) { - Owner->notifyResourceAvailable(RR); + LLVM_DEBUG(dbgs() << "[E] Resource Available: [" << RR.first << '.' + << RR.second << "]\n"); + for (HWEventListener *Listener : getListeners()) + Listener->onResourceAvailable(RR); } void ExecuteStage::notifyInstructionIssued( @@ -180,7 +180,7 @@ dbgs() << " cycles: " << Resource.second << '\n'; } }); - Owner->notifyInstructionEvent(HWInstructionIssuedEvent(IR, Used)); + notifyInstructionEvent(HWInstructionIssuedEvent(IR, Used)); } void ExecuteStage::notifyReservedBuffers(ArrayRef Buffers) { @@ -190,7 +190,8 @@ SmallVector BufferIDs(Buffers.begin(), Buffers.end()); std::transform(Buffers.begin(), Buffers.end(), BufferIDs.begin(), [&](uint64_t Op) { return HWS.getResourceID(Op); }); - Owner->notifyReservedBuffers(BufferIDs); + for (HWEventListener *Listener : getListeners()) + Listener->onReservedBuffers(BufferIDs); } void ExecuteStage::notifyReleasedBuffers(ArrayRef Buffers) { @@ -200,7 +201,8 @@ SmallVector BufferIDs(Buffers.begin(), Buffers.end()); std::transform(Buffers.begin(), Buffers.end(), BufferIDs.begin(), [&](uint64_t Op) { return HWS.getResourceID(Op); }); - Owner->notifyReleasedBuffers(BufferIDs); + for (HWEventListener *Listener : getListeners()) + Listener->onReleasedBuffers(BufferIDs); } } // namespace mca Index: llvm/trunk/tools/llvm-mca/Pipeline.h =================================================================== --- llvm/trunk/tools/llvm-mca/Pipeline.h +++ llvm/trunk/tools/llvm-mca/Pipeline.h @@ -70,11 +70,6 @@ void run(); void addEventListener(HWEventListener *Listener); void notifyCycleBegin(unsigned Cycle); - void notifyInstructionEvent(const HWInstructionEvent &Event); - void notifyStallEvent(const HWStallEvent &Event); - void notifyResourceAvailable(const ResourceRef &RR); - void notifyReservedBuffers(llvm::ArrayRef Buffers); - void notifyReleasedBuffers(llvm::ArrayRef Buffers); void notifyCycleEnd(unsigned Cycle); }; } // namespace mca Index: llvm/trunk/tools/llvm-mca/Pipeline.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/Pipeline.cpp +++ llvm/trunk/tools/llvm-mca/Pipeline.cpp @@ -27,6 +27,8 @@ void Pipeline::addEventListener(HWEventListener *Listener) { if (Listener) Listeners.insert(Listener); + for (auto &S : Stages) + S->addListener(Listener); } bool Pipeline::hasWorkToProcess() { @@ -77,33 +79,6 @@ Listener->onCycleBegin(); } -void Pipeline::notifyInstructionEvent(const HWInstructionEvent &Event) { - for (HWEventListener *Listener : Listeners) - Listener->onInstructionEvent(Event); -} - -void Pipeline::notifyStallEvent(const HWStallEvent &Event) { - for (HWEventListener *Listener : Listeners) - Listener->onStallEvent(Event); -} - -void Pipeline::notifyResourceAvailable(const ResourceRef &RR) { - LLVM_DEBUG(dbgs() << "[E] Resource Available: [" << RR.first << '.' - << RR.second << "]\n"); - for (HWEventListener *Listener : Listeners) - Listener->onResourceAvailable(RR); -} - -void Pipeline::notifyReservedBuffers(ArrayRef Buffers) { - for (HWEventListener *Listener : Listeners) - Listener->onReservedBuffers(Buffers); -} - -void Pipeline::notifyReleasedBuffers(ArrayRef Buffers) { - for (HWEventListener *Listener : Listeners) - Listener->onReleasedBuffers(Buffers); -} - void Pipeline::notifyCycleEnd(unsigned Cycle) { LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycle << "\n\n"); for (HWEventListener *Listener : Listeners) Index: llvm/trunk/tools/llvm-mca/RetireStage.h =================================================================== --- llvm/trunk/tools/llvm-mca/RetireStage.h +++ llvm/trunk/tools/llvm-mca/RetireStage.h @@ -23,21 +23,20 @@ namespace mca { -class Pipeline; - class RetireStage : public Stage { // Owner will go away when we move listeners/eventing to the stages. - Pipeline *Owner; RetireControlUnit &RCU; RegisterFile &PRF; public: - RetireStage(Pipeline *P, RetireControlUnit &R, RegisterFile &F) - : Stage(), Owner(P), RCU(R), PRF(F) {} + RetireStage(RetireControlUnit &R, RegisterFile &F) + : Stage(), RCU(R), PRF(F) {} RetireStage(const RetireStage &Other) = delete; RetireStage &operator=(const RetireStage &Other) = delete; - virtual bool hasWorkToComplete() const override final { return !RCU.isEmpty(); } + virtual bool hasWorkToComplete() const override final { + return !RCU.isEmpty(); + } virtual void preExecute(const InstRef &IR) override final; virtual bool execute(InstRef &IR) override final { return true; } void notifyInstructionRetired(const InstRef &IR); Index: llvm/trunk/tools/llvm-mca/RetireStage.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/RetireStage.cpp +++ llvm/trunk/tools/llvm-mca/RetireStage.cpp @@ -16,7 +16,6 @@ #include "RetireStage.h" #include "HWEventListener.h" -#include "Pipeline.h" #include "llvm/Support/Debug.h" using namespace llvm; @@ -50,7 +49,7 @@ for (const std::unique_ptr &WS : IR.getInstruction()->getDefs()) PRF.removeRegisterWrite(*WS.get(), FreedRegs, !Desc.isZeroLatency()); - Owner->notifyInstructionEvent(HWInstructionRetiredEvent(IR, FreedRegs)); + notifyInstructionEvent(HWInstructionRetiredEvent(IR, FreedRegs)); } } // namespace mca Index: llvm/trunk/tools/llvm-mca/Stage.h =================================================================== --- llvm/trunk/tools/llvm-mca/Stage.h +++ llvm/trunk/tools/llvm-mca/Stage.h @@ -16,17 +16,20 @@ #ifndef LLVM_TOOLS_LLVM_MCA_STAGE_H #define LLVM_TOOLS_LLVM_MCA_STAGE_H +#include "HWEventListener.h" #include namespace mca { -class HWEventListener; class InstRef; class Stage { - std::set Listeners; Stage(const Stage &Other) = delete; Stage &operator=(const Stage &Other) = delete; + std::set Listeners; + +protected: + const std::set &getListeners() const { return Listeners; } public: Stage(); @@ -51,6 +54,8 @@ /// Add a listener to receive callbacks during the execution of this stage. void addListener(HWEventListener *Listener); + + virtual void notifyInstructionEvent(const HWInstructionEvent &Event); }; } // namespace mca Index: llvm/trunk/tools/llvm-mca/Stage.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/Stage.cpp +++ llvm/trunk/tools/llvm-mca/Stage.cpp @@ -14,7 +14,6 @@ //===----------------------------------------------------------------------===// #include "Stage.h" -#include "llvm/Support/ErrorHandling.h" namespace mca { @@ -22,7 +21,12 @@ Stage::Stage() {} void Stage::addListener(HWEventListener *Listener) { - llvm_unreachable("Stage-based eventing is not implemented."); + Listeners.insert(Listener); +} + +void Stage::notifyInstructionEvent(const HWInstructionEvent &Event) { + for (HWEventListener *Listener : Listeners) + Listener->onInstructionEvent(Event); } } // namespace mca Index: llvm/trunk/tools/llvm-mca/llvm-mca.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/llvm-mca.cpp +++ llvm/trunk/tools/llvm-mca/llvm-mca.cpp @@ -511,9 +511,9 @@ Width, RegisterFileSize, LoadQueueSize, StoreQueueSize, AssumeNoAlias); P->appendStage(llvm::make_unique(IB, S)); P->appendStage(llvm::make_unique( - P.get(), *STI, *MRI, RegisterFileSize, Width, RCU, PRF, HWS)); - P->appendStage(llvm::make_unique(P.get(), RCU, PRF)); - P->appendStage(llvm::make_unique(P.get(), RCU, HWS)); + *STI, *MRI, RegisterFileSize, Width, RCU, PRF, HWS)); + P->appendStage(llvm::make_unique(RCU, PRF)); + P->appendStage(llvm::make_unique(RCU, HWS)); mca::PipelinePrinter Printer(*P); if (PrintSummaryView)