LLVM: lib/MCA/Stages/InOrderIssueStage.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
19
20#define DEBUG_TYPE "llvm-mca"
21namespace llvm {
22namespace mca {
23
29
35
38 return;
39
41 return;
42
44}
45
49 : STI(STI), PRF(PRF), RM(STI.getSchedModel()), CB(CB), LSU(LSU),
50 NumIssued(), CarryOver(), Bandwidth(), LastWriteBackCycle() {}
51
53 return STI.getSchedModel().IssueWidth;
54}
55
57 return !IssuedInst.empty() || SI.isValid() || CarriedOver;
58}
59
61 if (SI.isValid() || CarriedOver)
62 return false;
63
66
67 bool ShouldCarryOver = NumMicroOps > getIssueWidth();
68 if (Bandwidth < NumMicroOps && !ShouldCarryOver)
69 return false;
70
71
72
74 return false;
75
76 return true;
77}
78
80 if (RM.checkAvailability(IR.getInstruction()->getDesc())) {
82 return true;
83 }
84
85 return false;
86}
87
89 unsigned FirstWBCycle = IR.getInstruction()->getLatency();
90 for (const WriteState &WS : IR.getInstruction()->getDefs()) {
91 int CyclesLeft = WS.getCyclesLeft();
93 CyclesLeft = WS.getLatency();
94 if (CyclesLeft < 0)
95 CyclesLeft = 0;
96 FirstWBCycle = std::min(FirstWBCycle, (unsigned)CyclesLeft);
97 }
98 return FirstWBCycle;
99}
100
101
102
106 for (const ReadState &RS : IR.getInstruction()->getUses()) {
110 }
111
112 return 0;
113}
114
115bool InOrderIssueStage::canExecute(const InstRef &IR) {
116 assert(.getCyclesLeft() && "Should not have reached this code!");
117 assert(.isValid() && "Should not have reached this code!");
118
121 return false;
122 }
123
126 return false;
127 }
128
129 if (IR.getInstruction()->isMemOp() && !LSU.isReady(IR)) {
130
131
133 return false;
134 }
135
136 if (unsigned CustomStallCycles = CB.checkCustomHazard(IssuedInst, IR)) {
138 return false;
139 }
140
141 if (LastWriteBackCycle) {
142 if (.getInstruction()->getRetireOOO()) {
144
145 if (NextWriteBackCycle < LastWriteBackCycle) {
146 SI.update(IR, LastWriteBackCycle - NextWriteBackCycle,
148 return false;
149 }
150 }
151 }
152
153 return true;
154}
155
157 unsigned SourceIndex,
161
164
167}
168
169void InOrderIssueStage::notifyInstructionIssued(const InstRef &IR,
174
176}
177
178void InOrderIssueStage::notifyInstructionDispatched(
179 const InstRef &IR, unsigned Ops, ArrayRef UsedRegs) {
181 HWInstructionDispatchedEvent(IR, UsedRegs, Ops));
182
184}
185
186void InOrderIssueStage::notifyInstructionExecuted(const InstRef &IR) {
189 LLVM_DEBUG(dbgs() << "[E] Instruction #" << IR << " is executed\n");
190}
191
192void InOrderIssueStage::notifyInstructionRetired(const InstRef &IR,
193 ArrayRef FreedRegs) {
196}
197
202
204 return E;
205
206 if (SI.isValid())
207 notifyStallEvent();
208
210}
211
214 unsigned SourceIndex = IR.getSourceIndex();
216
217 if (!canExecute(IR)) {
218 LLVM_DEBUG(dbgs() << "[N] Stalled #" << SI.getInstruction() << " for "
219 << SI.getCyclesLeft() << " cycles\n");
220 Bandwidth = 0;
222 }
223
226
229
231 notifyInstructionDispatched(IR, NumMicroOps, UsedRegs);
232
234 RM.issueInstruction(Desc, UsedResources);
236
239
240
243 Use.first.first = RM.resolveResourceMask(Mask);
244 }
245 notifyInstructionIssued(IR, UsedResources);
246
247 bool ShouldCarryOver = NumMicroOps > Bandwidth;
248 if (ShouldCarryOver) {
249 CarryOver = NumMicroOps - Bandwidth;
250 CarriedOver = IR;
251 Bandwidth = 0;
252 NumIssued += Bandwidth;
254 } else {
255 NumIssued += NumMicroOps;
256 Bandwidth = IS.getEndGroup() ? 0 : Bandwidth - NumMicroOps;
257 }
258
259
260
261
262
263 if (IS.isExecuted() && !ShouldCarryOver) {
264 PRF.onInstructionExecuted(&IS);
265 LSU.onInstructionExecuted(IR);
266 notifyInstructionExecuted(IR);
267
268 retireInstruction(IR);
269 return llvm::ErrorSuccess();
270 }
271
272 IssuedInst.push_back(IR);
273
274 if (.getInstruction()->getRetireOOO())
276
277 return llvm::ErrorSuccess();
278}
279
280void InOrderIssueStage::updateIssuedInst() {
281
282
283 unsigned NumExecuted = 0;
284 for (auto I = IssuedInst.begin(), E = IssuedInst.end();
285 I != (E - NumExecuted);) {
288
290 if (!IS.isExecuted()) {
292 << " is still executing\n");
293 ++I;
294 continue;
295 }
296
297
298
299
300 if (!CarriedOver) {
301 PRF.onInstructionExecuted(&IS);
302 LSU.onInstructionExecuted(IR);
303 notifyInstructionExecuted(IR);
304
305 retireInstruction(*I);
306 }
307
308 ++NumExecuted;
309
310 std::iter_swap(I, E - NumExecuted);
311 }
312
313 if (NumExecuted)
314 IssuedInst.resize(IssuedInst.size() - NumExecuted);
315}
316
317void InOrderIssueStage::updateCarriedOver() {
318 if (!CarriedOver)
319 return;
320
321 assert(!SI.isValid() && "A stalled instruction cannot be carried over.");
322
323 if (CarryOver > Bandwidth) {
324 CarryOver -= Bandwidth;
325 Bandwidth = 0;
326 LLVM_DEBUG(dbgs() << "[N] Carry over (" << CarryOver << "uops left) #"
327 << CarriedOver << " \n");
328 return;
329 }
330
331 LLVM_DEBUG(dbgs() << "[N] Carry over (complete) #" << CarriedOver << " \n");
332
333 if (CarriedOver.getInstruction()->getEndGroup())
334 Bandwidth = 0;
335 else
336 Bandwidth -= CarryOver;
337
338
339
340 if (CarriedOver.getInstruction()->isExecuted()) {
341 PRF.onInstructionExecuted(CarriedOver.getInstruction());
342 LSU.onInstructionExecuted(CarriedOver);
343 notifyInstructionExecuted(CarriedOver);
344
345 retireInstruction(CarriedOver);
346 }
347
348 CarriedOver = InstRef();
349 CarryOver = 0;
350}
351
352void InOrderIssueStage::retireInstruction(InstRef &IR) {
354 IS.retire();
355
356 llvm::SmallVector<unsigned, 4> FreedRegs(PRF.getNumRegisterFiles());
357 for (const WriteState &WS : IS.getDefs())
358 PRF.removeRegisterWrite(WS, FreedRegs);
359
360 if (IS.isMemOp())
361 LSU.onInstructionRetired(IR);
362
363 notifyInstructionRetired(IR, FreedRegs);
364}
365
366void InOrderIssueStage::notifyStallEvent() {
367 assert(SI.getCyclesLeft() && "A zero cycles stall?");
368 assert(SI.isValid() && "Invalid stall information found!");
369
370 const InstRef &IR = SI.getInstruction();
371
372 switch (SI.getStallKind()) {
373 default:
374 break;
380 break;
381 }
387 break;
388 }
392 break;
393 }
394 }
395}
396
398 NumIssued = 0;
400
401 PRF.cycleStart();
402 LSU.cycleEvent();
403
404
406 RM.cycleEvent(Freed);
407
408 updateIssuedInst();
409
410
411 updateCarriedOver();
412
413
414 if (SI.isValid()) {
415 if (!SI.getCyclesLeft()) {
416
417
418
419 InstRef IR = SI.getInstruction();
420 SI.clear();
421
423 return E;
424 }
425
426 if (SI.getCyclesLeft()) {
427
428
429 notifyStallEvent();
430 Bandwidth = 0;
432 }
433 }
434
437}
438
440 PRF.cycleEnd();
441 SI.cycleEnd();
442
443 if (LastWriteBackCycle > 0)
444 --LastWriteBackCycle;
445
447}
448
449}
450}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
InOrderIssueStage implements an in-order execution pipeline.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
A Load/Store unit class that models load/store queues and that implements a simple weak memory consis...
Legalize the Machine IR a function s Machine IR
This file defines abstractions used by the Pipeline to model register reads, register writes and inst...
StandardInstrumentations SI(Mod->getContext(), Debug, VerifyEach)
This file defines a register mapping file class.
This file simulates the hardware responsible for retiring instructions.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Subclass of Error for the sole purpose of identifying the success path in the type system.
Lightweight error class with error context and mandatory checking.
Generic base class for all target subtargets.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
Class which can be overriden by targets to enforce instruction dependencies and behaviours that aren'...
bool hasWorkToComplete() const override
Returns true if some instructions are still executing this stage.
Definition InOrderIssueStage.cpp:56
Error cycleEnd() override
Called once at the end of each cycle.
Definition InOrderIssueStage.cpp:439
Error execute(InstRef &IR) override
The primary action that this stage performs on instruction IR.
Definition InOrderIssueStage.cpp:198
bool isAvailable(const InstRef &) const override
Returns true if it can execute IR during this cycle.
Definition InOrderIssueStage.cpp:60
unsigned getIssueWidth() const
Definition InOrderIssueStage.cpp:52
Error cycleStart() override
Called once at the start of each cycle.
Definition InOrderIssueStage.cpp:397
An InstRef contains both a SourceMgr index and Instruction pair.
unsigned getNumMicroOps() const
const InstrDesc & getDesc() const
SmallVectorImpl< WriteState > & getDefs()
SmallVectorImpl< ReadState > & getUses()
bool getBeginGroup() const
An instruction propagated through the simulated instruction pipeline.
LLVM_ABI void cycleEvent()
bool isEliminated() const
int getCyclesLeft() const
LLVM_ABI void execute(unsigned IID)
void setLSUTokenID(unsigned LSUTok)
LLVM_ABI void dispatch(unsigned RCUTokenID)
Abstract base interface for LS (load/store) units in llvm-mca.
virtual void onInstructionIssued(const InstRef &IR)=0
Tracks register operand latency in cycles.
Manages hardware register files, and tracks register definitions for register renaming purposes.
void addRegisterWrite(WriteRef Write, MutableArrayRef< unsigned > UsedPhysRegs)
unsigned getNumRegisterFiles() const
RAWHazard checkRAWHazards(const MCSubtargetInfo &STI, const ReadState &RS) const
void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const
void notifyEvent(const EventT &Event) const
Notify listeners of a particular hardware event.
A reference to a register write.
Tracks uses of a register definition (e.g.
static void addRegisterReadWrite(RegisterFile &PRF, Instruction &IS, unsigned SourceIndex, const MCSubtargetInfo &STI, SmallVectorImpl< unsigned > &UsedRegs)
Definition InOrderIssueStage.cpp:156
static bool hasResourceHazard(const ResourceManager &RM, const InstRef &IR)
Definition InOrderIssueStage.cpp:79
static unsigned findFirstWriteBackCycle(const InstRef &IR)
Definition InOrderIssueStage.cpp:88
std::pair< ResourceRef, ReleaseAtCycles > ResourceUse
static unsigned checkRegisterHazard(const RegisterFile &PRF, const MCSubtargetInfo &STI, const InstRef &IR)
Return a number of cycles left until register requirements of the instructions are met.
Definition InOrderIssueStage.cpp:103
constexpr int UNKNOWN_CYCLES
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
An instruction descriptor.
bool hasUnknownCycles() const
static const unsigned UnhandledTokenID
void clear()
Definition InOrderIssueStage.cpp:24
void cycleEnd()
Definition InOrderIssueStage.cpp:36
void update(const InstRef &Inst, unsigned Cycles, StallKind SK)
Definition InOrderIssueStage.cpp:30