Index: tools/llvm-mca/Backend.cpp =================================================================== --- tools/llvm-mca/Backend.cpp +++ tools/llvm-mca/Backend.cpp @@ -38,6 +38,7 @@ notifyCycleBegin(Cycle); InstRef IR; + Dispatch->preExecute(IR); HWS->cycleEvent(); // TODO: This will eventually be stage-ified. Index: tools/llvm-mca/CMakeLists.txt =================================================================== --- tools/llvm-mca/CMakeLists.txt +++ tools/llvm-mca/CMakeLists.txt @@ -26,7 +26,7 @@ RegisterFile.cpp RegisterFileStatistics.cpp ResourcePressureView.cpp - RetireControlUnit.cpp + RetireStage.cpp RetireControlUnitStatistics.cpp Scheduler.cpp SchedulerStatistics.cpp Index: tools/llvm-mca/DispatchStage.h =================================================================== --- tools/llvm-mca/DispatchStage.h +++ tools/llvm-mca/DispatchStage.h @@ -1,4 +1,4 @@ -//===----------------------- Dispatch.h -------------------------*- C++ -*-===// +//===----------------------- DispatchStage.h --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,7 +18,7 @@ #include "Instruction.h" #include "RegisterFile.h" -#include "RetireControlUnit.h" +#include "RetireStage.h" #include "Stage.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -36,7 +36,7 @@ // functional units are available. // To be more specific, an instruction can be dispatched to the Scheduler if: // 1) There are enough entries in the reorder buffer (implemented by class -// RetireControlUnit) to accommodate all opcodes. +// RetireStage) to accommodate all opcodes. // 2) There are enough temporaries to rename output register operands. // 3) There are enough entries available in the used buffered resource(s). // @@ -58,7 +58,7 @@ unsigned CarryOver; Scheduler *SC; std::unique_ptr RAT; - std::unique_ptr RCU; + std::unique_ptr RS; Backend *Owner; const llvm::MCSubtargetInfo &STI; @@ -66,7 +66,7 @@ bool checkRCU(const InstRef &IR); bool checkScheduler(const InstRef &IR); void dispatch(InstRef IR); - bool isRCUEmpty() const { return RCU->isEmpty(); } + bool isRCUEmpty() const { return RS->isEmpty(); } void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI); void notifyInstructionDispatched(const InstRef &IR, @@ -94,8 +94,7 @@ CarryOver(0U), SC(Sched), RAT(llvm::make_unique(Subtarget.getSchedModel(), MRI, RegisterFileSize)), - RCU(llvm::make_unique(Subtarget.getSchedModel(), - this)), + RS(llvm::make_unique(Subtarget.getSchedModel(), this)), Owner(B), STI(Subtarget) {} virtual bool isReady() const override final { return isRCUEmpty(); } @@ -105,7 +104,7 @@ void notifyDispatchStall(const InstRef &IR, unsigned EventType); void onInstructionExecuted(unsigned TokenID) { - RCU->onInstructionExecuted(TokenID); + RS->onInstructionExecuted(TokenID); } #ifndef NDEBUG Index: tools/llvm-mca/DispatchStage.cpp =================================================================== --- tools/llvm-mca/DispatchStage.cpp +++ tools/llvm-mca/DispatchStage.cpp @@ -1,4 +1,4 @@ -//===--------------------- Dispatch.cpp -------------------------*- C++ -*-===// +//===--------------------- DispatchStage.cpp --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -58,7 +58,7 @@ bool DispatchStage::checkRCU(const InstRef &IR) { const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps; - if (RCU->isAvailable(NumMicroOps)) + if (RS->isAvailable(NumMicroOps)) return true; Owner->notifyStallEvent( HWStallEvent(HWStallEvent::RetireControlUnitStall, IR)); @@ -131,7 +131,7 @@ // Reserve slots in the RCU, and notify the instruction that it has been // dispatched to the schedulers for execution. - IS.dispatch(RCU->reserveSlot(IR, NumMicroOps)); + IS.dispatch(RS->reserveSlot(IR, NumMicroOps)); // Notify listeners of the "instruction dispatched" event. notifyInstructionDispatched(IR, RegisterFiles); @@ -143,7 +143,7 @@ } void DispatchStage::preExecute(const InstRef &IR) { - RCU->cycleEvent(); + RS->cycleEvent(); AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver; CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U; } @@ -159,7 +159,7 @@ #ifndef NDEBUG void DispatchStage::dump() const { RAT->dump(); - RCU->dump(); + RS->dump(); } #endif } // namespace mca Index: tools/llvm-mca/README.txt =================================================================== --- tools/llvm-mca/README.txt +++ tools/llvm-mca/README.txt @@ -256,7 +256,7 @@ -------------------------------------------------------- Flag '-verbose' enables extra statistics and performance counters for the -dispatch logic, the reorder buffer, the retire control unit and the register +dispatch logic, the reorder buffer, the retire stage, and the register file. Below is an example of verbose output generated by the tool for the dot-product @@ -402,8 +402,8 @@ 'NumMicroOpcodes' of TableGen class ProcWriteResources and its derived classes; TargetSchedule.td). -The reorder buffer is implemented by class RetireControlUnit (see -DispatchStage.h). Its goal is to track the progress of instructions that are +The reorder buffer is implemented by class RetireStage (see +RetireStage.h). Its goal is to track the progress of instructions that are "in-flight", and retire instructions in program order. The number of entries in the reorder buffer defaults to the value of field 'MicroOpBufferSize' from the target scheduling model. Index: tools/llvm-mca/RetireStage.h =================================================================== --- tools/llvm-mca/RetireStage.h +++ tools/llvm-mca/RetireStage.h @@ -1,4 +1,4 @@ -//===---------------------- RetireControlUnit.h -----------------*- C++ -*-===// +//===-------------------------- RetireStage.h -------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -8,14 +8,16 @@ //===----------------------------------------------------------------------===// /// \file /// -/// This file implements the logic for retiring instructions. +/// This file implements the pipeline stage responsible for retiring +/// instructions. /// //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H -#define LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H +#ifndef LLVM_TOOLS_LLVM_MCA_RETIRE_STAGE_H +#define LLVM_TOOLS_LLVM_MCA_RETIRE_STAGE_H #include "Instruction.h" +#include "Stage.h" #include "llvm/MC/MCSchedule.h" #include @@ -31,18 +33,18 @@ /// This class checks on every cycle if/which instructions can be retired. /// Instructions are retired in program order. /// In the event of instruction retired, the DispatchStage object that owns -/// this RetireControlUnit (RCU) gets notified. +/// this RetireStage (RS) gets notified. /// On instruction retired, register updates are all architecturally /// committed, and any temporary registers originally allocated for the /// retired instruction are freed. -struct RetireControlUnit { - // A RUToken is created by the RCU for every instruction dispatched to the - // schedulers. These "tokens" are managed by the RCU in its token Queue. +struct RetireStage : public Stage { + // A RUToken is created by the RS for every instruction dispatched to the + // schedulers. These "tokens" are managed by the RS in its token Queue. // - // On evey cycle ('cycleEvent'), the RCU iterates through the token queue + // On evey cycle ('cycleEvent'), the RS iterates through the token queue // looking for any token with its 'Executed' flag set. If a token has that // flag set, then the instruction has reached the write-back stage and will - // be retired by the RCU. + // be retired by the RS. // // 'NumSlots' represents the number of entries consumed by the instruction in // the reorder buffer. Those entries will become available again once the @@ -65,7 +67,7 @@ DispatchStage *Owner; public: - RetireControlUnit(const llvm::MCSchedModel &SM, DispatchStage *DU); + RetireStage(const llvm::MCSchedModel &SM, DispatchStage *DU); bool isFull() const { return !AvailableSlots; } bool isEmpty() const { return AvailableSlots == Queue.size(); } @@ -83,6 +85,9 @@ /// Retires instructions in program order. void cycleEvent(); + // This is a no-op for now. + virtual bool execute(InstRef &IR) override final { return true; } + void onInstructionExecuted(unsigned TokenID); #ifndef NDEBUG @@ -92,4 +97,4 @@ } // namespace mca -#endif // LLVM_TOOLS_LLVM_MCA_RETIRE_CONTROL_UNIT_H +#endif // LLVM_TOOLS_LLVM_MCA_RETIRE_STAGE_H Index: tools/llvm-mca/RetireStage.cpp =================================================================== --- tools/llvm-mca/RetireStage.cpp +++ tools/llvm-mca/RetireStage.cpp @@ -1,4 +1,4 @@ -//===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===// +//===---------------------- RetireStage.cpp ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -8,11 +8,11 @@ //===----------------------------------------------------------------------===// /// \file /// -/// This file implements methods declared by the RetireControlUnit interface. +/// This file implements methods declared by the RetireStage interface. /// //===----------------------------------------------------------------------===// -#include "RetireControlUnit.h" +#include "RetireStage.h" #include "DispatchStage.h" #include "llvm/Support/Debug.h" @@ -22,9 +22,8 @@ namespace mca { -RetireControlUnit::RetireControlUnit(const llvm::MCSchedModel &SM, - DispatchStage *DS) - : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0), +RetireStage::RetireStage(const llvm::MCSchedModel &SM, DispatchStage *DS) + : Stage(), NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0), AvailableSlots(SM.MicroOpBufferSize), MaxRetirePerCycle(0), Owner(DS) { // Check if the scheduling model provides extra information about the machine // processor. If so, then use that information to set the reorder buffer size @@ -41,8 +40,7 @@ } // Reserves a number of slots, and returns a new token. -unsigned RetireControlUnit::reserveSlot(const InstRef &IR, - unsigned NumMicroOps) { +unsigned RetireStage::reserveSlot(const InstRef &IR, unsigned NumMicroOps) { assert(isAvailable(NumMicroOps)); unsigned NormalizedQuantity = std::min(NumMicroOps, static_cast(Queue.size())); @@ -58,7 +56,7 @@ return TokenID; } -void RetireControlUnit::cycleEvent() { +void RetireStage::cycleEvent() { if (isEmpty()) return; @@ -68,7 +66,7 @@ break; RUToken &Current = Queue[CurrentInstructionSlotIdx]; assert(Current.NumSlots && "Reserved zero slots?"); - assert(Current.IR.isValid() && "Invalid RUToken in the RCU queue."); + assert(Current.IR.isValid() && "Invalid RUToken in the RetireStage queue."); if (!Current.Executed) break; Owner->notifyInstructionRetired(Current.IR); @@ -79,14 +77,14 @@ } } -void RetireControlUnit::onInstructionExecuted(unsigned TokenID) { +void RetireStage::onInstructionExecuted(unsigned TokenID) { assert(Queue.size() > TokenID); assert(Queue[TokenID].Executed == false && Queue[TokenID].IR.isValid()); Queue[TokenID].Executed = true; } #ifndef NDEBUG -void RetireControlUnit::dump() const { +void RetireStage::dump() const { dbgs() << "Retire Unit: { Total Slots=" << Queue.size() << ", Available Slots=" << AvailableSlots << " }\n"; }