diff options
author | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2018-11-09 12:29:57 +0000 |
---|---|---|
committer | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2018-11-09 12:29:57 +0000 |
commit | dffec12f33cc0387a323e065638486f2e2bc23c4 (patch) | |
tree | 2d8d0a051c2c1780a1ed4c10aa45d0facbd9570f | |
parent | a1062f4b68c5a750a5b66e56753b10a3a72d7129 (diff) | |
download | bcm5719-llvm-dffec12f33cc0387a323e065638486f2e2bc23c4.tar.gz bcm5719-llvm-dffec12f33cc0387a323e065638486f2e2bc23c4.zip |
[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%.
llvm-svn: 346487
-rw-r--r-- | llvm/tools/llvm-mca/include/Stages/EntryStage.h | 8 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp | 3 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/lib/Stages/EntryStage.cpp | 15 |
3 files changed, 15 insertions, 11 deletions
diff --git a/llvm/tools/llvm-mca/include/Stages/EntryStage.h b/llvm/tools/llvm-mca/include/Stages/EntryStage.h index ed9f32f5d53..21b8331e95b 100644 --- a/llvm/tools/llvm-mca/include/Stages/EntryStage.h +++ b/llvm/tools/llvm-mca/include/Stages/EntryStage.h @@ -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; diff --git a/llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp b/llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp index 0456e1d7a5b..bd7b411af11 100644 --- a/llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp +++ b/llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp @@ -60,9 +60,10 @@ const RetireControlUnit::RUToken &RetireControlUnit::peekCurrentToken() const { } 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; diff --git a/llvm/tools/llvm-mca/lib/Stages/EntryStage.cpp b/llvm/tools/llvm-mca/lib/Stages/EntryStage.cpp index 929d51e824c..f552132cac6 100644 --- a/llvm/tools/llvm-mca/lib/Stages/EntryStage.cpp +++ b/llvm/tools/llvm-mca/lib/Stages/EntryStage.cpp @@ -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(); } |