Index: llvm/trunk/tools/llvm-mca/Backend.h =================================================================== --- llvm/trunk/tools/llvm-mca/Backend.h +++ llvm/trunk/tools/llvm-mca/Backend.h @@ -1,81 +0,0 @@ -//===--------------------- Backend.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file implements an OoO backend for the llvm-mca tool. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVM_MCA_BACKEND_H -#define LLVM_TOOLS_LLVM_MCA_BACKEND_H - -#include "Scheduler.h" -#include "Stage.h" -#include "llvm/ADT/SmallVector.h" - -namespace mca { - -class HWEventListener; -class HWInstructionEvent; -class HWStallEvent; - -/// An out of order backend for a specific subtarget. -/// -/// It emulates an out-of-order execution of instructions. Instructions are -/// fetched from a MCInst sequence managed by an initial 'Fetch' stage. -/// Instructions are firstly fetched, then dispatched to the schedulers, and -/// then executed. -/// -/// This class tracks the lifetime of an instruction from the moment where -/// it gets dispatched to the schedulers, to the moment where it finishes -/// executing and register writes are architecturally committed. -/// In particular, it monitors changes in the state of every instruction -/// in flight. -/// -/// Instructions are executed in a loop of iterations. The number of iterations -/// is defined by the SourceMgr object, which is managed by the initial stage -/// of the instruction pipeline. -/// -/// The Backend entry point is method 'run()' which executes cycles in a loop -/// until there are new instructions to dispatch, and not every instruction -/// has been retired. -/// -/// Internally, the Backend collects statistical information in the form of -/// histograms. For example, it tracks how the dispatch group size changes -/// over time. -class Backend { - /// An ordered list of stages that define this backend's instruction pipeline. - llvm::SmallVector, 8> Stages; - std::set Listeners; - unsigned Cycles; - - bool executeStages(InstRef &IR); - void postExecuteStages(const InstRef &IR); - bool hasWorkToProcess(); - void runCycle(unsigned Cycle); - -public: - Backend(unsigned DispatchWidth = 0, unsigned RegisterFileSize = 0, - unsigned LoadQueueSize = 0, unsigned StoreQueueSize = 0, - bool AssumeNoAlias = false) - : Cycles(0) {} - void appendStage(std::unique_ptr S) { Stages.push_back(std::move(S)); } - 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 - -#endif Index: llvm/trunk/tools/llvm-mca/Backend.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/Backend.cpp +++ llvm/trunk/tools/llvm-mca/Backend.cpp @@ -1,111 +0,0 @@ -//===--------------------- Backend.cpp --------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// Implementation of class Backend which emulates an hardware OoO backend. -/// -//===----------------------------------------------------------------------===// - -#include "Backend.h" -#include "HWEventListener.h" -#include "llvm/CodeGen/TargetSchedule.h" -#include "llvm/Support/Debug.h" - -namespace mca { - -#define DEBUG_TYPE "llvm-mca" - -using namespace llvm; - -void Backend::addEventListener(HWEventListener *Listener) { - if (Listener) - Listeners.insert(Listener); -} - -bool Backend::hasWorkToProcess() { - const auto It = llvm::find_if(Stages, [](const std::unique_ptr &S) { - return S->hasWorkToComplete(); - }); - return It != Stages.end(); -} - -// This routine returns early if any stage returns 'false' after execute() is -// called on it. -bool Backend::executeStages(InstRef &IR) { - for (const std::unique_ptr &S : Stages) - if (!S->execute(IR)) - return false; - return true; -} - -void Backend::postExecuteStages(const InstRef &IR) { - for (const std::unique_ptr &S : Stages) - S->postExecute(IR); -} - -void Backend::run() { - while (hasWorkToProcess()) - runCycle(Cycles++); -} - -void Backend::runCycle(unsigned Cycle) { - notifyCycleBegin(Cycle); - - // Update the stages before we do any processing for this cycle. - InstRef IR; - for (auto &S : Stages) - S->preExecute(IR); - - // Continue executing this cycle until any stage claims it cannot make - // progress. - while (executeStages(IR)) - postExecuteStages(IR); - - notifyCycleEnd(Cycle); -} - -void Backend::notifyCycleBegin(unsigned Cycle) { - LLVM_DEBUG(dbgs() << "[E] Cycle begin: " << Cycle << '\n'); - for (HWEventListener *Listener : Listeners) - Listener->onCycleBegin(); -} - -void Backend::notifyInstructionEvent(const HWInstructionEvent &Event) { - for (HWEventListener *Listener : Listeners) - 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"); - for (HWEventListener *Listener : Listeners) - Listener->onResourceAvailable(RR); -} - -void Backend::notifyReservedBuffers(ArrayRef Buffers) { - for (HWEventListener *Listener : Listeners) - Listener->onReservedBuffers(Buffers); -} - -void Backend::notifyReleasedBuffers(ArrayRef Buffers) { - for (HWEventListener *Listener : Listeners) - Listener->onReleasedBuffers(Buffers); -} - -void Backend::notifyCycleEnd(unsigned Cycle) { - LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycle << "\n\n"); - for (HWEventListener *Listener : Listeners) - Listener->onCycleEnd(); -} -} // namespace mca. Index: llvm/trunk/tools/llvm-mca/BackendPrinter.h =================================================================== --- llvm/trunk/tools/llvm-mca/BackendPrinter.h +++ llvm/trunk/tools/llvm-mca/BackendPrinter.h @@ -1,52 +0,0 @@ -//===--------------------- BackendPrinter.h ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file implements class BackendPrinter. -/// -/// BackendPrinter allows the customization of the performance report. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVM_MCA_BACKENDPRINTER_H -#define LLVM_TOOLS_LLVM_MCA_BACKENDPRINTER_H - -#include "Backend.h" -#include "View.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/raw_ostream.h" - -#define DEBUG_TYPE "llvm-mca" - -namespace mca { - -/// A printer class that knows how to collects statistics on the -/// code analyzed by the llvm-mca tool. -/// -/// This class knows how to print out the analysis information collected -/// during the execution of the code. Internally, it delegates to other -/// classes the task of printing out timeline information as well as -/// resource pressure. -class BackendPrinter { - Backend &B; - llvm::SmallVector, 8> Views; - -public: - BackendPrinter(Backend &backend) : B(backend) {} - - void addView(std::unique_ptr V) { - B.addEventListener(V.get()); - Views.emplace_back(std::move(V)); - } - - void printReport(llvm::raw_ostream &OS) const; -}; -} // namespace mca - -#endif Index: llvm/trunk/tools/llvm-mca/BackendPrinter.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/BackendPrinter.cpp +++ llvm/trunk/tools/llvm-mca/BackendPrinter.cpp @@ -1,27 +0,0 @@ -//===--------------------- BackendPrinter.cpp -------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file implements the BackendPrinter interface. -/// -//===----------------------------------------------------------------------===// - -#include "BackendPrinter.h" -#include "View.h" -#include "llvm/CodeGen/TargetSchedule.h" - -namespace mca { - -using namespace llvm; - -void BackendPrinter::printReport(llvm::raw_ostream &OS) const { - for (const auto &V : Views) - V->printView(OS); -} -} // namespace mca. Index: llvm/trunk/tools/llvm-mca/CMakeLists.txt =================================================================== --- llvm/trunk/tools/llvm-mca/CMakeLists.txt +++ llvm/trunk/tools/llvm-mca/CMakeLists.txt @@ -10,8 +10,6 @@ ) add_llvm_tool(llvm-mca - Backend.cpp - BackendPrinter.cpp CodeRegion.cpp DispatchStage.cpp DispatchStatistics.cpp @@ -24,6 +22,8 @@ InstructionTables.cpp LSUnit.cpp llvm-mca.cpp + Pipeline.cpp + PipelinePrinter.cpp RegisterFile.cpp RegisterFileStatistics.cpp ResourcePressureView.cpp Index: llvm/trunk/tools/llvm-mca/DispatchStage.h =================================================================== --- llvm/trunk/tools/llvm-mca/DispatchStage.h +++ llvm/trunk/tools/llvm-mca/DispatchStage.h @@ -30,7 +30,7 @@ class WriteState; class Scheduler; -class Backend; +class Pipeline; // Implements the hardware dispatch logic. // @@ -54,7 +54,7 @@ unsigned DispatchWidth; unsigned AvailableEntries; unsigned CarryOver; - Backend *Owner; + Pipeline *Owner; const llvm::MCSubtargetInfo &STI; RetireControlUnit &RCU; RegisterFile &PRF; @@ -84,12 +84,12 @@ } public: - DispatchStage(Backend *B, const llvm::MCSubtargetInfo &Subtarget, + DispatchStage(Pipeline *P, 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(B), STI(Subtarget), RCU(R), PRF(F), SC(Sched) {} + CarryOver(0U), Owner(P), 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 @@ -17,8 +17,8 @@ //===----------------------------------------------------------------------===// #include "DispatchStage.h" -#include "Backend.h" #include "HWEventListener.h" +#include "Pipeline.h" #include "Scheduler.h" #include "llvm/Support/Debug.h" 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,11 @@ namespace mca { -class Backend; +class Pipeline; class ExecuteStage : public Stage { // Owner will go away when we move listeners/eventing to the stages. - Backend *Owner; + Pipeline *Owner; RetireControlUnit &RCU; Scheduler &HWS; @@ -40,8 +40,8 @@ void issueReadyInstructions(); public: - ExecuteStage(Backend *B, RetireControlUnit &R, Scheduler &S) - : Stage(), Owner(B), RCU(R), HWS(S) {} + ExecuteStage(Pipeline *P, RetireControlUnit &R, Scheduler &S) + : Stage(), Owner(P), 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,7 @@ //===----------------------------------------------------------------------===// #include "ExecuteStage.h" -#include "Backend.h" +#include "Pipeline.h" #include "Scheduler.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" Index: llvm/trunk/tools/llvm-mca/HWEventListener.h =================================================================== --- llvm/trunk/tools/llvm-mca/HWEventListener.h +++ llvm/trunk/tools/llvm-mca/HWEventListener.h @@ -27,11 +27,11 @@ class HWInstructionEvent { public: // This is the list of event types that are shared by all targets, that - // generic subtarget-agnostic classes (e.g. Backend, HWInstructionEvent, ...) - // and generic Views can manipulate. + // generic subtarget-agnostic classes (e.g., Pipeline, HWInstructionEvent, + // ...) and generic Views can manipulate. // Subtargets are free to define additional event types, that are goin to be // handled by generic components as opaque values, but can still be - // emitted by subtarget-specific pipeline components (e.g. Scheduler, + // emitted by subtarget-specific pipeline stages (e.g., ExecuteStage, // DispatchStage, ...) and interpreted by subtarget-specific EventListener // implementations. enum GenericEventType { @@ -116,7 +116,7 @@ class HWEventListener { public: - // Generic events generated by the backend pipeline. + // Generic events generated by the pipeline. virtual void onCycleBegin() {} virtual void onCycleEnd() {} Index: llvm/trunk/tools/llvm-mca/Instruction.h =================================================================== --- llvm/trunk/tools/llvm-mca/Instruction.h +++ llvm/trunk/tools/llvm-mca/Instruction.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// \file /// -/// This file defines abstractions used by the Backend to model register reads, +/// This file defines abstractions used by the Pipeline to model register reads, /// register writes and instructions. /// //===----------------------------------------------------------------------===// @@ -264,10 +264,10 @@ bool isZeroLatency() const { return !MaxLatency && Resources.empty(); } }; -/// An instruction dispatched to the out-of-order backend. +/// An instruction propagated through the simulated instruction pipeline. /// -/// This class is used to monitor changes in the internal state of instructions -/// that are dispatched by the DispatchUnit to the hardware schedulers. +/// This class is used to monitor changes to the internal state of instructions +/// that are sent to the various components of the simulated hardware pipeline. class Instruction { const InstrDesc &Desc; Index: llvm/trunk/tools/llvm-mca/Instruction.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/Instruction.cpp +++ llvm/trunk/tools/llvm-mca/Instruction.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines abstractions used by the Backend to model register reads, +// This file defines abstractions used by the Pipeline to model register reads, // register writes and instructions. // //===----------------------------------------------------------------------===// Index: llvm/trunk/tools/llvm-mca/InstructionTables.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/InstructionTables.cpp +++ llvm/trunk/tools/llvm-mca/InstructionTables.cpp @@ -11,7 +11,7 @@ /// This file implements method InstructionTables::run(). /// Method run() prints a theoretical resource pressure distribution based on /// the information available in the scheduling model, and without running -/// the backend pipeline. +/// the pipeline. /// //===----------------------------------------------------------------------===// Index: llvm/trunk/tools/llvm-mca/Pipeline.h =================================================================== --- llvm/trunk/tools/llvm-mca/Pipeline.h +++ llvm/trunk/tools/llvm-mca/Pipeline.h @@ -0,0 +1,82 @@ +//===--------------------- Pipeline.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file implements an ordered container of stages that simulate the +/// pipeline of a hardware backend. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_MCA_PIPELINE_H +#define LLVM_TOOLS_LLVM_MCA_PIPELINE_H + +#include "Scheduler.h" +#include "Stage.h" +#include "llvm/ADT/SmallVector.h" + +namespace mca { + +class HWEventListener; +class HWInstructionEvent; +class HWStallEvent; + +/// A pipeline for a specific subtarget. +/// +/// It emulates an out-of-order execution of instructions. Instructions are +/// fetched from a MCInst sequence managed by an initial 'Fetch' stage. +/// Instructions are firstly fetched, then dispatched to the schedulers, and +/// then executed. +/// +/// This class tracks the lifetime of an instruction from the moment where +/// it gets dispatched to the schedulers, to the moment where it finishes +/// executing and register writes are architecturally committed. +/// In particular, it monitors changes in the state of every instruction +/// in flight. +/// +/// Instructions are executed in a loop of iterations. The number of iterations +/// is defined by the SourceMgr object, which is managed by the initial stage +/// of the instruction pipeline. +/// +/// The Pipeline entry point is method 'run()' which executes cycles in a loop +/// until there are new instructions to dispatch, and not every instruction +/// has been retired. +/// +/// Internally, the Pipeline collects statistical information in the form of +/// histograms. For example, it tracks how the dispatch group size changes +/// over time. +class Pipeline { + /// An ordered list of stages that define this instruction pipeline. + llvm::SmallVector, 8> Stages; + std::set Listeners; + unsigned Cycles; + + bool executeStages(InstRef &IR); + void postExecuteStages(const InstRef &IR); + bool hasWorkToProcess(); + void runCycle(unsigned Cycle); + +public: + Pipeline(unsigned DispatchWidth = 0, unsigned RegisterFileSize = 0, + unsigned LoadQueueSize = 0, unsigned StoreQueueSize = 0, + bool AssumeNoAlias = false) + : Cycles(0) {} + void appendStage(std::unique_ptr S) { Stages.push_back(std::move(S)); } + 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 + +#endif // LLVM_TOOLS_LLVM_MCA_PIPELINE_H Index: llvm/trunk/tools/llvm-mca/Pipeline.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/Pipeline.cpp +++ llvm/trunk/tools/llvm-mca/Pipeline.cpp @@ -0,0 +1,112 @@ +//===--------------------- Pipeline.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file implements an ordered container of stages that simulate the +/// pipeline of a hardware backend. +/// +//===----------------------------------------------------------------------===// + +#include "Pipeline.h" +#include "HWEventListener.h" +#include "llvm/CodeGen/TargetSchedule.h" +#include "llvm/Support/Debug.h" + +namespace mca { + +#define DEBUG_TYPE "llvm-mca" + +using namespace llvm; + +void Pipeline::addEventListener(HWEventListener *Listener) { + if (Listener) + Listeners.insert(Listener); +} + +bool Pipeline::hasWorkToProcess() { + const auto It = llvm::find_if(Stages, [](const std::unique_ptr &S) { + return S->hasWorkToComplete(); + }); + return It != Stages.end(); +} + +// This routine returns early if any stage returns 'false' after execute() is +// called on it. +bool Pipeline::executeStages(InstRef &IR) { + for (const std::unique_ptr &S : Stages) + if (!S->execute(IR)) + return false; + return true; +} + +void Pipeline::postExecuteStages(const InstRef &IR) { + for (const std::unique_ptr &S : Stages) + S->postExecute(IR); +} + +void Pipeline::run() { + while (hasWorkToProcess()) + runCycle(Cycles++); +} + +void Pipeline::runCycle(unsigned Cycle) { + notifyCycleBegin(Cycle); + + // Update the stages before we do any processing for this cycle. + InstRef IR; + for (auto &S : Stages) + S->preExecute(IR); + + // Continue executing this cycle until any stage claims it cannot make + // progress. + while (executeStages(IR)) + postExecuteStages(IR); + + notifyCycleEnd(Cycle); +} + +void Pipeline::notifyCycleBegin(unsigned Cycle) { + LLVM_DEBUG(dbgs() << "[E] Cycle begin: " << Cycle << '\n'); + for (HWEventListener *Listener : Listeners) + 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) + Listener->onCycleEnd(); +} +} // namespace mca. Index: llvm/trunk/tools/llvm-mca/PipelinePrinter.h =================================================================== --- llvm/trunk/tools/llvm-mca/PipelinePrinter.h +++ llvm/trunk/tools/llvm-mca/PipelinePrinter.h @@ -0,0 +1,52 @@ +//===--------------------- PipelinePrinter.h --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file implements class PipelinePrinter. +/// +/// PipelinePrinter allows the customization of the performance report. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H +#define LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H + +#include "Pipeline.h" +#include "View.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "llvm-mca" + +namespace mca { + +/// A printer class that knows how to collects statistics on the +/// code analyzed by the llvm-mca tool. +/// +/// This class knows how to print out the analysis information collected +/// during the execution of the code. Internally, it delegates to other +/// classes the task of printing out timeline information as well as +/// resource pressure. +class PipelinePrinter { + Pipeline &P; + llvm::SmallVector, 8> Views; + +public: + PipelinePrinter(Pipeline &pipeline) : P(pipeline) {} + + void addView(std::unique_ptr V) { + P.addEventListener(V.get()); + Views.emplace_back(std::move(V)); + } + + void printReport(llvm::raw_ostream &OS) const; +}; +} // namespace mca + +#endif // LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H Index: llvm/trunk/tools/llvm-mca/PipelinePrinter.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/PipelinePrinter.cpp +++ llvm/trunk/tools/llvm-mca/PipelinePrinter.cpp @@ -0,0 +1,27 @@ +//===--------------------- PipelinePrinter.cpp ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file implements the PipelinePrinter interface. +/// +//===----------------------------------------------------------------------===// + +#include "PipelinePrinter.h" +#include "View.h" +#include "llvm/CodeGen/TargetSchedule.h" + +namespace mca { + +using namespace llvm; + +void PipelinePrinter::printReport(llvm::raw_ostream &OS) const { + for (const auto &V : Views) + V->printView(OS); +} +} // namespace mca. Index: llvm/trunk/tools/llvm-mca/README.txt =================================================================== --- llvm/trunk/tools/llvm-mca/README.txt +++ llvm/trunk/tools/llvm-mca/README.txt @@ -18,7 +18,7 @@ were inspired by the IACA tool from Intel. The presence of long data dependency chains, as well as poor usage of hardware -resources may lead to bottlenecks in the back-end. The tool is able to generate +resources may lead to bottlenecks in the backend. The tool is able to generate a detailed report which should help with identifying and analyzing sources of bottlenecks. @@ -54,12 +54,12 @@ The tool takes assembly code as input. Assembly code is parsed into a sequence of MCInst with the help of the existing LLVM target assembly parsers. The parsed -sequence of MCInst is then analyzed by a 'Backend' module to generate a +sequence of MCInst is then analyzed by a 'Pipeline' module to generate a performance report. -The Backend module internally emulates the execution of the machine code +The Pipeline module internally emulates the execution of the machine code sequence in a loop of iterations (which by default is 100). At the end of this -process, the backend collects a number of statistics which are then printed out +process, the pipeline collects a number of statistics which are then printed out in the form of a report. Here is an example of performance report generated by the tool for a dot-product @@ -311,7 +311,7 @@ JLSAGU, 0/12 /////////////////// -Based on the verbose report, the backend was only able to dispatch two +Based on the verbose report, the pipeline was only able to dispatch two instructions 51.5% of the time. The dispatch group was limited to one instruction 44.6% of the cycles, which corresponds to 272 cycles. @@ -344,8 +344,8 @@ LLVM-MCA instruction flow ------------------------- -This section describes the instruction flow through the out-of-order backend, as -well as the functional units involved in the process. +This section describes the instruction flow through the out-of-order backend, +as well as the functional units involved in the process. An instruction goes through a default sequence of stages: - Dispatch (Instruction is dispatched to the schedulers). Index: llvm/trunk/tools/llvm-mca/ResourcePressureView.h =================================================================== --- llvm/trunk/tools/llvm-mca/ResourcePressureView.h +++ llvm/trunk/tools/llvm-mca/ResourcePressureView.h @@ -10,7 +10,7 @@ /// /// This file define class ResourcePressureView. /// Class ResourcePressureView observes hardware events generated by -/// the Backend object and collects statistics related to resource usage at +/// the Pipeline object and collects statistics related to resource usage at /// instruction granularity. /// Resource pressure information is then printed out to a stream in the /// form of a table like the one from the example below: @@ -67,8 +67,6 @@ namespace mca { -class Backend; - /// This class collects resource pressure statistics and it is able to print /// out all the collected information as a table to an output stream. class ResourcePressureView : public View { Index: llvm/trunk/tools/llvm-mca/RetireStage.h =================================================================== --- llvm/trunk/tools/llvm-mca/RetireStage.h +++ llvm/trunk/tools/llvm-mca/RetireStage.h @@ -23,17 +23,17 @@ namespace mca { -class Backend; +class Pipeline; class RetireStage : public Stage { // Owner will go away when we move listeners/eventing to the stages. - Backend *Owner; + Pipeline *Owner; RetireControlUnit &RCU; RegisterFile &PRF; public: - RetireStage(Backend *B, RetireControlUnit &R, RegisterFile &F) - : Stage(), Owner(B), RCU(R), PRF(F) {} + RetireStage(Pipeline *P, RetireControlUnit &R, RegisterFile &F) + : Stage(), Owner(P), RCU(R), PRF(F) {} RetireStage(const RetireStage &Other) = delete; RetireStage &operator=(const RetireStage &Other) = delete; Index: llvm/trunk/tools/llvm-mca/RetireStage.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/RetireStage.cpp +++ llvm/trunk/tools/llvm-mca/RetireStage.cpp @@ -15,8 +15,8 @@ //===----------------------------------------------------------------------===// #include "RetireStage.h" -#include "Backend.h" #include "HWEventListener.h" +#include "Pipeline.h" #include "llvm/Support/Debug.h" using namespace llvm; Index: llvm/trunk/tools/llvm-mca/Scheduler.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/Scheduler.cpp +++ llvm/trunk/tools/llvm-mca/Scheduler.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "Scheduler.h" -#include "Backend.h" #include "HWEventListener.h" +#include "Pipeline.h" #include "Support.h" #include "llvm/Support/raw_ostream.h" Index: llvm/trunk/tools/llvm-mca/Support.h =================================================================== --- llvm/trunk/tools/llvm-mca/Support.h +++ llvm/trunk/tools/llvm-mca/Support.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// \file /// -/// Helper functions used by various backend components. +/// Helper functions used by various pipeline components. /// //===----------------------------------------------------------------------===// Index: llvm/trunk/tools/llvm-mca/Support.cpp =================================================================== --- llvm/trunk/tools/llvm-mca/Support.cpp +++ llvm/trunk/tools/llvm-mca/Support.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// \file /// -/// This file implements a few helper functions used by various backend +/// This file implements a few helper functions used by various pipeline /// components. /// //===----------------------------------------------------------------------===// Index: llvm/trunk/tools/llvm-mca/TimelineView.h =================================================================== --- llvm/trunk/tools/llvm-mca/TimelineView.h +++ llvm/trunk/tools/llvm-mca/TimelineView.h @@ -10,8 +10,8 @@ /// /// This file implements a timeline view for the llvm-mca tool. /// -/// Class TimelineView observes events generated by the backend. For every -/// instruction executed by the backend, it stores information related to +/// Class TimelineView observes events generated by the pipeline. For every +/// instruction executed by the pipeline, it stores information related to /// state transition. It then plots that information in the form of a table /// as reported by the example below: /// @@ -113,7 +113,7 @@ /// This class listens to instruction state transition events /// in order to construct a timeline information. /// -/// For every instruction executed by the Backend, this class constructs +/// For every instruction executed by the Pipeline, this class constructs /// a TimelineViewEntry object. TimelineViewEntry objects are then used /// to print the timeline information, as well as the "average wait times" /// for every instruction in the input assembly sequence. 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 @@ -21,7 +21,6 @@ // //===----------------------------------------------------------------------===// -#include "BackendPrinter.h" #include "CodeRegion.h" #include "DispatchStage.h" #include "DispatchStatistics.h" @@ -29,6 +28,8 @@ #include "FetchStage.h" #include "InstructionInfoView.h" #include "InstructionTables.h" +#include "Pipeline.h" +#include "PipelinePrinter.h" #include "RegisterFile.h" #include "RegisterFileStatistics.h" #include "ResourcePressureView.h" @@ -506,14 +507,14 @@ mca::Scheduler HWS(SM, LoadQueueSize, StoreQueueSize, AssumeNoAlias); // Create the pipeline and add stages to it. - auto B = llvm::make_unique( + auto P = llvm::make_unique( Width, RegisterFileSize, LoadQueueSize, StoreQueueSize, AssumeNoAlias); - B->appendStage(llvm::make_unique(IB, S)); - B->appendStage(llvm::make_unique( - B.get(), *STI, *MRI, RegisterFileSize, Width, RCU, PRF, HWS)); - B->appendStage(llvm::make_unique(B.get(), RCU, PRF)); - B->appendStage(llvm::make_unique(B.get(), RCU, HWS)); - mca::BackendPrinter Printer(*B); + 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)); + mca::PipelinePrinter Printer(*P); if (PrintSummaryView) Printer.addView(llvm::make_unique(SM, S, Width)); @@ -543,7 +544,7 @@ *STI, *IP, S, TimelineMaxIterations, TimelineMaxCycles)); } - B->run(); + P->run(); Printer.printReport(TOF->os()); }