Skip to content

Commit dffec12

Browse files
committed
[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
1 parent a1062f4 commit dffec12

File tree

3 files changed

+15
-11
lines changed

3 files changed

+15
-11
lines changed

llvm/tools/llvm-mca/include/Stages/EntryStage.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@
1919

2020
#include "SourceMgr.h"
2121
#include "Stages/Stage.h"
22-
#include <map>
22+
#include "llvm/ADT/SmallVector.h"
2323

2424
namespace llvm {
2525
namespace mca {
2626

2727
class EntryStage final : public Stage {
2828
InstRef CurrentInstruction;
29-
using InstMap = std::map<unsigned, std::unique_ptr<Instruction>>;
30-
InstMap Instructions;
29+
SmallVector<std::unique_ptr<Instruction>, 16> Instructions;
3130
SourceMgr &SM;
31+
unsigned NumRetired;
3232

3333
// Updates the program counter, and sets 'CurrentInstruction'.
3434
void getNextInstruction();
@@ -37,7 +37,7 @@ class EntryStage final : public Stage {
3737
EntryStage &operator=(const EntryStage &Other) = delete;
3838

3939
public:
40-
EntryStage(SourceMgr &SM) : CurrentInstruction(), SM(SM) {}
40+
EntryStage(SourceMgr &SM) : CurrentInstruction(), SM(SM), NumRetired(0) { }
4141

4242
bool isAvailable(const InstRef &IR) const override;
4343
bool hasWorkToComplete() const override;

llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ const RetireControlUnit::RUToken &RetireControlUnit::peekCurrentToken() const {
6060
}
6161

6262
void RetireControlUnit::consumeCurrentToken() {
63-
const RetireControlUnit::RUToken &Current = peekCurrentToken();
63+
RetireControlUnit::RUToken &Current = Queue[CurrentInstructionSlotIdx];
6464
assert(Current.NumSlots && "Reserved zero slots?");
6565
assert(Current.IR && "Invalid RUToken in the RCU queue.");
66+
Current.IR.getInstruction()->retire();
6667

6768
// Update the slot index to be the next item in the circular queue.
6869
CurrentInstructionSlotIdx += Current.NumSlots;

llvm/tools/llvm-mca/lib/Stages/EntryStage.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void EntryStage::getNextInstruction() {
3434
SourceRef SR = SM.peekNext();
3535
std::unique_ptr<Instruction> Inst = llvm::make_unique<Instruction>(SR.second);
3636
CurrentInstruction = InstRef(SR.first, Inst.get());
37-
Instructions[SR.first] = std::move(Inst);
37+
Instructions.emplace_back(std::move(Inst));
3838
SM.updateNext();
3939
}
4040

@@ -57,14 +57,17 @@ llvm::Error EntryStage::cycleStart() {
5757

5858
llvm::Error EntryStage::cycleEnd() {
5959
// Find the first instruction which hasn't been retired.
60-
const InstMap::iterator It =
61-
llvm::find_if(Instructions, [](const InstMap::value_type &KeyValuePair) {
62-
return !KeyValuePair.second->isRetired();
63-
});
60+
auto Range = make_range(&Instructions[NumRetired], Instructions.end());
61+
auto It = find_if(Range, [](const std::unique_ptr<Instruction> &I) {
62+
return !I->isRetired();
63+
});
6464

65+
NumRetired = std::distance(Instructions.begin(), It);
6566
// Erase instructions up to the first that hasn't been retired.
66-
if (It != Instructions.begin())
67+
if ((NumRetired * 2) >= Instructions.size()) {
6768
Instructions.erase(Instructions.begin(), It);
69+
NumRetired = 0;
70+
}
6871

6972
return llvm::ErrorSuccess();
7073
}

0 commit comments

Comments
 (0)