[llvm-mca] Rename Backend to Pipeline. NFC.

Summary:
This change renames the Backend and BackendPrinter to Pipeline and PipelinePrinter respectively. 
Variables and comments have also been updated to reflect this change.

The reason for this rename, is to be slightly more correct about what MCA is modeling.  MCA models a Pipeline, which implies some logical sequence of stages. 

Reviewers: andreadb, courbet, RKSimon

Reviewed By: andreadb, courbet

Subscribers: mgorny, javed.absar, tschuett, gbedwell, llvm-commits

Differential Revision: https://reviews.llvm.org/D48496

llvm-svn: 335496
This commit is contained in:
Matt Davis 2018-06-25 16:53:00 +00:00
parent 742553da13
commit dea343d2b3
22 changed files with 97 additions and 96 deletions

View File

@ -10,8 +10,6 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_tool(llvm-mca
Backend.cpp
BackendPrinter.cpp
CodeRegion.cpp
DispatchStage.cpp
DispatchStatistics.cpp
@ -24,6 +22,8 @@ add_llvm_tool(llvm-mca
InstructionTables.cpp
LSUnit.cpp
llvm-mca.cpp
Pipeline.cpp
PipelinePrinter.cpp
RegisterFile.cpp
RegisterFileStatistics.cpp
ResourcePressureView.cpp

View File

@ -17,8 +17,8 @@
//===----------------------------------------------------------------------===//
#include "DispatchStage.h"
#include "Backend.h"
#include "HWEventListener.h"
#include "Pipeline.h"
#include "Scheduler.h"
#include "llvm/Support/Debug.h"

View File

@ -30,7 +30,7 @@ namespace mca {
class WriteState;
class Scheduler;
class Backend;
class Pipeline;
// Implements the hardware dispatch logic.
//
@ -54,7 +54,7 @@ class DispatchStage : public Stage {
unsigned DispatchWidth;
unsigned AvailableEntries;
unsigned CarryOver;
Backend *Owner;
Pipeline *Owner;
const llvm::MCSubtargetInfo &STI;
RetireControlUnit &RCU;
RegisterFile &PRF;
@ -84,12 +84,12 @@ class DispatchStage : public Stage {
}
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

View File

@ -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"

View File

@ -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 @@ class ExecuteStage : public Stage {
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;

View File

@ -27,11 +27,11 @@ namespace mca {
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 @@ public:
class HWEventListener {
public:
// Generic events generated by the backend pipeline.
// Generic events generated by the pipeline.
virtual void onCycleBegin() {}
virtual void onCycleEnd() {}

View File

@ -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.
//
//===----------------------------------------------------------------------===//

View File

@ -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 @@ struct InstrDesc {
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;

View File

@ -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.
///
//===----------------------------------------------------------------------===//

View File

@ -1,4 +1,4 @@
//===--------------------- Backend.cpp --------------------------*- C++ -*-===//
//===--------------------- Pipeline.cpp -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -8,11 +8,12 @@
//===----------------------------------------------------------------------===//
/// \file
///
/// Implementation of class Backend which emulates an hardware OoO backend.
/// This file implements an ordered container of stages that simulate the
/// pipeline of a hardware backend.
///
//===----------------------------------------------------------------------===//
#include "Backend.h"
#include "Pipeline.h"
#include "HWEventListener.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Support/Debug.h"
@ -23,12 +24,12 @@ namespace mca {
using namespace llvm;
void Backend::addEventListener(HWEventListener *Listener) {
void Pipeline::addEventListener(HWEventListener *Listener) {
if (Listener)
Listeners.insert(Listener);
}
bool Backend::hasWorkToProcess() {
bool Pipeline::hasWorkToProcess() {
const auto It = llvm::find_if(Stages, [](const std::unique_ptr<Stage> &S) {
return S->hasWorkToComplete();
});
@ -37,24 +38,24 @@ bool Backend::hasWorkToProcess() {
// This routine returns early if any stage returns 'false' after execute() is
// called on it.
bool Backend::executeStages(InstRef &IR) {
bool Pipeline::executeStages(InstRef &IR) {
for (const std::unique_ptr<Stage> &S : Stages)
if (!S->execute(IR))
return false;
return true;
}
void Backend::postExecuteStages(const InstRef &IR) {
void Pipeline::postExecuteStages(const InstRef &IR) {
for (const std::unique_ptr<Stage> &S : Stages)
S->postExecute(IR);
}
void Backend::run() {
void Pipeline::run() {
while (hasWorkToProcess())
runCycle(Cycles++);
}
void Backend::runCycle(unsigned Cycle) {
void Pipeline::runCycle(unsigned Cycle) {
notifyCycleBegin(Cycle);
// Update the stages before we do any processing for this cycle.
@ -70,40 +71,40 @@ void Backend::runCycle(unsigned Cycle) {
notifyCycleEnd(Cycle);
}
void Backend::notifyCycleBegin(unsigned Cycle) {
void Pipeline::notifyCycleBegin(unsigned Cycle) {
LLVM_DEBUG(dbgs() << "[E] Cycle begin: " << Cycle << '\n');
for (HWEventListener *Listener : Listeners)
Listener->onCycleBegin();
}
void Backend::notifyInstructionEvent(const HWInstructionEvent &Event) {
void Pipeline::notifyInstructionEvent(const HWInstructionEvent &Event) {
for (HWEventListener *Listener : Listeners)
Listener->onInstructionEvent(Event);
}
void Backend::notifyStallEvent(const HWStallEvent &Event) {
void Pipeline::notifyStallEvent(const HWStallEvent &Event) {
for (HWEventListener *Listener : Listeners)
Listener->onStallEvent(Event);
}
void Backend::notifyResourceAvailable(const ResourceRef &RR) {
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 Backend::notifyReservedBuffers(ArrayRef<unsigned> Buffers) {
void Pipeline::notifyReservedBuffers(ArrayRef<unsigned> Buffers) {
for (HWEventListener *Listener : Listeners)
Listener->onReservedBuffers(Buffers);
}
void Backend::notifyReleasedBuffers(ArrayRef<unsigned> Buffers) {
void Pipeline::notifyReleasedBuffers(ArrayRef<unsigned> Buffers) {
for (HWEventListener *Listener : Listeners)
Listener->onReleasedBuffers(Buffers);
}
void Backend::notifyCycleEnd(unsigned Cycle) {
void Pipeline::notifyCycleEnd(unsigned Cycle) {
LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycle << "\n\n");
for (HWEventListener *Listener : Listeners)
Listener->onCycleEnd();

View File

@ -1,4 +1,4 @@
//===--------------------- Backend.h ----------------------------*- C++ -*-===//
//===--------------------- Pipeline.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -8,12 +8,13 @@
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements an OoO backend for the llvm-mca tool.
/// This file implements an ordered container of stages that simulate the
/// pipeline of a hardware backend.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_MCA_BACKEND_H
#define LLVM_TOOLS_LLVM_MCA_BACKEND_H
#ifndef LLVM_TOOLS_LLVM_MCA_PIPELINE_H
#define LLVM_TOOLS_LLVM_MCA_PIPELINE_H
#include "Scheduler.h"
#include "Stage.h"
@ -25,7 +26,7 @@ class HWEventListener;
class HWInstructionEvent;
class HWStallEvent;
/// An out of order backend for a specific subtarget.
/// 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.
@ -42,15 +43,15 @@ class HWStallEvent;
/// 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
/// 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 Backend collects statistical information in the form of
/// Internally, the Pipeline 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.
class Pipeline {
/// An ordered list of stages that define this instruction pipeline.
llvm::SmallVector<std::unique_ptr<Stage>, 8> Stages;
std::set<HWEventListener *> Listeners;
unsigned Cycles;
@ -61,9 +62,9 @@ class Backend {
void runCycle(unsigned Cycle);
public:
Backend(unsigned DispatchWidth = 0, unsigned RegisterFileSize = 0,
unsigned LoadQueueSize = 0, unsigned StoreQueueSize = 0,
bool AssumeNoAlias = false)
Pipeline(unsigned DispatchWidth = 0, unsigned RegisterFileSize = 0,
unsigned LoadQueueSize = 0, unsigned StoreQueueSize = 0,
bool AssumeNoAlias = false)
: Cycles(0) {}
void appendStage(std::unique_ptr<Stage> S) { Stages.push_back(std::move(S)); }
void run();
@ -78,4 +79,4 @@ public:
};
} // namespace mca
#endif
#endif // LLVM_TOOLS_LLVM_MCA_PIPELINE_H

View File

@ -1,4 +1,4 @@
//===--------------------- BackendPrinter.cpp -------------------*- C++ -*-===//
//===--------------------- PipelinePrinter.cpp ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -8,11 +8,11 @@
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements the BackendPrinter interface.
/// This file implements the PipelinePrinter interface.
///
//===----------------------------------------------------------------------===//
#include "BackendPrinter.h"
#include "PipelinePrinter.h"
#include "View.h"
#include "llvm/CodeGen/TargetSchedule.h"
@ -20,7 +20,7 @@ namespace mca {
using namespace llvm;
void BackendPrinter::printReport(llvm::raw_ostream &OS) const {
void PipelinePrinter::printReport(llvm::raw_ostream &OS) const {
for (const auto &V : Views)
V->printView(OS);
}

View File

@ -1,4 +1,4 @@
//===--------------------- BackendPrinter.h ---------------------*- C++ -*-===//
//===--------------------- PipelinePrinter.h --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -8,16 +8,16 @@
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements class BackendPrinter.
/// This file implements class PipelinePrinter.
///
/// BackendPrinter allows the customization of the performance report.
/// PipelinePrinter allows the customization of the performance report.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_MCA_BACKENDPRINTER_H
#define LLVM_TOOLS_LLVM_MCA_BACKENDPRINTER_H
#ifndef LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H
#define LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H
#include "Backend.h"
#include "Pipeline.h"
#include "View.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"
@ -33,15 +33,15 @@ namespace mca {
/// 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;
class PipelinePrinter {
Pipeline &P;
llvm::SmallVector<std::unique_ptr<View>, 8> Views;
public:
BackendPrinter(Backend &backend) : B(backend) {}
PipelinePrinter(Pipeline &pipeline) : P(pipeline) {}
void addView(std::unique_ptr<View> V) {
B.addEventListener(V.get());
P.addEventListener(V.get());
Views.emplace_back(std::move(V));
}
@ -49,4 +49,4 @@ public:
};
} // namespace mca
#endif
#endif // LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H

View File

@ -18,7 +18,7 @@ cycle), as well as hardware resources pressure. The analysis and reporting style
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 @@ How the tool works
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 @@ JFPU01, 18/18
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 @@ dependencies, and not by resource pressure.
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).

View File

@ -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 {

View File

@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
#include "RetireStage.h"
#include "Backend.h"
#include "HWEventListener.h"
#include "Pipeline.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

View File

@ -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;

View File

@ -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"

View File

@ -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.
///
//===----------------------------------------------------------------------===//

View File

@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
/// \file
///
/// Helper functions used by various backend components.
/// Helper functions used by various pipeline components.
///
//===----------------------------------------------------------------------===//

View File

@ -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 @@ namespace mca {
/// 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.

View File

@ -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 @@ int main(int argc, char **argv) {
mca::Scheduler HWS(SM, LoadQueueSize, StoreQueueSize, AssumeNoAlias);
// Create the pipeline and add stages to it.
auto B = llvm::make_unique<mca::Backend>(
auto P = llvm::make_unique<mca::Pipeline>(
Width, RegisterFileSize, LoadQueueSize, StoreQueueSize, AssumeNoAlias);
B->appendStage(llvm::make_unique<mca::FetchStage>(IB, S));
B->appendStage(llvm::make_unique<mca::DispatchStage>(
B.get(), *STI, *MRI, RegisterFileSize, Width, RCU, PRF, HWS));
B->appendStage(llvm::make_unique<mca::RetireStage>(B.get(), RCU, PRF));
B->appendStage(llvm::make_unique<mca::ExecuteStage>(B.get(), RCU, HWS));
mca::BackendPrinter Printer(*B);
P->appendStage(llvm::make_unique<mca::FetchStage>(IB, S));
P->appendStage(llvm::make_unique<mca::DispatchStage>(
P.get(), *STI, *MRI, RegisterFileSize, Width, RCU, PRF, HWS));
P->appendStage(llvm::make_unique<mca::RetireStage>(P.get(), RCU, PRF));
P->appendStage(llvm::make_unique<mca::ExecuteStage>(P.get(), RCU, HWS));
mca::PipelinePrinter Printer(*P);
if (PrintSummaryView)
Printer.addView(llvm::make_unique<mca::SummaryView>(SM, S, Width));
@ -543,7 +544,7 @@ int main(int argc, char **argv) {
*STI, *IP, S, TimelineMaxIterations, TimelineMaxCycles));
}
B->run();
P->run();
Printer.printReport(TOF->os());
}