[llvm-mca] Introduce a sequential container of Stages
Summary:
Remove explicit stages and introduce a list of stages.
A pipeline should be composed of an arbitrary list of stages, and not any
predefined list of stages in the Backend. The Backend should not know of any
particular stage, rather it should only be concerned that it has a list of
stages, and that those stages will fulfill the contract of what it means to be
a Stage (namely pre/post/execute a given instruction).
For now, we leave the original set of stages defined in the Backend ctor;
however, I imagine these will be moved out at a later time.
This patch makes an adjustment to the semantics of Stage::isReady.
Specifically, what the Backend really needs to know is if a Stage has
unfinished work. With that said, it is more appropriately renamed
Stage::hasWorkToComplete(). This change will clean up the check in
Backend::run(), allowing us to query each stage to see if there is unfinished
work, regardless of what subclass a stage might be. I feel that this change
simplifies the semantics too, but that's a subjective statement.
Given how RetireStage and ExecuteStage handle data in their preExecute(), I've
had to change the order of Retire and Execute in our stage list. Retire must
complete any of its preExecute actions before ExecuteStage's preExecute can
take control. This is mainly because both stages utilize the RCU. In the
meantime, I want to see if I can adjust that or remove that coupling.
Reviewers: andreadb, RKSimon, courbet
Reviewed By: andreadb
Subscribers: tschuett, gbedwell, llvm-commits
Differential Revision: https://reviews.llvm.org/D46907
llvm-svn: 335361
diff --git a/llvm/tools/llvm-mca/Backend.h b/llvm/tools/llvm-mca/Backend.h
index 79e5bba..87969ae6 100644
--- a/llvm/tools/llvm-mca/Backend.h
+++ b/llvm/tools/llvm-mca/Backend.h
@@ -15,14 +15,9 @@
#ifndef LLVM_TOOLS_LLVM_MCA_BACKEND_H
#define LLVM_TOOLS_LLVM_MCA_BACKEND_H
-#include "DispatchStage.h"
-#include "ExecuteStage.h"
-#include "FetchStage.h"
-#include "InstrBuilder.h"
-#include "RegisterFile.h"
-#include "RetireControlUnit.h"
-#include "RetireStage.h"
#include "Scheduler.h"
+#include "Stage.h"
+#include "llvm/ADT/SmallVector.h"
namespace mca {
@@ -55,40 +50,22 @@
/// histograms. For example, it tracks how the dispatch group size changes
/// over time.
class Backend {
- // The following are the simulated hardware components of the backend.
- RetireControlUnit RCU;
- RegisterFile PRF;
- Scheduler HWS;
-
- /// TODO: Eventually this will become a list of unique Stage* that this
- /// backend pipeline executes.
- std::unique_ptr<FetchStage> Fetch;
- std::unique_ptr<DispatchStage> Dispatch;
- std::unique_ptr<ExecuteStage> Execute;
- std::unique_ptr<RetireStage> Retire;
-
+ /// An ordered list of stages that define this backend's instruction pipeline.
+ llvm::SmallVector<std::unique_ptr<Stage>, 8> Stages;
std::set<HWEventListener *> Listeners;
unsigned Cycles;
+ bool executeStages(InstRef &IR);
+ void postExecuteStages(const InstRef &IR);
+ bool hasWorkToProcess();
void runCycle(unsigned Cycle);
public:
- Backend(const llvm::MCSubtargetInfo &Subtarget,
- const llvm::MCRegisterInfo &MRI,
- std::unique_ptr<FetchStage> InitialStage, unsigned DispatchWidth = 0,
- unsigned RegisterFileSize = 0, unsigned LoadQueueSize = 0,
- unsigned StoreQueueSize = 0, bool AssumeNoAlias = false)
- : RCU(Subtarget.getSchedModel()),
- PRF(Subtarget.getSchedModel(), MRI, RegisterFileSize),
- HWS(Subtarget.getSchedModel(), LoadQueueSize, StoreQueueSize,
- AssumeNoAlias),
- Fetch(std::move(InitialStage)),
- Dispatch(llvm::make_unique<DispatchStage>(
- this, Subtarget, MRI, RegisterFileSize, DispatchWidth, RCU, PRF,
- HWS)),
- Execute(llvm::make_unique<ExecuteStage>(this, RCU, HWS)),
- Retire(llvm::make_unique<RetireStage>(this, RCU, PRF)), Cycles(0) {}
-
+ Backend(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();
void addEventListener(HWEventListener *Listener);
void notifyCycleBegin(unsigned Cycle);