[llvm] r346487 - [llvm-mca] Use a small vector for instructions in the EntryStage.

Andrea Di Biagio via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 9 04:29:57 PST 2018


Author: adibiagio
Date: Fri Nov  9 04:29:57 2018
New Revision: 346487

URL: http://llvm.org/viewvc/llvm-project?rev=346487&view=rev
Log:
[llvm-mca] Use a small vector for instructions in the EntryStage.

Use a simple SmallVector to track the lifetime of simulated instructions.
An ordered map was not needed because instructions are already picked in program
order. It is also much faster if we avoid searching for already retired
instructions at the end of every cycle.
The new policy only triggers a "garbage collection" when the number of retired
instructions becomes significantly big when compared with the total size of the
vector.

While working on this, I noticed that instructions were correctly retired, but
their internal state was not updated (i.e. there was no transition from the
EXECUTED state, to the RETIRED state). While this was not a problem for the
views, it prevented the EntryStage from correctly garbage collecting already
retired instructions. That was a bad oversight, and this patch fixes it.

The observed speedup on a debug build of llvm-mca after this patch is ~6%.
On a release build of llvm-mca, the observed speedup is ~%15%.

Modified:
    llvm/trunk/tools/llvm-mca/include/Stages/EntryStage.h
    llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp
    llvm/trunk/tools/llvm-mca/lib/Stages/EntryStage.cpp

Modified: llvm/trunk/tools/llvm-mca/include/Stages/EntryStage.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/Stages/EntryStage.h?rev=346487&r1=346486&r2=346487&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/Stages/EntryStage.h (original)
+++ llvm/trunk/tools/llvm-mca/include/Stages/EntryStage.h Fri Nov  9 04:29:57 2018
@@ -19,16 +19,16 @@
 
 #include "SourceMgr.h"
 #include "Stages/Stage.h"
-#include <map>
+#include "llvm/ADT/SmallVector.h"
 
 namespace llvm {
 namespace mca {
 
 class EntryStage final : public Stage {
   InstRef CurrentInstruction;
-  using InstMap = std::map<unsigned, std::unique_ptr<Instruction>>;
-  InstMap Instructions;
+  SmallVector<std::unique_ptr<Instruction>, 16> Instructions;
   SourceMgr &SM;
+  unsigned NumRetired;
 
   // Updates the program counter, and sets 'CurrentInstruction'.
   void getNextInstruction();
@@ -37,7 +37,7 @@ class EntryStage final : public Stage {
   EntryStage &operator=(const EntryStage &Other) = delete;
 
 public:
-  EntryStage(SourceMgr &SM) : CurrentInstruction(), SM(SM) {}
+  EntryStage(SourceMgr &SM) : CurrentInstruction(), SM(SM), NumRetired(0) { }
 
   bool isAvailable(const InstRef &IR) const override;
   bool hasWorkToComplete() const override;

Modified: llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp?rev=346487&r1=346486&r2=346487&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp Fri Nov  9 04:29:57 2018
@@ -60,9 +60,10 @@ const RetireControlUnit::RUToken &Retire
 }
 
 void RetireControlUnit::consumeCurrentToken() {
-  const RetireControlUnit::RUToken &Current = peekCurrentToken();
+  RetireControlUnit::RUToken &Current = Queue[CurrentInstructionSlotIdx];
   assert(Current.NumSlots && "Reserved zero slots?");
   assert(Current.IR && "Invalid RUToken in the RCU queue.");
+  Current.IR.getInstruction()->retire();
 
   // Update the slot index to be the next item in the circular queue.
   CurrentInstructionSlotIdx += Current.NumSlots;

Modified: llvm/trunk/tools/llvm-mca/lib/Stages/EntryStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/Stages/EntryStage.cpp?rev=346487&r1=346486&r2=346487&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/Stages/EntryStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/Stages/EntryStage.cpp Fri Nov  9 04:29:57 2018
@@ -34,7 +34,7 @@ void EntryStage::getNextInstruction() {
   SourceRef SR = SM.peekNext();
   std::unique_ptr<Instruction> Inst = llvm::make_unique<Instruction>(SR.second);
   CurrentInstruction = InstRef(SR.first, Inst.get());
-  Instructions[SR.first] = std::move(Inst);
+  Instructions.emplace_back(std::move(Inst));
   SM.updateNext();
 }
 
@@ -57,14 +57,17 @@ llvm::Error EntryStage::cycleStart() {
 
 llvm::Error EntryStage::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();
-      });
+  auto Range = make_range(&Instructions[NumRetired], Instructions.end());
+  auto It = find_if(Range, [](const std::unique_ptr<Instruction> &I) {
+    return !I->isRetired();
+  });
 
+  NumRetired = std::distance(Instructions.begin(), It);
   // Erase instructions up to the first that hasn't been retired.
-  if (It != Instructions.begin())
+  if ((NumRetired * 2) >= Instructions.size()) {
     Instructions.erase(Instructions.begin(), It);
+    NumRetired = 0;
+  }
 
   return llvm::ErrorSuccess();
 }




More information about the llvm-commits mailing list