]> granicus.if.org Git - llvm/commitdiff
[llvm-mca] Add cycleBegin/cycleEnd callbacks to mca::Stage.
authorMatt Davis <Matthew.Davis@sony.com>
Thu, 12 Jul 2018 22:59:53 +0000 (22:59 +0000)
committerMatt Davis <Matthew.Davis@sony.com>
Thu, 12 Jul 2018 22:59:53 +0000 (22:59 +0000)
Summary:
This patch  clears up some of the semantics within the Stage class.  Now, preExecute
can be called multiple times per simulated cycle.  Previously preExecute was
only called once per cycle, and postExecute could have been called multiple
times.

Now, cycleStart/cycleEnd are called only once per simulated cycle.
preExecute/postExecute can be called multiple times per cycle.  This
occurs because multiple execution events can occur during a single cycle.

When stages are executed (Pipeline::runCycle), the postExecute hook will
be called only if all Stages return a success from their 'execute' callback.

Reviewers: andreadb, courbet, RKSimon

Reviewed By: andreadb

Subscribers: tschuett, gbedwell, llvm-commits

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336959 91177308-0d34-0410-b5e6-96231b3b80d8

tools/llvm-mca/DispatchStage.cpp
tools/llvm-mca/DispatchStage.h
tools/llvm-mca/ExecuteStage.cpp
tools/llvm-mca/ExecuteStage.h
tools/llvm-mca/FetchStage.cpp
tools/llvm-mca/FetchStage.h
tools/llvm-mca/Pipeline.cpp
tools/llvm-mca/Pipeline.h
tools/llvm-mca/RetireStage.cpp
tools/llvm-mca/RetireStage.h
tools/llvm-mca/Stage.h

index 99cf8e077d10127b55353bdf944f4d671adba236..ad10fbe73e8df35a3c5bfa48a7afd3595a8675ab 100644 (file)
@@ -129,7 +129,7 @@ void DispatchStage::dispatch(InstRef IR) {
   notifyInstructionDispatched(IR, RegisterFiles);
 }
 
