Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit c9a3110

Browse files
Matt DavisMatt Davis
Matt Davis
authored and
Matt Davis
committed
[llvm-mca] Avoid exposing index values in the MCA interfaces.
Summary: This patch eliminates many places where we originally needed to pass index values to represent an instruction. The index is still used as a key, in various parts of MCA. I'm not comfortable eliminating the index just yet. By burying the index in the instruction, we can avoid exposing that value in many places. Eventually, we should consider removing the Instructions list in the Backend all together, it's only used to hold and reclaim the memory for the allocated Instruction instances. Instead we could pass around a smart pointer. But that's a separate discussion/patch. Reviewers: andreadb, courbet, RKSimon Reviewed By: andreadb Subscribers: javed.absar, tschuett, gbedwell, llvm-commits Differential Revision: https://reviews.llvm.org/D46367 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@331660 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent a3a709f commit c9a3110

16 files changed

+204
-173
lines changed

tools/llvm-mca/Backend.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,15 @@ void Backend::runCycle(unsigned Cycle) {
3232
notifyCycleBegin(Cycle);
3333

3434
while (SM.hasNext()) {
35-
InstRef IR = SM.peekNext();
36-
std::unique_ptr<Instruction> NewIS = IB.createInstruction(*IR.second);
35+
SourceRef SR = SM.peekNext();
36+
std::unique_ptr<Instruction> NewIS = IB.createInstruction(*SR.second);
3737
const InstrDesc &Desc = NewIS->getDesc();
38-
if (!DU->isAvailable(Desc.NumMicroOps) ||
39-
!DU->canDispatch(IR.first, *NewIS))
40-
break;
41-
4238
Instruction *IS = NewIS.get();
43-
Instructions[IR.first] = std::move(NewIS);
44-
DU->dispatch(IR.first, IS, STI);
39+
InstRef IR(SR.first, IS);
40+
if (!DU->isAvailable(Desc.NumMicroOps) || !DU->canDispatch(IR))
41+
break;
42+
Instructions[SR.first] = std::move(NewIS);
43+
DU->dispatch(IR, STI);
4544
SM.updateNext();
4645
}
4746

tools/llvm-mca/Backend.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,9 @@ class Backend {
8080
runCycle(Cycles++);
8181
}
8282

83-
const Instruction &getInstruction(unsigned Index) const {
84-
const auto It = Instructions.find(Index);
85-
assert(It != Instructions.end() && "no running instructions with index");
86-
assert(It->second);
87-
return *It->second;
83+
void eraseInstruction(const InstRef &IR) {
84+
Instructions.erase(IR.getSourceIndex());
8885
}
89-
void eraseInstruction(unsigned Index) { Instructions.erase(Index); }
9086

9187
void addEventListener(HWEventListener *Listener);
9288
void notifyCycleBegin(unsigned Cycle);

tools/llvm-mca/Dispatch.cpp

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -252,50 +252,48 @@ void RegisterFile::dump() const {
252252
}
253253
#endif
254254

255-
void DispatchUnit::notifyInstructionDispatched(unsigned Index,
255+
void DispatchUnit::notifyInstructionDispatched(const InstRef &IR,
256256
ArrayRef<unsigned> UsedRegs) {
257-
DEBUG(dbgs() << "[E] Instruction Dispatched: " << Index << '\n');
258-
Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(Index, UsedRegs));
257+
DEBUG(dbgs() << "[E] Instruction Dispatched: " << IR << '\n');
258+
Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(IR, UsedRegs));
259259
}
260260

261-
void DispatchUnit::notifyInstructionRetired(unsigned Index) {
262-
DEBUG(dbgs() << "[E] Instruction Retired: " << Index << '\n');
263-
const Instruction &IS = Owner->getInstruction(Index);
261+
void DispatchUnit::notifyInstructionRetired(const InstRef &IR) {
262+
DEBUG(dbgs() << "[E] Instruction Retired: " << IR << '\n');
264263
SmallVector<unsigned, 4> FreedRegs(RAT->getNumRegisterFiles());
265-
for (const std::unique_ptr<WriteState> &WS : IS.getDefs())
264+
for (const std::unique_ptr<WriteState> &WS : IR.getInstruction()->getDefs())
266265
RAT->invalidateRegisterMapping(*WS.get(), FreedRegs);
267-
268-
Owner->notifyInstructionEvent(HWInstructionRetiredEvent(Index, FreedRegs));
269-
Owner->eraseInstruction(Index);
266+
Owner->notifyInstructionEvent(HWInstructionRetiredEvent(IR, FreedRegs));
267+
Owner->eraseInstruction(IR);
270268
}
271269

272-
bool DispatchUnit::checkRAT(unsigned Index, const Instruction &Instr) {
270+
bool DispatchUnit::checkRAT(const InstRef &IR) {
273271
SmallVector<unsigned, 4> RegDefs;
274-
for (const std::unique_ptr<WriteState> &RegDef : Instr.getDefs())
272+
for (const std::unique_ptr<WriteState> &RegDef :
273+
IR.getInstruction()->getDefs())
275274
RegDefs.emplace_back(RegDef->getRegisterID());
276275

277276
unsigned RegisterMask = RAT->isAvailable(RegDefs);
278277
// A mask with all zeroes means: register files are available.
279278
if (RegisterMask) {
280-
Owner->notifyStallEvent(
281-
HWStallEvent(HWStallEvent::RegisterFileStall, Index));
279+
Owner->notifyStallEvent(HWStallEvent(HWStallEvent::RegisterFileStall, IR));
282280
return false;
283281
}
284282

285283
return true;
286284
}
287285

288-
bool DispatchUnit::checkRCU(unsigned Index, const InstrDesc &Desc) {
289-
unsigned NumMicroOps = Desc.NumMicroOps;
286+
bool DispatchUnit::checkRCU(const InstRef &IR) {
287+
const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
290288
if (RCU->isAvailable(NumMicroOps))
291289
return true;
292290
Owner->notifyStallEvent(
293-
HWStallEvent(HWStallEvent::RetireControlUnitStall, Index));
291+
HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
294292
return false;
295293
}
296294

297-
bool DispatchUnit::checkScheduler(unsigned Index, const InstrDesc &Desc) {
298-
return SC->canBeDispatched(Index, Desc);
295+
bool DispatchUnit::checkScheduler(const InstRef &IR) {
296+
return SC->canBeDispatched(IR);
299297
}
300298

301299
void DispatchUnit::updateRAWDependencies(ReadState &RS,
@@ -326,10 +324,11 @@ void DispatchUnit::updateRAWDependencies(ReadState &RS,
326324
DependentWrites.clear();
327325
}
328326

329-
void DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
330-
const MCSubtargetInfo &STI) {
327+
void DispatchUnit::dispatch(InstRef IR, const MCSubtargetInfo &STI) {
331328
assert(!CarryOver && "Cannot dispatch another instruction!");
332-
unsigned NumMicroOps = NewInst->getDesc().NumMicroOps;
329+
Instruction &IS = *IR.getInstruction();
330+
const InstrDesc &Desc = IS.getDesc();
331+
const unsigned NumMicroOps = Desc.NumMicroOps;
333332
if (NumMicroOps > DispatchWidth) {
334333
assert(AvailableEntries == DispatchWidth);
335334
AvailableEntries = 0;
@@ -343,27 +342,26 @@ void DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
343342
// instruction. The assumption is that a zero-latency instruction doesn't
344343
// require to be issued to the scheduler for execution. More importantly, it
345344
// doesn't have to wait on the register input operands.
346-
const InstrDesc &Desc = NewInst->getDesc();
347345
if (Desc.MaxLatency || !Desc.Resources.empty())
348-
for (std::unique_ptr<ReadState> &RS : NewInst->getUses())
346+
for (std::unique_ptr<ReadState> &RS : IS.getUses())
349347
updateRAWDependencies(*RS, STI);
350348

351349
// Allocate new mappings.
352350
SmallVector<unsigned, 4> RegisterFiles(RAT->getNumRegisterFiles());
353-
for (std::unique_ptr<WriteState> &WS : NewInst->getDefs())
351+
for (std::unique_ptr<WriteState> &WS : IS.getDefs())
354352
RAT->addRegisterMapping(*WS, RegisterFiles);
355353

356354
// Reserve slots in the RCU, and notify the instruction that it has been
357355
// dispatched to the schedulers for execution.
358-
NewInst->dispatch(RCU->reserveSlot(IID, NumMicroOps));
356+
IS.dispatch(RCU->reserveSlot(IR, NumMicroOps));
359357

360358
// Notify listeners of the "instruction dispatched" event.
361-
notifyInstructionDispatched(IID, RegisterFiles);
359+
notifyInstructionDispatched(IR, RegisterFiles);
362360

363361
// Now move the instruction into the scheduler's queue.
364362
// The scheduler is responsible for checking if this is a zero-latency
365363
// instruction that doesn't consume pipeline/scheduler resources.
366-
SC->scheduleInstruction(IID, *NewInst);
364+
SC->scheduleInstruction(IR);
367365
}
368366

369367
#ifndef NDEBUG

tools/llvm-mca/Dispatch.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,12 @@ class DispatchUnit {
189189
std::unique_ptr<RetireControlUnit> RCU;
190190
Backend *Owner;
191191

192-
bool checkRAT(unsigned Index, const Instruction &Inst);
193-
bool checkRCU(unsigned Index, const InstrDesc &Desc);
194-
bool checkScheduler(unsigned Index, const InstrDesc &Desc);
192+
bool checkRAT(const InstRef &IR);
193+
bool checkRCU(const InstRef &IR);
194+
bool checkScheduler(const InstRef &IR);
195195

196196
void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI);
197-
void notifyInstructionDispatched(unsigned IID,
197+
void notifyInstructionDispatched(const InstRef &IR,
198198
llvm::ArrayRef<unsigned> UsedPhysRegs);
199199

200200
public:
@@ -214,14 +214,12 @@ class DispatchUnit {
214214

215215
bool isRCUEmpty() const { return RCU->isEmpty(); }
216216

217-
bool canDispatch(unsigned Index, const Instruction &Inst) {
218-
const InstrDesc &Desc = Inst.getDesc();
219-
assert(isAvailable(Desc.NumMicroOps));
220-
return checkRCU(Index, Desc) && checkRAT(Index, Inst) &&
221-
checkScheduler(Index, Desc);
217+
bool canDispatch(const InstRef &IR) {
218+
assert(isAvailable(IR.getInstruction()->getDesc().NumMicroOps));
219+
return checkRCU(IR) && checkRAT(IR) && checkScheduler(IR);
222220
}
223221

224-
void dispatch(unsigned IID, Instruction *I, const llvm::MCSubtargetInfo &STI);
222+
void dispatch(InstRef IR, const llvm::MCSubtargetInfo &STI);
225223

226224
void collectWrites(llvm::SmallVectorImpl<WriteState *> &Vec,
227225
unsigned RegID) const {
@@ -235,9 +233,9 @@ class DispatchUnit {
235233
CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
236234
}
237235

238-
void notifyInstructionRetired(unsigned Index);
236+
void notifyInstructionRetired(const InstRef &IR);
239237

240-
void notifyDispatchStall(unsigned Index, unsigned EventType);
238+
void notifyDispatchStall(const InstRef &IR, unsigned EventType);
241239

242240
void onInstructionExecuted(unsigned TokenID) {
243241
RCU->onInstructionExecuted(TokenID);

tools/llvm-mca/HWEventListener.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
//===----------------------- HWEventListener.h ------------------*- C++ -*-===//
32
//
43
// The LLVM Compiler Infrastructure
@@ -16,6 +15,7 @@
1615
#ifndef LLVM_TOOLS_LLVM_MCA_HWEVENTLISTENER_H
1716
#define LLVM_TOOLS_LLVM_MCA_HWEVENTLISTENER_H
1817

18+
#include "Instruction.h"
1919
#include "llvm/ADT/ArrayRef.h"
2020
#include <utility>
2121

@@ -48,30 +48,30 @@ class HWInstructionEvent {
4848
LastGenericEventType,
4949
};
5050

51-
HWInstructionEvent(unsigned type, unsigned index)
52-
: Type(type), Index(index) {}
51+
HWInstructionEvent(unsigned type, const InstRef &Inst)
52+
: Type(type), IR(Inst) {}
5353

5454
// The event type. The exact meaning depends on the subtarget.
5555
const unsigned Type;
56-
// The index of the instruction in the source manager.
57-
const unsigned Index;
56+
57+
// The instruction this event was generated for.
58+
const InstRef &IR;
5859
};
5960

6061
class HWInstructionIssuedEvent : public HWInstructionEvent {
6162
public:
6263
using ResourceRef = std::pair<uint64_t, uint64_t>;
63-
HWInstructionIssuedEvent(unsigned Index,
64+
HWInstructionIssuedEvent(const InstRef &IR,
6465
llvm::ArrayRef<std::pair<ResourceRef, double>> UR)
65-
: HWInstructionEvent(HWInstructionEvent::Issued, Index),
66-
UsedResources(UR) {}
66+
: HWInstructionEvent(HWInstructionEvent::Issued, IR), UsedResources(UR) {}
6767

6868
llvm::ArrayRef<std::pair<ResourceRef, double>> UsedResources;
6969
};
7070

7171
class HWInstructionDispatchedEvent : public HWInstructionEvent {
7272
public:
73-
HWInstructionDispatchedEvent(unsigned Index, llvm::ArrayRef<unsigned> Regs)
74-
: HWInstructionEvent(HWInstructionEvent::Dispatched, Index),
73+
HWInstructionDispatchedEvent(const InstRef &IR, llvm::ArrayRef<unsigned> Regs)
74+
: HWInstructionEvent(HWInstructionEvent::Dispatched, IR),
7575
UsedPhysRegs(Regs) {}
7676
// Number of physical register allocated for this instruction. There is one
7777
// entry per register file.
@@ -80,8 +80,8 @@ class HWInstructionDispatchedEvent : public HWInstructionEvent {
8080

8181
class HWInstructionRetiredEvent : public HWInstructionEvent {
8282
public:
83-
HWInstructionRetiredEvent(unsigned Index, llvm::ArrayRef<unsigned> Regs)
84-
: HWInstructionEvent(HWInstructionEvent::Retired, Index),
83+
HWInstructionRetiredEvent(const InstRef &IR, llvm::ArrayRef<unsigned> Regs)
84+
: HWInstructionEvent(HWInstructionEvent::Retired, IR),
8585
FreedPhysRegs(Regs) {}
8686
// Number of register writes that have been architecturally committed. There
8787
// is one entry per register file.
@@ -105,12 +105,13 @@ class HWStallEvent {
105105
LastGenericEvent
106106
};
107107

108-
HWStallEvent(unsigned type, unsigned index) : Type(type), Index(index) {}
108+
HWStallEvent(unsigned type, const InstRef &Inst) : Type(type), IR(Inst) {}
109109

110110
// The exact meaning of the stall event type depends on the subtarget.
111111
const unsigned Type;
112-
// The index of the instruction in the source manager.
113-
const unsigned Index;
112+
113+
// The instruction this event was generated for.
114+
const InstRef &IR;
114115
};
115116

116117
class HWEventListener {

tools/llvm-mca/Instruction.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define LLVM_TOOLS_LLVM_MCA_INSTRUCTION_H
1818

1919
#include "llvm/Support/MathExtras.h"
20+
#include "llvm/Support/raw_ostream.h"
2021
#include <memory>
2122
#include <set>
2223
#include <vector>
@@ -30,6 +31,36 @@ class ReadState;
3031

3132
constexpr int UNKNOWN_CYCLES = -512;
3233

34+
class Instruction;
35+
36+
/// An InstRef contains both a SourceMgr index and Instruction pair. The index
37+
/// is used as a unique identifier for the instruction. MCA will make use of
38+
/// this index as a key throughout MCA.
39+
class InstRef : public std::pair<unsigned, Instruction *> {
40+
public:
41+
InstRef() : std::pair<unsigned, Instruction *>(0, nullptr) {}
42+
InstRef(unsigned Index, Instruction *I)
43+
: std::pair<unsigned, Instruction *>(Index, I) {}
44+
45+
unsigned getSourceIndex() const { return first; }
46+
Instruction *getInstruction() { return second; }
47+
const Instruction *getInstruction() const { return second; }
48+
49+
/// Returns true if this InstRef has been populated.
50+
bool isValid() const { return second != nullptr; }
51+
52+
#ifndef NDEBUG
53+
void print(llvm::raw_ostream &OS) const { OS << getSourceIndex(); }
54+
#endif
55+
};
56+
57+
#ifndef NDEBUG
58+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const InstRef &IR) {
59+
IR.print(OS);
60+
return OS;
61+
}
62+
#endif
63+
3364
/// A register write descriptor.
3465
struct WriteDescriptor {
3566
// Operand index. -1 if this is an implicit write.

tools/llvm-mca/InstructionTables.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ void InstructionTables::run() {
3030
// Create an instruction descriptor for every instruction in the sequence.
3131
while (S.hasNext()) {
3232
UsedResources.clear();
33-
InstRef IR = S.peekNext();
34-
std::unique_ptr<Instruction> Inst = IB.createInstruction(*IR.second);
33+
SourceRef SR = S.peekNext();
34+
std::unique_ptr<Instruction> Inst = IB.createInstruction(*SR.second);
3535
const InstrDesc &Desc = Inst->getDesc();
3636
// Now identify the resources consumed by this instruction.
3737
for (const std::pair<uint64_t, ResourceUsage> Resource : Desc.Resources) {
@@ -70,7 +70,8 @@ void InstructionTables::run() {
7070
}
7171

7272
// Now send a fake instruction issued event to all the views.
73-
HWInstructionIssuedEvent Event(IR.first, UsedResources);
73+
InstRef IR(SR.first, Inst.get());
74+
HWInstructionIssuedEvent Event(IR, UsedResources);
7475
for (std::unique_ptr<View> &Listener : Views)
7576
Listener->onInstructionEvent(Event);
7677
S.updateNext();

tools/llvm-mca/LSUnit.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,15 @@ void LSUnit::assignSQSlot(unsigned Index) {
5050
StoreQueue.insert(Index);
5151
}
5252

53-
bool LSUnit::reserve(unsigned Index, const InstrDesc &Desc) {
53+
bool LSUnit::reserve(const InstRef &IR) {
54+
const InstrDesc Desc = IR.getInstruction()->getDesc();
5455
unsigned MayLoad = Desc.MayLoad;
5556
unsigned MayStore = Desc.MayStore;
5657
unsigned IsMemBarrier = Desc.HasSideEffects;
5758
if (!MayLoad && !MayStore)
5859
return false;
5960

61+
const unsigned Index = IR.getSourceIndex();
6062
if (MayLoad) {
6163
if (IsMemBarrier)
6264
LoadBarriers.insert(Index);
@@ -70,7 +72,8 @@ bool LSUnit::reserve(unsigned Index, const InstrDesc &Desc) {
7072
return true;
7173
}
7274

73-
bool LSUnit::isReady(unsigned Index) const {
75+
bool LSUnit::isReady(const InstRef &IR) const {
76+
const unsigned Index = IR.getSourceIndex();
7477
bool IsALoad = LoadQueue.count(Index) != 0;
7578
bool IsAStore = StoreQueue.count(Index) != 0;
7679
assert((IsALoad || IsAStore) && "Instruction is not in queue!");
@@ -116,7 +119,8 @@ bool LSUnit::isReady(unsigned Index) const {
116119
return !IsAStore;
117120
}
118121

119-
void LSUnit::onInstructionExecuted(unsigned Index) {
122+
void LSUnit::onInstructionExecuted(const InstRef &IR) {
123+
const unsigned Index = IR.getSourceIndex();
120124
std::set<unsigned>::iterator it = LoadQueue.find(Index);
121125
if (it != LoadQueue.end()) {
122126
DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index

0 commit comments

Comments
 (0)