[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.cpp b/llvm/tools/llvm-mca/Backend.cpp
index 3e7a365..c3e8d2f 100644
--- a/llvm/tools/llvm-mca/Backend.cpp
+++ b/llvm/tools/llvm-mca/Backend.cpp
@@ -13,7 +13,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "Backend.h"
-#include "FetchStage.h"
 #include "HWEventListener.h"
 #include "llvm/CodeGen/TargetSchedule.h"
 #include "llvm/Support/Debug.h"
@@ -29,8 +28,29 @@
     Listeners.insert(Listener);
 }
 
+bool Backend::hasWorkToProcess() {
+  const auto It = llvm::find_if(Stages, [](const std::unique_ptr<Stage> &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<Stage> &S : Stages)
+    if (!S->execute(IR))
+      return false;
+  return true;
+}
+
+void Backend::postExecuteStages(const InstRef &IR) {
+  for (const std::unique_ptr<Stage> &S : Stages)
+    S->postExecute(IR);
+}
+
 void Backend::run() {
-  while (Fetch->isReady() || !Dispatch->isReady())
+  while (hasWorkToProcess())
     runCycle(Cycles++);
 }
 
@@ -39,17 +59,13 @@
 
   // Update the stages before we do any processing for this cycle.
   InstRef IR;
-  Retire->preExecute(IR);
-  Dispatch->preExecute(IR);
-  Execute->preExecute(IR);
+  for (auto &S : Stages)
+    S->preExecute(IR);
 
-  // Fetch instructions and dispatch them to the hardware.
-  while (Fetch->execute(IR)) {
-    if (!Dispatch->execute(IR))
-      break;
-    Execute->execute(IR);
-    Fetch->postExecute(IR);
-  }
+  // Continue executing this cycle until any stage claims it cannot make
+  // progress.
+  while (executeStages(IR))
+    postExecuteStages(IR);
 
   notifyCycleEnd(Cycle);
 }