Index: tools/llvm-mca/Backend.h =================================================================== --- tools/llvm-mca/Backend.h +++ tools/llvm-mca/Backend.h @@ -19,6 +19,7 @@ #include "FetchStage.h" #include "InstrBuilder.h" #include "Scheduler.h" +#include "llvm/ADT/SmallVector.h" namespace mca { @@ -58,6 +59,7 @@ std::unique_ptr HWS; std::unique_ptr Dispatch; std::set Listeners; + llvm::SmallVector Stages; unsigned Cycles; void runCycle(unsigned Cycle); @@ -73,9 +75,13 @@ LoadQueueSize, StoreQueueSize, AssumeNoAlias)), Dispatch(llvm::make_unique( - this, Subtarget, MRI, RegisterFileSize, DispatchWidth, HWS.get())), + Subtarget, MRI, RegisterFileSize, DispatchWidth, HWS.get())), Cycles(0) { HWS->setDispatchStage(Dispatch.get()); + + // Build a list of all stages that this backend recognizes. + Stages.push_back(Fetch.get()); + Stages.push_back(Dispatch.get()); } void run(); Index: tools/llvm-mca/Backend.cpp =================================================================== --- tools/llvm-mca/Backend.cpp +++ tools/llvm-mca/Backend.cpp @@ -25,8 +25,11 @@ using namespace llvm; void Backend::addEventListener(HWEventListener *Listener) { - if (Listener) + if (Listener) { Listeners.insert(Listener); + for (Stage *S : Stages) + S->addListener(Listener); + } } void Backend::run() { @@ -61,11 +64,6 @@ Listener->onInstructionEvent(Event); } -void Backend::notifyStallEvent(const HWStallEvent &Event) { - for (HWEventListener *Listener : Listeners) - Listener->onStallEvent(Event); -} - void Backend::notifyResourceAvailable(const ResourceRef &RR) { LLVM_DEBUG(dbgs() << "[E] Resource Available: [" << RR.first << '.' << RR.second << "]\n"); Index: tools/llvm-mca/DispatchStage.h =================================================================== --- tools/llvm-mca/DispatchStage.h +++ tools/llvm-mca/DispatchStage.h @@ -59,7 +59,6 @@ Scheduler *SC; std::unique_ptr RAT; std::unique_ptr RCU; - Backend *Owner; const llvm::MCSubtargetInfo &STI; bool checkRAT(const InstRef &IR); @@ -87,7 +86,7 @@ } public: - DispatchStage(Backend *B, const llvm::MCSubtargetInfo &Subtarget, + DispatchStage(const llvm::MCSubtargetInfo &Subtarget, const llvm::MCRegisterInfo &MRI, unsigned RegisterFileSize, unsigned MaxDispatchWidth, Scheduler *Sched) : DispatchWidth(MaxDispatchWidth), AvailableEntries(MaxDispatchWidth), @@ -96,7 +95,7 @@ RegisterFileSize)), RCU(llvm::make_unique(Subtarget.getSchedModel(), this)), - Owner(B), STI(Subtarget) {} + STI(Subtarget) {} virtual bool isReady() const override final { return isRCUEmpty(); } virtual void preExecute(const InstRef &IR) override final; Index: tools/llvm-mca/DispatchStage.cpp =================================================================== --- tools/llvm-mca/DispatchStage.cpp +++ tools/llvm-mca/DispatchStage.cpp @@ -27,7 +27,7 @@ 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::notifyInstructionRetired(const InstRef &IR) { @@ -37,7 +37,7 @@ for (const std::unique_ptr &WS : IR.getInstruction()->getDefs()) RAT->removeRegisterWrite(*WS.get(), FreedRegs, !Desc.isZeroLatency()); - Owner->notifyInstructionEvent(HWInstructionRetiredEvent(IR, FreedRegs)); + notifyInstructionEvent(HWInstructionRetiredEvent(IR, FreedRegs)); } bool DispatchStage::checkRAT(const InstRef &IR) { @@ -49,7 +49,7 @@ unsigned RegisterMask = RAT->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; } @@ -60,8 +60,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; } Index: tools/llvm-mca/Scheduler.cpp =================================================================== --- tools/llvm-mca/Scheduler.cpp +++ tools/llvm-mca/Scheduler.cpp @@ -344,7 +344,7 @@ } } - Owner->notifyStallEvent(HWStallEvent(Type, IR)); + DS->notifyStallEvent(HWStallEvent(Type, IR)); return false; } Index: tools/llvm-mca/Stage.h =================================================================== --- tools/llvm-mca/Stage.h +++ tools/llvm-mca/Stage.h @@ -16,11 +16,11 @@ #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 { @@ -46,8 +46,14 @@ /// The primary action that this stage performs. virtual bool execute(InstRef &IR) = 0; - /// Add a listener to receive callbaks during the execution of this stage. + /// Add a listener to receive callbacks during the execution of this stage. void addListener(HWEventListener *Listener); + + /// Notify listeners that an instruction event has occurred. + void notifyInstructionEvent(const HWInstructionEvent &Event); + + /// Notify listeners that a hardware stall event has occurred. + void notifyStallEvent(const HWStallEvent &Event); }; } // namespace mca Index: tools/llvm-mca/Stage.cpp =================================================================== --- tools/llvm-mca/Stage.cpp +++ tools/llvm-mca/Stage.cpp @@ -22,7 +22,17 @@ 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); +} + +void Stage::notifyStallEvent(const HWStallEvent &Event) { + for (HWEventListener *Listener : Listeners) + Listener->onStallEvent(Event); } } // namespace mca