1 //===--------------------- Instruction.h ------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file defines abstractions used by the Pipeline to model register reads,
11 /// register writes and instructions.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_MCA_INSTRUCTION_H
16 #define LLVM_MCA_INSTRUCTION_H
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/Support/MathExtras.h"
24 #include "llvm/Support/raw_ostream.h"
33 constexpr int UNKNOWN_CYCLES
= -512;
35 /// A register write descriptor.
36 struct WriteDescriptor
{
37 // Operand index. The index is negative for implicit writes only.
38 // For implicit writes, the actual operand index is computed performing
39 // a bitwise not of the OpIndex.
41 // Write latency. Number of cycles before write-back stage.
43 // This field is set to a value different than zero only if this
44 // is an implicit definition.
46 // Instruction itineraries would set this field to the SchedClass ID.
47 // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry
48 // element associated to this write.
49 // When computing read latencies, this value is matched against the
50 // "ReadAdvance" information. The hardware backend may implement
51 // dedicated forwarding paths to quickly propagate write results to dependent
52 // instructions waiting in the reservation station (effectively bypassing the
54 unsigned SClassOrWriteResourceID
;
55 // True only if this is a write obtained from an optional definition.
56 // Optional definitions are allowed to reference regID zero (i.e. "no
60 bool isImplicitWrite() const { return OpIndex
< 0; };
63 /// A register read descriptor.
64 struct ReadDescriptor
{
65 // A MCOperand index. This is used by the Dispatch logic to identify register
66 // reads. Implicit reads have negative indices. The actual operand index of an
67 // implicit read is the bitwise not of field OpIndex.
69 // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit
70 // uses always come first in the sequence of uses.
72 // This field is only set if this is an implicit read.
74 // Scheduling Class Index. It is used to query the scheduling model for the
75 // MCSchedClassDesc object.
76 unsigned SchedClassID
;
78 bool isImplicitRead() const { return OpIndex
< 0; };
83 /// A critical data dependency descriptor.
85 /// Field RegID is set to the invalid register for memory dependencies.
86 struct CriticalDependency
{
92 /// Tracks uses of a register definition (e.g. register write).
94 /// Each implicit/explicit register write is associated with an instance of
95 /// this class. A WriteState object tracks the dependent users of a
96 /// register write. It also tracks how many cycles are left before the write
99 const WriteDescriptor
*WD
;
100 // On instruction issue, this field is set equal to the write latency.
101 // Before instruction issue, this field defaults to -512, a special
102 // value that represents an "unknown" number of cycles.
105 // Actual register defined by this write. This field is only used
106 // to speedup queries on the register file.
107 // For implicit writes, this field always matches the value of
108 // field RegisterID from WD.
111 // Physical register file that serves register RegisterID.
114 // True if this write implicitly clears the upper portion of RegisterID's
116 bool ClearsSuperRegs
;
118 // True if this write is from a dependency breaking zero-idiom instruction.
121 // True if this write has been eliminated at register renaming stage.
122 // Example: a register move doesn't consume scheduler/pipleline resources if
123 // it is eliminated at register renaming stage. It still consumes
124 // decode bandwidth, and ROB entries.
127 // This field is set if this is a partial register write, and it has a false
128 // dependency on any previous write of the same register (or a portion of it).
129 // DependentWrite must be able to complete before this write completes, so
130 // that we don't break the WAW, and the two writes can be merged together.
131 const WriteState
*DependentWrite
;
133 // A partial write that is in a false dependency with this write.
134 WriteState
*PartialWrite
;
135 unsigned DependentWriteCyclesLeft
;
137 // Critical register dependency for this write.
138 CriticalDependency CRD
;
140 // A list of dependent reads. Users is a set of dependent
141 // reads. A dependent read is added to the set only if CyclesLeft
142 // is "unknown". As soon as CyclesLeft is 'known', each user in the set
143 // gets notified with the actual CyclesLeft.
145 // The 'second' element of a pair is a "ReadAdvance" number of cycles.
146 SmallVector
<std::pair
<ReadState
*, int>, 4> Users
;
149 WriteState(const WriteDescriptor
&Desc
, unsigned RegID
,
150 bool clearsSuperRegs
= false, bool writesZero
= false)
151 : WD(&Desc
), CyclesLeft(UNKNOWN_CYCLES
), RegisterID(RegID
), PRFID(0),
152 ClearsSuperRegs(clearsSuperRegs
), WritesZero(writesZero
),
153 IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr),
154 DependentWriteCyclesLeft(0), CRD() {}
156 WriteState(const WriteState
&Other
) = default;
157 WriteState
&operator=(const WriteState
&Other
) = default;
159 int getCyclesLeft() const { return CyclesLeft
; }
160 unsigned getWriteResourceID() const { return WD
->SClassOrWriteResourceID
; }
161 unsigned getRegisterID() const { return RegisterID
; }
162 unsigned getRegisterFileID() const { return PRFID
; }
163 unsigned getLatency() const { return WD
->Latency
; }
164 unsigned getDependentWriteCyclesLeft() const {
165 return DependentWriteCyclesLeft
;
167 const WriteState
*getDependentWrite() const { return DependentWrite
; }
168 const CriticalDependency
&getCriticalRegDep() const { return CRD
; }
170 // This method adds Use to the set of data dependent reads. IID is the
171 // instruction identifier associated with this write. ReadAdvance is the
172 // number of cycles to subtract from the latency of this data dependency.
173 // Use is in a RAW dependency with this write.
174 void addUser(unsigned IID
, ReadState
*Use
, int ReadAdvance
);
176 // Use is a younger register write that is in a false dependency with this
177 // write. IID is the instruction identifier associated with this write.
178 void addUser(unsigned IID
, WriteState
*Use
);
180 unsigned getNumUsers() const {
181 unsigned NumUsers
= Users
.size();
187 bool clearsSuperRegisters() const { return ClearsSuperRegs
; }
188 bool isWriteZero() const { return WritesZero
; }
189 bool isEliminated() const { return IsEliminated
; }
191 bool isReady() const {
194 unsigned CyclesLeft
= getDependentWriteCyclesLeft();
195 return !CyclesLeft
|| CyclesLeft
< getLatency();
198 bool isExecuted() const {
199 return CyclesLeft
!= UNKNOWN_CYCLES
&& CyclesLeft
<= 0;
202 void setDependentWrite(const WriteState
*Other
) { DependentWrite
= Other
; }
203 void writeStartEvent(unsigned IID
, unsigned RegID
, unsigned Cycles
);
204 void setWriteZero() { WritesZero
= true; }
205 void setEliminated() {
206 assert(Users
.empty() && "Write is in an inconsistent state.");
211 void setPRF(unsigned PRF
) { PRFID
= PRF
; }
213 // On every cycle, update CyclesLeft and notify dependent users.
215 void onInstructionIssued(unsigned IID
);
222 /// Tracks register operand latency in cycles.
224 /// A read may be dependent on more than one write. This occurs when some
225 /// writes only partially update the register associated to this read.
227 const ReadDescriptor
*RD
;
228 // Physical register identified associated to this read.
230 // Physical register file that serves register RegisterID.
232 // Number of writes that contribute to the definition of RegisterID.
233 // In the absence of partial register updates, the number of DependentWrites
234 // cannot be more than one.
235 unsigned DependentWrites
;
236 // Number of cycles left before RegisterID can be read. This value depends on
237 // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES.
238 // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of
239 // every dependent write is known.
241 // This field is updated on every writeStartEvent(). When the number of
242 // dependent writes (i.e. field DependentWrite) is zero, this value is
243 // propagated to field CyclesLeft.
244 unsigned TotalCycles
;
245 // Longest register dependency.
246 CriticalDependency CRD
;
247 // This field is set to true only if there are no dependent writes, and
248 // there are no `CyclesLeft' to wait.
250 // True if this is a read from a known zero register.
252 // True if this register read is from a dependency-breaking instruction.
253 bool IndependentFromDef
;
256 ReadState(const ReadDescriptor
&Desc
, unsigned RegID
)
257 : RD(&Desc
), RegisterID(RegID
), PRFID(0), DependentWrites(0),
258 CyclesLeft(UNKNOWN_CYCLES
), TotalCycles(0), CRD(), IsReady(true),
259 IsZero(false), IndependentFromDef(false) {}
261 const ReadDescriptor
&getDescriptor() const { return *RD
; }
262 unsigned getSchedClass() const { return RD
->SchedClassID
; }
263 unsigned getRegisterID() const { return RegisterID
; }
264 unsigned getRegisterFileID() const { return PRFID
; }
265 const CriticalDependency
&getCriticalRegDep() const { return CRD
; }
267 bool isPending() const { return !IndependentFromDef
&& CyclesLeft
> 0; }
268 bool isReady() const { return IsReady
; }
269 bool isImplicitRead() const { return RD
->isImplicitRead(); }
271 bool isIndependentFromDef() const { return IndependentFromDef
; }
272 void setIndependentFromDef() { IndependentFromDef
= true; }
275 void writeStartEvent(unsigned IID
, unsigned RegID
, unsigned Cycles
);
276 void setDependentWrites(unsigned Writes
) {
277 DependentWrites
= Writes
;
281 bool isReadZero() const { return IsZero
; }
282 void setReadZero() { IsZero
= true; }
283 void setPRF(unsigned ID
) { PRFID
= ID
; }
286 /// A sequence of cycles.
288 /// This class can be used as a building block to construct ranges of cycles.
290 unsigned Begin
; // Inclusive.
291 unsigned End
; // Exclusive.
292 bool Reserved
; // Resources associated to this segment must be reserved.
295 CycleSegment(unsigned StartCycle
, unsigned EndCycle
, bool IsReserved
= false)
296 : Begin(StartCycle
), End(EndCycle
), Reserved(IsReserved
) {}
298 bool contains(unsigned Cycle
) const { return Cycle
>= Begin
&& Cycle
< End
; }
299 bool startsAfter(const CycleSegment
&CS
) const { return End
<= CS
.Begin
; }
300 bool endsBefore(const CycleSegment
&CS
) const { return Begin
>= CS
.End
; }
301 bool overlaps(const CycleSegment
&CS
) const {
302 return !startsAfter(CS
) && !endsBefore(CS
);
304 bool isExecuting() const { return Begin
== 0 && End
!= 0; }
305 bool isExecuted() const { return End
== 0; }
306 bool operator<(const CycleSegment
&Other
) const {
307 return Begin
< Other
.Begin
;
309 CycleSegment
&operator--(void) {
317 bool isValid() const { return Begin
<= End
; }
318 unsigned size() const { return End
- Begin
; };
319 void subtract(unsigned Cycles
) {
320 assert(End
>= Cycles
);
324 unsigned begin() const { return Begin
; }
325 unsigned end() const { return End
; }
326 void setEnd(unsigned NewEnd
) { End
= NewEnd
; }
327 bool isReserved() const { return Reserved
; }
328 void setReserved() { Reserved
= true; }
331 /// Helper used by class InstrDesc to describe how hardware resources
334 /// This class describes how many resource units of a specific resource kind
335 /// (and how many cycles) are "used" by an instruction.
336 struct ResourceUsage
{
339 ResourceUsage(CycleSegment Cycles
, unsigned Units
= 1)
340 : CS(Cycles
), NumUnits(Units
) {}
341 unsigned size() const { return CS
.size(); }
342 bool isReserved() const { return CS
.isReserved(); }
343 void setReserved() { CS
.setReserved(); }
346 /// An instruction descriptor
348 SmallVector
<WriteDescriptor
, 4> Writes
; // Implicit writes are at the end.
349 SmallVector
<ReadDescriptor
, 4> Reads
; // Implicit reads are at the end.
351 // For every resource used by an instruction of this kind, this vector
352 // reports the number of "consumed cycles".
353 SmallVector
<std::pair
<uint64_t, ResourceUsage
>, 4> Resources
;
355 // A list of buffered resources consumed by this instruction.
356 SmallVector
<uint64_t, 4> Buffers
;
358 unsigned UsedProcResUnits
;
359 unsigned UsedProcResGroups
;
362 // Number of MicroOps for this instruction.
363 unsigned NumMicroOps
;
364 // SchedClassID used to construct this InstrDesc.
365 // This information is currently used by views to do fast queries on the
366 // subtarget when computing the reciprocal throughput.
367 unsigned SchedClassID
;
375 // True if all buffered resources are in-order, and there is at least one
376 // buffer which is a dispatch hazard (BufferSize = 0).
377 bool MustIssueImmediately
;
379 // A zero latency instruction doesn't consume any scheduler resources.
380 bool isZeroLatency() const { return !MaxLatency
&& Resources
.empty(); }
382 InstrDesc() = default;
383 InstrDesc(const InstrDesc
&Other
) = delete;
384 InstrDesc
&operator=(const InstrDesc
&Other
) = delete;
387 /// Base class for instructions consumed by the simulation pipeline.
389 /// This class tracks data dependencies as well as generic properties
390 /// of the instruction.
391 class InstructionBase
{
392 const InstrDesc
&Desc
;
394 // This field is set for instructions that are candidates for move
395 // elimination. For more information about move elimination, see the
396 // definition of RegisterMappingTracker in RegisterFile.h
397 bool IsOptimizableMove
;
399 // Output dependencies.
400 // One entry per each implicit and explicit register definition.
401 SmallVector
<WriteState
, 4> Defs
;
403 // Input dependencies.
404 // One entry per each implicit and explicit register use.
405 SmallVector
<ReadState
, 4> Uses
;
408 InstructionBase(const InstrDesc
&D
) : Desc(D
), IsOptimizableMove(false) {}
410 SmallVectorImpl
<WriteState
> &getDefs() { return Defs
; }
411 const ArrayRef
<WriteState
> getDefs() const { return Defs
; }
412 SmallVectorImpl
<ReadState
> &getUses() { return Uses
; }
413 const ArrayRef
<ReadState
> getUses() const { return Uses
; }
414 const InstrDesc
&getDesc() const { return Desc
; }
416 unsigned getLatency() const { return Desc
.MaxLatency
; }
418 bool hasDependentUsers() const {
420 [](const WriteState
&Def
) { return Def
.getNumUsers() > 0; });
423 unsigned getNumUsers() const {
424 unsigned NumUsers
= 0;
425 for (const WriteState
&Def
: Defs
)
426 NumUsers
+= Def
.getNumUsers();
430 // Returns true if this instruction is a candidate for move elimination.
431 bool isOptimizableMove() const { return IsOptimizableMove
; }
432 void setOptimizableMove() { IsOptimizableMove
= true; }
433 bool isMemOp() const { return Desc
.MayLoad
|| Desc
.MayStore
; }
436 /// An instruction propagated through the simulated instruction pipeline.
438 /// This class is used to monitor changes to the internal state of instructions
439 /// that are sent to the various components of the simulated hardware pipeline.
440 class Instruction
: public InstructionBase
{
442 IS_INVALID
, // Instruction in an invalid state.
443 IS_DISPATCHED
, // Instruction dispatched but operands are not ready.
444 IS_PENDING
, // Instruction is not ready, but operand latency is known.
445 IS_READY
, // Instruction dispatched and operands ready.
446 IS_EXECUTING
, // Instruction issued.
447 IS_EXECUTED
, // Instruction executed. Values are written back.
448 IS_RETIRED
// Instruction retired.
451 // The current instruction stage.
452 enum InstrStage Stage
;
454 // This value defaults to the instruction latency. This instruction is
455 // considered executed when field CyclesLeft goes to zero.
458 // Retire Unit token ID for this instruction.
461 // LS token ID for this instruction.
462 // This field is set to the invalid null token if this is not a memory
466 // Critical register dependency.
467 CriticalDependency CriticalRegDep
;
469 // Critical memory dependency.
470 CriticalDependency CriticalMemDep
;
472 // A bitmask of busy processor resource units.
473 // This field is set to zero only if execution is not delayed during this
474 // cycle because of unavailable pipeline resources.
475 uint64_t CriticalResourceMask
;
477 // True if this instruction has been optimized at register renaming stage.
481 Instruction(const InstrDesc
&D
)
482 : InstructionBase(D
), Stage(IS_INVALID
), CyclesLeft(UNKNOWN_CYCLES
),
483 RCUTokenID(0), LSUTokenID(0), CriticalRegDep(), CriticalMemDep(),
484 CriticalResourceMask(0), IsEliminated(false) {}
486 unsigned getRCUTokenID() const { return RCUTokenID
; }
487 unsigned getLSUTokenID() const { return LSUTokenID
; }
488 void setLSUTokenID(unsigned LSUTok
) { LSUTokenID
= LSUTok
; }
489 int getCyclesLeft() const { return CyclesLeft
; }
491 // Transition to the dispatch stage, and assign a RCUToken to this
492 // instruction. The RCUToken is used to track the completion of every
493 // register write performed by this instruction.
494 void dispatch(unsigned RCUTokenID
);
496 // Instruction issued. Transition to the IS_EXECUTING state, and update
497 // all the register definitions.
498 void execute(unsigned IID
);
500 // Force a transition from the IS_DISPATCHED state to the IS_READY or
501 // IS_PENDING state. State transitions normally occur either at the beginning
502 // of a new cycle (see method cycleEvent()), or as a result of another issue
503 // event. This method is called every time the instruction might have changed
504 // in state. It internally delegates to method updateDispatched() and
507 bool updateDispatched();
508 bool updatePending();
510 bool isDispatched() const { return Stage
== IS_DISPATCHED
; }
511 bool isPending() const { return Stage
== IS_PENDING
; }
512 bool isReady() const { return Stage
== IS_READY
; }
513 bool isExecuting() const { return Stage
== IS_EXECUTING
; }
514 bool isExecuted() const { return Stage
== IS_EXECUTED
; }
515 bool isRetired() const { return Stage
== IS_RETIRED
; }
516 bool isEliminated() const { return IsEliminated
; }
518 // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
519 void forceExecuted();
520 void setEliminated() { IsEliminated
= true; }
523 assert(isExecuted() && "Instruction is in an invalid state!");
527 const CriticalDependency
&getCriticalRegDep() const { return CriticalRegDep
; }
528 const CriticalDependency
&getCriticalMemDep() const { return CriticalMemDep
; }
529 const CriticalDependency
&computeCriticalRegDep();
530 void setCriticalMemDep(const CriticalDependency
&MemDep
) {
531 CriticalMemDep
= MemDep
;
534 uint64_t getCriticalResourceMask() const { return CriticalResourceMask
; }
535 void setCriticalResourceMask(uint64_t ResourceMask
) {
536 CriticalResourceMask
= ResourceMask
;
542 /// An InstRef contains both a SourceMgr index and Instruction pair. The index
543 /// is used as a unique identifier for the instruction. MCA will make use of
544 /// this index as a key throughout MCA.
546 std::pair
<unsigned, Instruction
*> Data
;
549 InstRef() : Data(std::make_pair(0, nullptr)) {}
550 InstRef(unsigned Index
, Instruction
*I
) : Data(std::make_pair(Index
, I
)) {}
552 bool operator==(const InstRef
&Other
) const { return Data
== Other
.Data
; }
553 bool operator!=(const InstRef
&Other
) const { return Data
!= Other
.Data
; }
554 bool operator<(const InstRef
&Other
) const {
555 return Data
.first
< Other
.Data
.first
;
558 unsigned getSourceIndex() const { return Data
.first
; }
559 Instruction
*getInstruction() { return Data
.second
; }
560 const Instruction
*getInstruction() const { return Data
.second
; }
562 /// Returns true if this references a valid instruction.
563 explicit operator bool() const { return Data
.second
!= nullptr; }
565 /// Invalidate this reference.
566 void invalidate() { Data
.second
= nullptr; }
569 void print(raw_ostream
&OS
) const { OS
<< getSourceIndex(); }
574 inline raw_ostream
&operator<<(raw_ostream
&OS
, const InstRef
&IR
) {
580 /// A reference to a register write.
582 /// This class is mainly used by the register file to describe register
583 /// mappings. It correlates a register write to the source index of the
584 /// defining instruction.
586 std::pair
<unsigned, WriteState
*> Data
;
587 static const unsigned INVALID_IID
;
590 WriteRef() : Data(INVALID_IID
, nullptr) {}
591 WriteRef(unsigned SourceIndex
, WriteState
*WS
) : Data(SourceIndex
, WS
) {}
593 unsigned getSourceIndex() const { return Data
.first
; }
594 const WriteState
*getWriteState() const { return Data
.second
; }
595 WriteState
*getWriteState() { return Data
.second
; }
596 void invalidate() { Data
.second
= nullptr; }
597 bool isWriteZero() const {
598 assert(isValid() && "Invalid null WriteState found!");
599 return getWriteState()->isWriteZero();
602 /// Returns true if this register write has been executed, and the new
603 /// register value is therefore available to users.
604 bool isAvailable() const {
605 if (getSourceIndex() == INVALID_IID
)
607 const WriteState
*WS
= getWriteState();
608 return !WS
|| WS
->isExecuted();
611 bool isValid() const { return Data
.second
&& Data
.first
!= INVALID_IID
; }
612 bool operator==(const WriteRef
&Other
) const { return Data
== Other
.Data
; }
622 #endif // LLVM_MCA_INSTRUCTION_H