[llvm] [cmake] Add possibility to use ChooseMSVCCRT.cmake when include LLVM library
[llvm-core.git] / include / llvm / MCA / Instruction.h
blobc97cb463d0f58a59b217d2c97066f8010eb280ee
1 //===--------------------- Instruction.h ------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file defines abstractions used by the Pipeline to model register reads,
11 /// register writes and instructions.
12 ///
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/MC/MCRegister.h" // definition of MCPhysReg.
22 #include "llvm/Support/MathExtras.h"
24 #ifndef NDEBUG
25 #include "llvm/Support/raw_ostream.h"
26 #endif
28 #include <memory>
30 namespace llvm {
32 namespace mca {
34 constexpr int UNKNOWN_CYCLES = -512;
36 /// A register write descriptor.
37 struct WriteDescriptor {
38 // Operand index. The index is negative for implicit writes only.
39 // For implicit writes, the actual operand index is computed performing
40 // a bitwise not of the OpIndex.
41 int OpIndex;
42 // Write latency. Number of cycles before write-back stage.
43 unsigned Latency;
44 // This field is set to a value different than zero only if this
45 // is an implicit definition.
46 MCPhysReg RegisterID;
47 // Instruction itineraries would set this field to the SchedClass ID.
48 // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry
49 // element associated to this write.
50 // When computing read latencies, this value is matched against the
51 // "ReadAdvance" information. The hardware backend may implement
52 // dedicated forwarding paths to quickly propagate write results to dependent
53 // instructions waiting in the reservation station (effectively bypassing the
54 // write-back stage).
55 unsigned SClassOrWriteResourceID;
56 // True only if this is a write obtained from an optional definition.
57 // Optional definitions are allowed to reference regID zero (i.e. "no
58 // register").
59 bool IsOptionalDef;
61 bool isImplicitWrite() const { return OpIndex < 0; };
64 /// A register read descriptor.
65 struct ReadDescriptor {
66 // A MCOperand index. This is used by the Dispatch logic to identify register
67 // reads. Implicit reads have negative indices. The actual operand index of an
68 // implicit read is the bitwise not of field OpIndex.
69 int OpIndex;
70 // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit
71 // uses always come first in the sequence of uses.
72 unsigned UseIndex;
73 // This field is only set if this is an implicit read.
74 MCPhysReg RegisterID;
75 // Scheduling Class Index. It is used to query the scheduling model for the
76 // MCSchedClassDesc object.
77 unsigned SchedClassID;
79 bool isImplicitRead() const { return OpIndex < 0; };
82 class ReadState;
84 /// A critical data dependency descriptor.
85 ///
86 /// Field RegID is set to the invalid register for memory dependencies.
87 struct CriticalDependency {
88 unsigned IID;
89 MCPhysReg RegID;
90 unsigned Cycles;
93 /// Tracks uses of a register definition (e.g. register write).
94 ///
95 /// Each implicit/explicit register write is associated with an instance of
96 /// this class. A WriteState object tracks the dependent users of a
97 /// register write. It also tracks how many cycles are left before the write
98 /// back stage.
99 class WriteState {
100 const WriteDescriptor *WD;
101 // On instruction issue, this field is set equal to the write latency.
102 // Before instruction issue, this field defaults to -512, a special
103 // value that represents an "unknown" number of cycles.
104 int CyclesLeft;
106 // Actual register defined by this write. This field is only used
107 // to speedup queries on the register file.
108 // For implicit writes, this field always matches the value of
109 // field RegisterID from WD.
110 MCPhysReg RegisterID;
112 // Physical register file that serves register RegisterID.
113 unsigned PRFID;
115 // True if this write implicitly clears the upper portion of RegisterID's
116 // super-registers.
117 bool ClearsSuperRegs;
119 // True if this write is from a dependency breaking zero-idiom instruction.
120 bool WritesZero;
122 // True if this write has been eliminated at register renaming stage.
123 // Example: a register move doesn't consume scheduler/pipleline resources if
124 // it is eliminated at register renaming stage. It still consumes
125 // decode bandwidth, and ROB entries.
126 bool IsEliminated;
128 // This field is set if this is a partial register write, and it has a false
129 // dependency on any previous write of the same register (or a portion of it).
130 // DependentWrite must be able to complete before this write completes, so
131 // that we don't break the WAW, and the two writes can be merged together.
132 const WriteState *DependentWrite;
134 // A partial write that is in a false dependency with this write.
135 WriteState *PartialWrite;
136 unsigned DependentWriteCyclesLeft;
138 // Critical register dependency for this write.
139 CriticalDependency CRD;
141 // A list of dependent reads. Users is a set of dependent
142 // reads. A dependent read is added to the set only if CyclesLeft
143 // is "unknown". As soon as CyclesLeft is 'known', each user in the set
144 // gets notified with the actual CyclesLeft.
146 // The 'second' element of a pair is a "ReadAdvance" number of cycles.
147 SmallVector<std::pair<ReadState *, int>, 4> Users;
149 public:
150 WriteState(const WriteDescriptor &Desc, MCPhysReg RegID,
151 bool clearsSuperRegs = false, bool writesZero = false)
152 : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0),
153 ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero),
154 IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr),
155 DependentWriteCyclesLeft(0), CRD() {}
157 WriteState(const WriteState &Other) = default;
158 WriteState &operator=(const WriteState &Other) = default;
160 int getCyclesLeft() const { return CyclesLeft; }
161 unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; }
162 MCPhysReg getRegisterID() const { return RegisterID; }
163 unsigned getRegisterFileID() const { return PRFID; }
164 unsigned getLatency() const { return WD->Latency; }
165 unsigned getDependentWriteCyclesLeft() const {
166 return DependentWriteCyclesLeft;
168 const WriteState *getDependentWrite() const { return DependentWrite; }
169 const CriticalDependency &getCriticalRegDep() const { return CRD; }
171 // This method adds Use to the set of data dependent reads. IID is the
172 // instruction identifier associated with this write. ReadAdvance is the
173 // number of cycles to subtract from the latency of this data dependency.
174 // Use is in a RAW dependency with this write.
175 void addUser(unsigned IID, ReadState *Use, int ReadAdvance);
177 // Use is a younger register write that is in a false dependency with this
178 // write. IID is the instruction identifier associated with this write.
179 void addUser(unsigned IID, WriteState *Use);
181 unsigned getNumUsers() const {
182 unsigned NumUsers = Users.size();
183 if (PartialWrite)
184 ++NumUsers;
185 return NumUsers;
188 bool clearsSuperRegisters() const { return ClearsSuperRegs; }
189 bool isWriteZero() const { return WritesZero; }
190 bool isEliminated() const { return IsEliminated; }
192 bool isReady() const {
193 if (DependentWrite)
194 return false;
195 unsigned CyclesLeft = getDependentWriteCyclesLeft();
196 return !CyclesLeft || CyclesLeft < getLatency();
199 bool isExecuted() const {
200 return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0;
203 void setDependentWrite(const WriteState *Other) { DependentWrite = Other; }
204 void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
205 void setWriteZero() { WritesZero = true; }
206 void setEliminated() {
207 assert(Users.empty() && "Write is in an inconsistent state.");
208 CyclesLeft = 0;
209 IsEliminated = true;
212 void setPRF(unsigned PRF) { PRFID = PRF; }
214 // On every cycle, update CyclesLeft and notify dependent users.
215 void cycleEvent();
216 void onInstructionIssued(unsigned IID);
218 #ifndef NDEBUG
219 void dump() const;
220 #endif
223 /// Tracks register operand latency in cycles.
225 /// A read may be dependent on more than one write. This occurs when some
226 /// writes only partially update the register associated to this read.
227 class ReadState {
228 const ReadDescriptor *RD;
229 // Physical register identified associated to this read.
230 MCPhysReg RegisterID;
231 // Physical register file that serves register RegisterID.
232 unsigned PRFID;
233 // Number of writes that contribute to the definition of RegisterID.
234 // In the absence of partial register updates, the number of DependentWrites
235 // cannot be more than one.
236 unsigned DependentWrites;
237 // Number of cycles left before RegisterID can be read. This value depends on
238 // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES.
239 // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of
240 // every dependent write is known.
241 int CyclesLeft;
242 // This field is updated on every writeStartEvent(). When the number of
243 // dependent writes (i.e. field DependentWrite) is zero, this value is
244 // propagated to field CyclesLeft.
245 unsigned TotalCycles;
246 // Longest register dependency.
247 CriticalDependency CRD;
248 // This field is set to true only if there are no dependent writes, and
249 // there are no `CyclesLeft' to wait.
250 bool IsReady;
251 // True if this is a read from a known zero register.
252 bool IsZero;
253 // True if this register read is from a dependency-breaking instruction.
254 bool IndependentFromDef;
256 public:
257 ReadState(const ReadDescriptor &Desc, MCPhysReg RegID)
258 : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0),
259 CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true),
260 IsZero(false), IndependentFromDef(false) {}
262 const ReadDescriptor &getDescriptor() const { return *RD; }
263 unsigned getSchedClass() const { return RD->SchedClassID; }
264 MCPhysReg getRegisterID() const { return RegisterID; }
265 unsigned getRegisterFileID() const { return PRFID; }
266 const CriticalDependency &getCriticalRegDep() const { return CRD; }
268 bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; }
269 bool isReady() const { return IsReady; }
270 bool isImplicitRead() const { return RD->isImplicitRead(); }
272 bool isIndependentFromDef() const { return IndependentFromDef; }
273 void setIndependentFromDef() { IndependentFromDef = true; }
275 void cycleEvent();
276 void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
277 void setDependentWrites(unsigned Writes) {
278 DependentWrites = Writes;
279 IsReady = !Writes;
282 bool isReadZero() const { return IsZero; }
283 void setReadZero() { IsZero = true; }
284 void setPRF(unsigned ID) { PRFID = ID; }
287 /// A sequence of cycles.
289 /// This class can be used as a building block to construct ranges of cycles.
290 class CycleSegment {
291 unsigned Begin; // Inclusive.
292 unsigned End; // Exclusive.
293 bool Reserved; // Resources associated to this segment must be reserved.
295 public:
296 CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false)
297 : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {}
299 bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; }
300 bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; }
301 bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; }
302 bool overlaps(const CycleSegment &CS) const {
303 return !startsAfter(CS) && !endsBefore(CS);
305 bool isExecuting() const { return Begin == 0 && End != 0; }
306 bool isExecuted() const { return End == 0; }
307 bool operator<(const CycleSegment &Other) const {
308 return Begin < Other.Begin;
310 CycleSegment &operator--(void) {
311 if (Begin)
312 Begin--;
313 if (End)
314 End--;
315 return *this;
318 bool isValid() const { return Begin <= End; }
319 unsigned size() const { return End - Begin; };
320 void subtract(unsigned Cycles) {
321 assert(End >= Cycles);
322 End -= Cycles;
325 unsigned begin() const { return Begin; }
326 unsigned end() const { return End; }
327 void setEnd(unsigned NewEnd) { End = NewEnd; }
328 bool isReserved() const { return Reserved; }
329 void setReserved() { Reserved = true; }
332 /// Helper used by class InstrDesc to describe how hardware resources
333 /// are used.
335 /// This class describes how many resource units of a specific resource kind
336 /// (and how many cycles) are "used" by an instruction.
337 struct ResourceUsage {
338 CycleSegment CS;
339 unsigned NumUnits;
340 ResourceUsage(CycleSegment Cycles, unsigned Units = 1)
341 : CS(Cycles), NumUnits(Units) {}
342 unsigned size() const { return CS.size(); }
343 bool isReserved() const { return CS.isReserved(); }
344 void setReserved() { CS.setReserved(); }
347 /// An instruction descriptor
348 struct InstrDesc {
349 SmallVector<WriteDescriptor, 4> Writes; // Implicit writes are at the end.
350 SmallVector<ReadDescriptor, 4> Reads; // Implicit reads are at the end.
352 // For every resource used by an instruction of this kind, this vector
353 // reports the number of "consumed cycles".
354 SmallVector<std::pair<uint64_t, ResourceUsage>, 4> Resources;
356 // A bitmask of used hardware buffers.
357 uint64_t UsedBuffers;
359 // A bitmask of used processor resource units.
360 uint64_t UsedProcResUnits;
362 // A bitmask of used processor resource groups.
363 uint64_t UsedProcResGroups;
365 unsigned MaxLatency;
366 // Number of MicroOps for this instruction.
367 unsigned NumMicroOps;
368 // SchedClassID used to construct this InstrDesc.
369 // This information is currently used by views to do fast queries on the
370 // subtarget when computing the reciprocal throughput.
371 unsigned SchedClassID;
373 bool MayLoad;
374 bool MayStore;
375 bool HasSideEffects;
376 bool BeginGroup;
377 bool EndGroup;
379 // True if all buffered resources are in-order, and there is at least one
380 // buffer which is a dispatch hazard (BufferSize = 0).
381 bool MustIssueImmediately;
383 // A zero latency instruction doesn't consume any scheduler resources.
384 bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
386 InstrDesc() = default;
387 InstrDesc(const InstrDesc &Other) = delete;
388 InstrDesc &operator=(const InstrDesc &Other) = delete;
391 /// Base class for instructions consumed by the simulation pipeline.
393 /// This class tracks data dependencies as well as generic properties
394 /// of the instruction.
395 class InstructionBase {
396 const InstrDesc &Desc;
398 // This field is set for instructions that are candidates for move
399 // elimination. For more information about move elimination, see the
400 // definition of RegisterMappingTracker in RegisterFile.h
401 bool IsOptimizableMove;
403 // Output dependencies.
404 // One entry per each implicit and explicit register definition.
405 SmallVector<WriteState, 4> Defs;
407 // Input dependencies.
408 // One entry per each implicit and explicit register use.
409 SmallVector<ReadState, 4> Uses;
411 public:
412 InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {}
414 SmallVectorImpl<WriteState> &getDefs() { return Defs; }
415 const ArrayRef<WriteState> getDefs() const { return Defs; }
416 SmallVectorImpl<ReadState> &getUses() { return Uses; }
417 const ArrayRef<ReadState> getUses() const { return Uses; }
418 const InstrDesc &getDesc() const { return Desc; }
420 unsigned getLatency() const { return Desc.MaxLatency; }
421 unsigned getNumMicroOps() const { return Desc.NumMicroOps; }
423 bool hasDependentUsers() const {
424 return any_of(Defs,
425 [](const WriteState &Def) { return Def.getNumUsers() > 0; });
428 unsigned getNumUsers() const {
429 unsigned NumUsers = 0;
430 for (const WriteState &Def : Defs)
431 NumUsers += Def.getNumUsers();
432 return NumUsers;
435 // Returns true if this instruction is a candidate for move elimination.
436 bool isOptimizableMove() const { return IsOptimizableMove; }
437 void setOptimizableMove() { IsOptimizableMove = true; }
438 bool isMemOp() const { return Desc.MayLoad || Desc.MayStore; }
441 /// An instruction propagated through the simulated instruction pipeline.
443 /// This class is used to monitor changes to the internal state of instructions
444 /// that are sent to the various components of the simulated hardware pipeline.
445 class Instruction : public InstructionBase {
446 enum InstrStage {
447 IS_INVALID, // Instruction in an invalid state.
448 IS_DISPATCHED, // Instruction dispatched but operands are not ready.
449 IS_PENDING, // Instruction is not ready, but operand latency is known.
450 IS_READY, // Instruction dispatched and operands ready.
451 IS_EXECUTING, // Instruction issued.
452 IS_EXECUTED, // Instruction executed. Values are written back.
453 IS_RETIRED // Instruction retired.
456 // The current instruction stage.
457 enum InstrStage Stage;
459 // This value defaults to the instruction latency. This instruction is
460 // considered executed when field CyclesLeft goes to zero.
461 int CyclesLeft;
463 // Retire Unit token ID for this instruction.
464 unsigned RCUTokenID;
466 // LS token ID for this instruction.
467 // This field is set to the invalid null token if this is not a memory
468 // operation.
469 unsigned LSUTokenID;
471 // A resource mask which identifies buffered resources consumed by this
472 // instruction at dispatch stage. In the absence of macro-fusion, this value
473 // should always match the value of field `UsedBuffers` from the instruction
474 // descriptor (see field InstrBase::Desc).
475 uint64_t UsedBuffers;
477 // Critical register dependency.
478 CriticalDependency CriticalRegDep;
480 // Critical memory dependency.
481 CriticalDependency CriticalMemDep;
483 // A bitmask of busy processor resource units.
484 // This field is set to zero only if execution is not delayed during this
485 // cycle because of unavailable pipeline resources.
486 uint64_t CriticalResourceMask;
488 // True if this instruction has been optimized at register renaming stage.
489 bool IsEliminated;
491 public:
492 Instruction(const InstrDesc &D)
493 : InstructionBase(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES),
494 RCUTokenID(0), LSUTokenID(0), UsedBuffers(D.UsedBuffers),
495 CriticalRegDep(), CriticalMemDep(), CriticalResourceMask(0),
496 IsEliminated(false) {}
498 unsigned getRCUTokenID() const { return RCUTokenID; }
499 unsigned getLSUTokenID() const { return LSUTokenID; }
500 void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; }
502 uint64_t getUsedBuffers() const { return UsedBuffers; }
503 void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; }
504 void clearUsedBuffers() { UsedBuffers = 0ULL; }
506 int getCyclesLeft() const { return CyclesLeft; }
508 // Transition to the dispatch stage, and assign a RCUToken to this
509 // instruction. The RCUToken is used to track the completion of every
510 // register write performed by this instruction.
511 void dispatch(unsigned RCUTokenID);
513 // Instruction issued. Transition to the IS_EXECUTING state, and update
514 // all the register definitions.
515 void execute(unsigned IID);
517 // Force a transition from the IS_DISPATCHED state to the IS_READY or
518 // IS_PENDING state. State transitions normally occur either at the beginning
519 // of a new cycle (see method cycleEvent()), or as a result of another issue
520 // event. This method is called every time the instruction might have changed
521 // in state. It internally delegates to method updateDispatched() and
522 // updateWaiting().
523 void update();
524 bool updateDispatched();
525 bool updatePending();
527 bool isDispatched() const { return Stage == IS_DISPATCHED; }
528 bool isPending() const { return Stage == IS_PENDING; }
529 bool isReady() const { return Stage == IS_READY; }
530 bool isExecuting() const { return Stage == IS_EXECUTING; }
531 bool isExecuted() const { return Stage == IS_EXECUTED; }
532 bool isRetired() const { return Stage == IS_RETIRED; }
533 bool isEliminated() const { return IsEliminated; }
535 // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
536 void forceExecuted();
537 void setEliminated() { IsEliminated = true; }
539 void retire() {
540 assert(isExecuted() && "Instruction is in an invalid state!");
541 Stage = IS_RETIRED;
544 const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; }
545 const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; }
546 const CriticalDependency &computeCriticalRegDep();
547 void setCriticalMemDep(const CriticalDependency &MemDep) {
548 CriticalMemDep = MemDep;
551 uint64_t getCriticalResourceMask() const { return CriticalResourceMask; }
552 void setCriticalResourceMask(uint64_t ResourceMask) {
553 CriticalResourceMask = ResourceMask;
556 void cycleEvent();
559 /// An InstRef contains both a SourceMgr index and Instruction pair. The index
560 /// is used as a unique identifier for the instruction. MCA will make use of
561 /// this index as a key throughout MCA.
562 class InstRef {
563 std::pair<unsigned, Instruction *> Data;
565 public:
566 InstRef() : Data(std::make_pair(0, nullptr)) {}
567 InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {}
569 bool operator==(const InstRef &Other) const { return Data == Other.Data; }
570 bool operator!=(const InstRef &Other) const { return Data != Other.Data; }
571 bool operator<(const InstRef &Other) const {
572 return Data.first < Other.Data.first;
575 unsigned getSourceIndex() const { return Data.first; }
576 Instruction *getInstruction() { return Data.second; }
577 const Instruction *getInstruction() const { return Data.second; }
579 /// Returns true if this references a valid instruction.
580 explicit operator bool() const { return Data.second != nullptr; }
582 /// Invalidate this reference.
583 void invalidate() { Data.second = nullptr; }
585 #ifndef NDEBUG
586 void print(raw_ostream &OS) const { OS << getSourceIndex(); }
587 #endif
590 #ifndef NDEBUG
591 inline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) {
592 IR.print(OS);
593 return OS;
595 #endif
597 /// A reference to a register write.
599 /// This class is mainly used by the register file to describe register
600 /// mappings. It correlates a register write to the source index of the
601 /// defining instruction.
602 class WriteRef {
603 std::pair<unsigned, WriteState *> Data;
604 static const unsigned INVALID_IID;
606 public:
607 WriteRef() : Data(INVALID_IID, nullptr) {}
608 WriteRef(unsigned SourceIndex, WriteState *WS) : Data(SourceIndex, WS) {}
610 unsigned getSourceIndex() const { return Data.first; }
611 const WriteState *getWriteState() const { return Data.second; }
612 WriteState *getWriteState() { return Data.second; }
613 void invalidate() { Data.second = nullptr; }
614 bool isWriteZero() const {
615 assert(isValid() && "Invalid null WriteState found!");
616 return getWriteState()->isWriteZero();
619 /// Returns true if this register write has been executed, and the new
620 /// register value is therefore available to users.
621 bool isAvailable() const {
622 if (getSourceIndex() == INVALID_IID)
623 return false;
624 const WriteState *WS = getWriteState();
625 return !WS || WS->isExecuted();
628 bool isValid() const { return Data.second && Data.first != INVALID_IID; }
629 bool operator==(const WriteRef &Other) const { return Data == Other.Data; }
631 #ifndef NDEBUG
632 void dump() const;
633 #endif
636 } // namespace mca
637 } // namespace llvm
639 #endif // LLVM_MCA_INSTRUCTION_H