-void DispatchStage::preExecute(const InstRef &IR) {
+void DispatchStage::cycleStart() {
   AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
   CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
 }
index 65ac2bc73147e53c4d8c2670d5bfc90a868a69bf..f21789a29c50143d1331ffbe93c87a41889e86d0 100644 (file)
@@ -93,7 +93,7 @@ public:
   // The retire stage, which controls the RCU, might have items to complete but
   // RetireStage::hasWorkToComplete will check for that case.
   virtual bool hasWorkToComplete() const override final { return false; }
-  virtual void preExecute(const InstRef &IR) override final;
+  virtual void cycleStart() override final;
   virtual bool execute(InstRef &IR) override final;
   void notifyDispatchStall(const InstRef &IR, unsigned EventType);
 
index f2e458dcabd5cbedb04febe16398988f5c58d965..40957c26695ca1704416b6986ceb72258261e98e 100644 (file)
@@ -89,7 +89,7 @@ void ExecuteStage::issueReadyInstructions() {
 // Notifications are issued to this stage's listeners when instructions are
 // moved between the HWS's queues.  In particular, when an instruction becomes
 // ready or executed.
-void ExecuteStage::preExecute(const InstRef &Unused) {
+void ExecuteStage::cycleStart() {
   reclaimSchedulerResources();
   updateSchedulerQueues();
   issueReadyInstructions();
index 622fa0f983a781b4703a725a410f7177a03caf46..4914a9373e7cfca637730fc4dffc05297c755ff2 100644 (file)
@@ -45,7 +45,7 @@ public:
   // execute(), so it is never left in a 'to-be-processed' state.
   virtual bool hasWorkToComplete() const override final { return false; }
 
-  virtual void preExecute(const InstRef &IR) override final;
+  virtual void cycleStart() override final;
   virtual bool execute(InstRef &IR) override final;
 
   void
index 4ea1c6b0fe30e3c0dc24d145bc46195c58713610..654f1778f85584da48d0a0d481783b25210e62d6 100644 (file)
@@ -29,15 +29,18 @@ bool FetchStage::execute(InstRef &IR) {
   return true;
 }
 
-void FetchStage::postExecute(const InstRef &IR) {
+void FetchStage::postExecute(const InstRef &IR) { SM.updateNext(); }
+
+void FetchStage::cycleEnd() {
   // Find the first instruction which hasn't been retired.
   const InstMap::iterator It =
       llvm::find_if(Instructions, [](const InstMap::value_type &KeyValuePair) {
         return !KeyValuePair.second->isRetired();
       });
+
+  // Erase instructions up to the first that hasn't been retired.
   if (It != Instructions.begin())
     Instructions.erase(Instructions.begin(), It);
-  SM.updateNext();
 }
 
 } // namespace mca
index 4c70b7f2bc60e56719e9be842a83bf0c82eaefd9..c824b3221e559f7d12097930a173dc99af8415a5 100644 (file)
@@ -37,6 +37,7 @@ public:
   bool hasWorkToComplete() const override final;
   bool execute(InstRef &IR) override final;
   void postExecute(const InstRef &IR) override final;
+  void cycleEnd() override final;
 };
 
 } // namespace mca
index 716c43b7d02370f7d22dd901d1d41bbfa32c7989..ebaacb27a9f4779074aa46e7fd2c25a84f9a2cca 100644 (file)
@@ -47,6 +47,11 @@ bool Pipeline::executeStages(InstRef &IR) {
   return true;
 }
 
+void Pipeline::preExecuteStages(const InstRef &IR) {
+  for (const std::unique_ptr<Stage> &S : Stages)
+    S->preExecute(IR);
+}
+
 void Pipeline::postExecuteStages(const InstRef &IR) {
   for (const std::unique_ptr<Stage> &S : Stages)
     S->postExecute(IR);
@@ -63,12 +68,19 @@ void Pipeline::runCycle(unsigned Cycle) {
   // Update the stages before we do any processing for this cycle.
   InstRef IR;
   for (auto &S : Stages)
-    S->preExecute(IR);
+    S->cycleStart();
 
   // Continue executing this cycle until any stage claims it cannot make
   // progress.
-  while (executeStages(IR))
+  while (true) {
+    preExecuteStages(IR);
+    if (!executeStages(IR))
+      break;
     postExecuteStages(IR);
+  }
+
+  for (auto &S : Stages)
+    S->cycleEnd();
 
   notifyCycleEnd(Cycle);
 }
index 660c431a4767fc0ed124bda144002038b67b27f0..888d9c9d3680d2dd326f5bb0b8e991789df1c63e 100644 (file)
@@ -59,6 +59,7 @@ class Pipeline {
   std::set<HWEventListener *> Listeners;
   unsigned Cycles;
 
+  void preExecuteStages(const InstRef &IR);
   bool executeStages(InstRef &IR);
   void postExecuteStages(const InstRef &IR);
   bool hasWorkToProcess();
index b4dcc2860353ff518d84b0bfaed61fee7dd15421..a708c982cd37e8b261f1e4076a2f3e357be88b9b 100644 (file)
@@ -24,7 +24,7 @@ using namespace llvm;
 
 namespace mca {
 
-void RetireStage::preExecute(const InstRef &IR) {
+void RetireStage::cycleStart() {
   if (RCU.isEmpty())
     return;
 
index c91e7e2c21873249c03eeff86886ea2ac327e81e..8cf672d92c6e3809e3d267f4089d49b72fde9239 100644 (file)
@@ -37,7 +37,7 @@ public:
   virtual bool hasWorkToComplete() const override final {
     return !RCU.isEmpty();
   }
-  virtual void preExecute(const InstRef &IR) override final;
+  virtual void cycleStart() override final;
   virtual bool execute(InstRef &IR) override final { return true; }
   void notifyInstructionRetired(const InstRef &IR);
   void onInstructionExecuted(unsigned TokenID);
index 80d4906ec9b3354666eca76c82ef960efc3c375c..28216627634e5f38ac5e25134185607884fba391 100644 (file)
@@ -41,15 +41,25 @@ public:
   /// retire.
   virtual bool hasWorkToComplete() const = 0;
 
-  /// Called as a setup phase to prepare for the main stage execution.
+  /// Called once at the start of each cycle.  This can be used as a setup
+  /// phase to prepare for the executions during the cycle.
+  virtual void cycleStart() {}
+
+  /// Called once at the end of each cycle.
+  virtual void cycleEnd() {}
+
+  /// Called prior to executing the list of stages.
+  /// This can be called multiple times per cycle.
   virtual void preExecute(const InstRef &IR) {}
 
-  /// Called as a cleanup and finalization phase after main stage execution.
+  /// Called as a cleanup and finalization phase after each execution.
+  /// This will only be called if all stages return a success from their
+  /// execute callback.  This can be called multiple times per cycle.
   virtual void postExecute(const InstRef &IR) {}
 
   /// The primary action that this stage performs.
   /// Returning false prevents successor stages from having their 'execute'
-  /// routine called.
+  /// routine called.  This can be called multiple times during a single cycle.
   virtual bool execute(InstRef &IR) = 0;
 
   /// Add a listener to receive callbacks during the execution of this stage.