LLVM 22.0.0git
Instruction.h
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_MCA_INSTRUCTION_H
16#define LLVM_MCA_INSTRUCTION_H
17
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/STLExtras.h"
21#include "llvm/MC/MCRegister.h" // definition of MCPhysReg.
24
25#ifndef NDEBUG
27#endif
28
29namespace llvm {
30
31namespace mca {
32
33constexpr int UNKNOWN_CYCLES = -512;
34
35/// A representation of an mca::Instruction operand
36/// for use in mca::CustomBehaviour.
38 // This class is mostly copied from MCOperand within
39 // MCInst.h except that we don't keep track of
40 // expressions or sub-instructions.
41 enum MCAOperandType : unsigned char {
42 kInvalid, ///< Uninitialized, Relocatable immediate, or Sub-instruction.
43 kRegister, ///< Register operand.
44 kImmediate, ///< Immediate operand.
45 kSFPImmediate, ///< Single-floating-point immediate operand.
46 kDFPImmediate, ///< Double-Floating-point immediate operand.
47 };
48 MCAOperandType Kind;
49
50 union {
51 unsigned RegVal;
52 int64_t ImmVal;
55 };
56
57 // We only store specific operands for specific instructions
58 // so an instruction's operand 3 may be stored within the list
59 // of MCAOperand as element 0. This Index attribute keeps track
60 // of the original index (3 for this example).
61 unsigned Index;
62
63public:
64 MCAOperand() : Kind(kInvalid), FPImmVal(), Index() {}
65
66 bool isValid() const { return Kind != kInvalid; }
67 bool isReg() const { return Kind == kRegister; }
68 bool isImm() const { return Kind == kImmediate; }
69 bool isSFPImm() const { return Kind == kSFPImmediate; }
70 bool isDFPImm() const { return Kind == kDFPImmediate; }
71
72 /// Returns the register number.
73 unsigned getReg() const {
74 assert(isReg() && "This is not a register operand!");
75 return RegVal;
76 }
77
78 int64_t getImm() const {
79 assert(isImm() && "This is not an immediate");
80 return ImmVal;
81 }
82
84 assert(isSFPImm() && "This is not an SFP immediate");
85 return SFPImmVal;
86 }
87
89 assert(isDFPImm() && "This is not an FP immediate");
90 return FPImmVal;
91 }
92
93 void setIndex(const unsigned Idx) { Index = Idx; }
94
95 unsigned getIndex() const { return Index; }
96
97 static MCAOperand createReg(unsigned Reg) {
99 Op.Kind = kRegister;
100 Op.RegVal = Reg;
101 return Op;
102 }
103
104 static MCAOperand createImm(int64_t Val) {
106 Op.Kind = kImmediate;
107 Op.ImmVal = Val;
108 return Op;
109 }
110
113 Op.Kind = kSFPImmediate;
114 Op.SFPImmVal = Val;
115 return Op;
116 }
117
120 Op.Kind = kDFPImmediate;
121 Op.FPImmVal = Val;
122 return Op;
123 }
124
127 Op.Kind = kInvalid;
128 Op.FPImmVal = 0;
129 return Op;
130 }
131};
132
133/// A register write descriptor.
135 // Operand index. The index is negative for implicit writes only.
136 // For implicit writes, the actual operand index is computed performing
137 // a bitwise not of the OpIndex.
139 // Write latency. Number of cycles before write-back stage.
140 unsigned Latency;
141 // This field is set to a value different than zero only if this
142 // is an implicit definition.
144 // Instruction itineraries would set this field to the SchedClass ID.
145 // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry
146 // element associated to this write.
147 // When computing read latencies, this value is matched against the
148 // "ReadAdvance" information. The hardware backend may implement
149 // dedicated forwarding paths to quickly propagate write results to dependent
150 // instructions waiting in the reservation station (effectively bypassing the
151 // write-back stage).
153 // True only if this is a write obtained from an optional definition.
154 // Optional definitions are allowed to reference regID zero (i.e. "no
155 // register").
157
158 bool isImplicitWrite() const { return OpIndex < 0; };
159};
160
161/// A register read descriptor.
163 // A MCOperand index. This is used by the Dispatch logic to identify register
164 // reads. Implicit reads have negative indices. The actual operand index of an
165 // implicit read is the bitwise not of field OpIndex.
167 // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit
168 // uses always come first in the sequence of uses.
169 unsigned UseIndex;
170 // This field is only set if this is an implicit read.
172 // Scheduling Class Index. It is used to query the scheduling model for the
173 // MCSchedClassDesc object.
174 unsigned SchedClassID;
175
176 bool isImplicitRead() const { return OpIndex < 0; };
177};
178
179class ReadState;
180
181/// A critical data dependency descriptor.
182///
183/// Field RegID is set to the invalid register for memory dependencies.
185 unsigned IID;
187 unsigned Cycles;
188};
189
190/// Tracks uses of a register definition (e.g. register write).
191///
192/// Each implicit/explicit register write is associated with an instance of
193/// this class. A WriteState object tracks the dependent users of a
194/// register write. It also tracks how many cycles are left before the write
195/// back stage.
197 const WriteDescriptor *WD;
198 // On instruction issue, this field is set equal to the write latency.
199 // Before instruction issue, this field defaults to -512, a special
200 // value that represents an "unknown" number of cycles.
201 int CyclesLeft;
202
203 // Actual register defined by this write. This field is only used
204 // to speedup queries on the register file.
205 // For implicit writes, this field always matches the value of
206 // field RegisterID from WD.
207 MCPhysReg RegisterID;
208
209 // Physical register file that serves register RegisterID.
210 unsigned PRFID;
211
212 // True if this write implicitly clears the upper portion of RegisterID's
213 // super-registers.
214 bool ClearsSuperRegs;
215
216 // True if this write is from a dependency breaking zero-idiom instruction.
217 bool WritesZero;
218
219 // True if this write has been eliminated at register renaming stage.
220 // Example: a register move doesn't consume scheduler/pipleline resources if
221 // it is eliminated at register renaming stage. It still consumes
222 // decode bandwidth, and ROB entries.
223 bool IsEliminated;
224
225 // This field is set if this is a partial register write, and it has a false
226 // dependency on any previous write of the same register (or a portion of it).
227 // DependentWrite must be able to complete before this write completes, so
228 // that we don't break the WAW, and the two writes can be merged together.
229 const WriteState *DependentWrite;
230
231 // A partial write that is in a false dependency with this write.
232 WriteState *PartialWrite;
233 unsigned DependentWriteCyclesLeft;
234
235 // Critical register dependency for this write.
237
238 // A list of dependent reads. Users is a set of dependent
239 // reads. A dependent read is added to the set only if CyclesLeft
240 // is "unknown". As soon as CyclesLeft is 'known', each user in the set
241 // gets notified with the actual CyclesLeft.
242
243 // The 'second' element of a pair is a "ReadAdvance" number of cycles.
245
246public:
248 bool clearsSuperRegs = false, bool writesZero = false)
249 : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0),
250 ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero),
251 IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr),
252 DependentWriteCyclesLeft(0), CRD() {}
253
254 WriteState(const WriteState &Other) = default;
256
257 int getCyclesLeft() const { return CyclesLeft; }
258 unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; }
259 MCPhysReg getRegisterID() const { return RegisterID; }
260 void setRegisterID(const MCPhysReg RegID) { RegisterID = RegID; }
261 unsigned getRegisterFileID() const { return PRFID; }
262 unsigned getLatency() const { return WD->Latency; }
264 return DependentWriteCyclesLeft;
265 }
266 const WriteState *getDependentWrite() const { return DependentWrite; }
267 const CriticalDependency &getCriticalRegDep() const { return CRD; }
268
269 // This method adds Use to the set of data dependent reads. IID is the
270 // instruction identifier associated with this write. ReadAdvance is the
271 // number of cycles to subtract from the latency of this data dependency.
272 // Use is in a RAW dependency with this write.
273 LLVM_ABI void addUser(unsigned IID, ReadState *Use, int ReadAdvance);
274
275 // Use is a younger register write that is in a false dependency with this
276 // write. IID is the instruction identifier associated with this write.
277 LLVM_ABI void addUser(unsigned IID, WriteState *Use);
278
279 unsigned getNumUsers() const {
280 unsigned NumUsers = Users.size();
281 if (PartialWrite)
282 ++NumUsers;
283 return NumUsers;
284 }
285
286 bool clearsSuperRegisters() const { return ClearsSuperRegs; }
287 bool isWriteZero() const { return WritesZero; }
288 bool isEliminated() const { return IsEliminated; }
289
290 bool isReady() const {
291 if (DependentWrite)
292 return false;
293 unsigned CyclesLeft = getDependentWriteCyclesLeft();
294 return !CyclesLeft || CyclesLeft < getLatency();
295 }
296
297 bool isExecuted() const {
298 return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0;
299 }
300
301 void setDependentWrite(const WriteState *Other) { DependentWrite = Other; }
302 LLVM_ABI void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
303 void setWriteZero() { WritesZero = true; }
305 assert(Users.empty() && "Write is in an inconsistent state.");
306 CyclesLeft = 0;
307 IsEliminated = true;
308 }
309
310 void setPRF(unsigned PRF) { PRFID = PRF; }
311
312 // On every cycle, update CyclesLeft and notify dependent users.
313 LLVM_ABI void cycleEvent();
314 LLVM_ABI void onInstructionIssued(unsigned IID);
315
316#ifndef NDEBUG
317 void dump() const;
318#endif
319};
320
321/// Tracks register operand latency in cycles.
322///
323/// A read may be dependent on more than one write. This occurs when some
324/// writes only partially update the register associated to this read.
326 const ReadDescriptor *RD;
327 // Physical register identified associated to this read.
328 MCPhysReg RegisterID;
329 // Physical register file that serves register RegisterID.
330 unsigned PRFID;
331 // Number of writes that contribute to the definition of RegisterID.
332 // In the absence of partial register updates, the number of DependentWrites
333 // cannot be more than one.
334 unsigned DependentWrites;
335 // Number of cycles left before RegisterID can be read. This value depends on
336 // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES.
337 // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of
338 // every dependent write is known.
339 int CyclesLeft;
340 // This field is updated on every writeStartEvent(). When the number of
341 // dependent writes (i.e. field DependentWrite) is zero, this value is
342 // propagated to field CyclesLeft.
343 unsigned TotalCycles;
344 // Longest register dependency.
346 // This field is set to true only if there are no dependent writes, and
347 // there are no `CyclesLeft' to wait.
348 bool IsReady;
349 // True if this is a read from a known zero register.
350 bool IsZero;
351 // True if this register read is from a dependency-breaking instruction.
352 bool IndependentFromDef;
353
354public:
356 : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0),
357 CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true),
358 IsZero(false), IndependentFromDef(false) {}
359
360 const ReadDescriptor &getDescriptor() const { return *RD; }
361 unsigned getSchedClass() const { return RD->SchedClassID; }
362 MCPhysReg getRegisterID() const { return RegisterID; }
363 unsigned getRegisterFileID() const { return PRFID; }
364 const CriticalDependency &getCriticalRegDep() const { return CRD; }
365
366 bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; }
367 bool isReady() const { return IsReady; }
368 bool isImplicitRead() const { return RD->isImplicitRead(); }
369
370 bool isIndependentFromDef() const { return IndependentFromDef; }
371 void setIndependentFromDef() { IndependentFromDef = true; }
372
373 LLVM_ABI void cycleEvent();
374 LLVM_ABI void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
375 void setDependentWrites(unsigned Writes) {
376 DependentWrites = Writes;
377 IsReady = !Writes;
378 }
379
380 bool isReadZero() const { return IsZero; }
381 void setReadZero() { IsZero = true; }
382 void setPRF(unsigned ID) { PRFID = ID; }
383
384#ifndef NDEBUG
385 void dump() const;
386#endif
387};
388
389/// A sequence of cycles.
390///
391/// This class can be used as a building block to construct ranges of cycles.
393 unsigned Begin; // Inclusive.
394 unsigned End; // Exclusive.
395 bool Reserved; // Resources associated to this segment must be reserved.
396
397public:
398 CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false)
399 : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {}
400
401 bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; }
402 bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; }
403 bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; }
404 bool overlaps(const CycleSegment &CS) const {
405 return !startsAfter(CS) && !endsBefore(CS);
406 }
407 bool isExecuting() const { return Begin == 0 && End != 0; }
408 bool isExecuted() const { return End == 0; }
409 bool operator<(const CycleSegment &Other) const {
410 return Begin < Other.Begin;
411 }
413 if (Begin)
414 Begin--;
415 if (End)
416 End--;
417 return *this;
418 }
419
420 bool isValid() const { return Begin <= End; }
421 unsigned size() const { return End - Begin; };
422 void subtract(unsigned Cycles) {
423 assert(End >= Cycles);
424 End -= Cycles;
425 }
426
427 unsigned begin() const { return Begin; }
428 unsigned end() const { return End; }
429 void setEnd(unsigned NewEnd) { End = NewEnd; }
430 bool isReserved() const { return Reserved; }
431 void setReserved() { Reserved = true; }
432};
433
434/// Helper used by class InstrDesc to describe how hardware resources
435/// are used.
436///
437/// This class describes how many resource units of a specific resource kind
438/// (and how many cycles) are "used" by an instruction.
441 unsigned NumUnits;
442 ResourceUsage(CycleSegment Cycles, unsigned Units = 1)
443 : CS(Cycles), NumUnits(Units) {}
444 unsigned size() const { return CS.size(); }
445 bool isReserved() const { return CS.isReserved(); }
446 void setReserved() { CS.setReserved(); }
447};
448
449/// An instruction descriptor
450struct InstrDesc {
451 SmallVector<WriteDescriptor, 2> Writes; // Implicit writes are at the end.
452 SmallVector<ReadDescriptor, 4> Reads; // Implicit reads are at the end.
453
454 // For every resource used by an instruction of this kind, this vector
455 // reports the number of "consumed cycles".
457
458 // A bitmask of used hardware buffers.
460
461 // A bitmask of used processor resource units.
463
464 // A bitmask of used processor resource groups.
466
467 unsigned MaxLatency;
468 // Number of MicroOps for this instruction.
469 unsigned NumMicroOps;
470 // SchedClassID used to construct this InstrDesc.
471 // This information is currently used by views to do fast queries on the
472 // subtarget when computing the reciprocal throughput.
473 unsigned SchedClassID;
474
475 // True if all buffered resources are in-order, and there is at least one
476 // buffer which is a dispatch hazard (BufferSize = 0).
478
479 // True if the corresponding mca::Instruction can be recycled. Currently only
480 // instructions that are neither variadic nor have any variant can be
481 // recycled.
482 unsigned IsRecyclable : 1;
483
484 // True if some of the consumed group resources are partially overlapping.
486
487 // A zero latency instruction doesn't consume any scheduler resources.
488 bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
489
490 InstrDesc() = default;
491 InstrDesc(const InstrDesc &Other) = delete;
493};
494
495/// Base class for instructions consumed by the simulation pipeline.
496///
497/// This class tracks data dependencies as well as generic properties
498/// of the instruction.
500 const InstrDesc &Desc;
501
502 // This field is set for instructions that are candidates for move
503 // elimination. For more information about move elimination, see the
504 // definition of RegisterMappingTracker in RegisterFile.h
505 bool IsOptimizableMove;
506
507 // Output dependencies.
508 // One entry per each implicit and explicit register definition.
510
511 // Input dependencies.
512 // One entry per each implicit and explicit register use.
514
515 // List of operands which can be used by mca::CustomBehaviour
516 std::vector<MCAOperand> Operands;
517
518 // Instruction opcode which can be used by mca::CustomBehaviour
519 unsigned Opcode;
520
521 // Flags used by the LSUnit.
522 bool IsALoadBarrier : 1;
523 bool IsAStoreBarrier : 1;
524 // Flags copied from the InstrDesc and potentially modified by
525 // CustomBehaviour or (more likely) InstrPostProcess.
526 bool MayLoad : 1;
527 bool MayStore : 1;
528 bool HasSideEffects : 1;
529 bool BeginGroup : 1;
530 bool EndGroup : 1;
531 bool RetireOOO : 1;
532
533public:
534 InstructionBase(const InstrDesc &D, const unsigned Opcode)
535 : Desc(D), IsOptimizableMove(false), Operands(0), Opcode(Opcode),
536 IsALoadBarrier(false), IsAStoreBarrier(false) {}
537
539 ArrayRef<WriteState> getDefs() const { return Defs; }
541 ArrayRef<ReadState> getUses() const { return Uses; }
542 const InstrDesc &getDesc() const { return Desc; }
543
544 unsigned getLatency() const { return Desc.MaxLatency; }
545 unsigned getNumMicroOps() const { return Desc.NumMicroOps; }
546 unsigned getOpcode() const { return Opcode; }
547 bool isALoadBarrier() const { return IsALoadBarrier; }
548 bool isAStoreBarrier() const { return IsAStoreBarrier; }
549 void setLoadBarrier(bool IsBarrier) { IsALoadBarrier = IsBarrier; }
550 void setStoreBarrier(bool IsBarrier) { IsAStoreBarrier = IsBarrier; }
551
552 /// Return the MCAOperand which corresponds to index Idx within the original
553 /// MCInst.
554 const MCAOperand *getOperand(const unsigned Idx) const {
555 auto It = llvm::find_if(Operands, [&Idx](const MCAOperand &Op) {
556 return Op.getIndex() == Idx;
557 });
558 if (It == Operands.end())
559 return nullptr;
560 return &(*It);
561 }
562 unsigned getNumOperands() const { return Operands.size(); }
563 void addOperand(const MCAOperand Op) { Operands.push_back(Op); }
564
565 bool hasDependentUsers() const {
566 return any_of(Defs,
567 [](const WriteState &Def) { return Def.getNumUsers() > 0; });
568 }
569
570 unsigned getNumUsers() const {
571 unsigned NumUsers = 0;
572 for (const WriteState &Def : Defs)
573 NumUsers += Def.getNumUsers();
574 return NumUsers;
575 }
576
577 // Returns true if this instruction is a candidate for move elimination.
578 bool isOptimizableMove() const { return IsOptimizableMove; }
579 void setOptimizableMove() { IsOptimizableMove = true; }
580 void clearOptimizableMove() { IsOptimizableMove = false; }
581 bool isMemOp() const { return MayLoad || MayStore; }
582
583 // Getters and setters for general instruction flags.
584 void setMayLoad(bool newVal) { MayLoad = newVal; }
585 void setMayStore(bool newVal) { MayStore = newVal; }
586 void setHasSideEffects(bool newVal) { HasSideEffects = newVal; }
587 void setBeginGroup(bool newVal) { BeginGroup = newVal; }
588 void setEndGroup(bool newVal) { EndGroup = newVal; }
589 void setRetireOOO(bool newVal) { RetireOOO = newVal; }
590
591 bool getMayLoad() const { return MayLoad; }
592 bool getMayStore() const { return MayStore; }
593 bool getHasSideEffects() const { return HasSideEffects; }
594 bool getBeginGroup() const { return BeginGroup; }
595 bool getEndGroup() const { return EndGroup; }
596 bool getRetireOOO() const { return RetireOOO; }
597};
598
599/// An instruction propagated through the simulated instruction pipeline.
600///
601/// This class is used to monitor changes to the internal state of instructions
602/// that are sent to the various components of the simulated hardware pipeline.
604 enum InstrStage {
605 IS_INVALID, // Instruction in an invalid state.
606 IS_DISPATCHED, // Instruction dispatched but operands are not ready.
607 IS_PENDING, // Instruction is not ready, but operand latency is known.
608 IS_READY, // Instruction dispatched and operands ready.
609 IS_EXECUTING, // Instruction issued.
610 IS_EXECUTED, // Instruction executed. Values are written back.
611 IS_RETIRED // Instruction retired.
612 };
613
614 // The current instruction stage.
615 enum InstrStage Stage;
616
617 // This value defaults to the instruction latency. This instruction is
618 // considered executed when field CyclesLeft goes to zero.
619 int CyclesLeft;
620
621 // Retire Unit token ID for this instruction.
622 unsigned RCUTokenID;
623
624 // LS token ID for this instruction.
625 // This field is set to the invalid null token if this is not a memory
626 // operation.
627 unsigned LSUTokenID;
628
629 // A resource mask which identifies buffered resources consumed by this
630 // instruction at dispatch stage. In the absence of macro-fusion, this value
631 // should always match the value of field `UsedBuffers` from the instruction
632 // descriptor (see field InstrBase::Desc).
633 uint64_t UsedBuffers;
634
635 // Critical register dependency.
636 CriticalDependency CriticalRegDep;
637
638 // Critical memory dependency.
639 CriticalDependency CriticalMemDep;
640
641 // A bitmask of busy processor resource units.
642 // This field is set to zero only if execution is not delayed during this
643 // cycle because of unavailable pipeline resources.
644 uint64_t CriticalResourceMask;
645
646 // True if this instruction has been optimized at register renaming stage.
647 bool IsEliminated;
648
649public:
650 Instruction(const InstrDesc &D, const unsigned Opcode)
651 : InstructionBase(D, Opcode), Stage(IS_INVALID),
652 CyclesLeft(UNKNOWN_CYCLES), RCUTokenID(0), LSUTokenID(0),
653 UsedBuffers(D.UsedBuffers), CriticalRegDep(), CriticalMemDep(),
654 CriticalResourceMask(0), IsEliminated(false) {}
655
656 LLVM_ABI void reset();
657
658 unsigned getRCUTokenID() const { return RCUTokenID; }
659 unsigned getLSUTokenID() const { return LSUTokenID; }
660 void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; }
661
662 uint64_t getUsedBuffers() const { return UsedBuffers; }
663 void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; }
664 void clearUsedBuffers() { UsedBuffers = 0ULL; }
665
666 int getCyclesLeft() const { return CyclesLeft; }
667
668 // Transition to the dispatch stage, and assign a RCUToken to this
669 // instruction. The RCUToken is used to track the completion of every
670 // register write performed by this instruction.
671 LLVM_ABI void dispatch(unsigned RCUTokenID);
672
673 // Instruction issued. Transition to the IS_EXECUTING state, and update
674 // all the register definitions.
675 LLVM_ABI void execute(unsigned IID);
676
677 // Force a transition from the IS_DISPATCHED state to the IS_READY or
678 // IS_PENDING state. State transitions normally occur either at the beginning
679 // of a new cycle (see method cycleEvent()), or as a result of another issue
680 // event. This method is called every time the instruction might have changed
681 // in state. It internally delegates to method updateDispatched() and
682 // updateWaiting().
683 LLVM_ABI void update();
685 LLVM_ABI bool updatePending();
686
687 bool isInvalid() const { return Stage == IS_INVALID; }
688 bool isDispatched() const { return Stage == IS_DISPATCHED; }
689 bool isPending() const { return Stage == IS_PENDING; }
690 bool isReady() const { return Stage == IS_READY; }
691 bool isExecuting() const { return Stage == IS_EXECUTING; }
692 bool isExecuted() const { return Stage == IS_EXECUTED; }
693 bool isRetired() const { return Stage == IS_RETIRED; }
694 bool isEliminated() const { return IsEliminated; }
695
696 // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
697 LLVM_ABI void forceExecuted();
698 void setEliminated() { IsEliminated = true; }
699
700 void retire() {
701 assert(isExecuted() && "Instruction is in an invalid state!");
702 Stage = IS_RETIRED;
703 }
704
705 const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; }
706 const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; }
709 CriticalMemDep = MemDep;
710 }
711
712 uint64_t getCriticalResourceMask() const { return CriticalResourceMask; }
714 CriticalResourceMask = ResourceMask;
715 }
716
717 LLVM_ABI void cycleEvent();
718};
719
720/// An InstRef contains both a SourceMgr index and Instruction pair. The index
721/// is used as a unique identifier for the instruction. MCA will make use of
722/// this index as a key throughout MCA.
723class InstRef {
724 std::pair<unsigned, Instruction *> Data;
725
726public:
727 InstRef() : Data(std::make_pair(0, nullptr)) {}
728 InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {}
729
730 bool operator==(const InstRef &Other) const { return Data == Other.Data; }
731 bool operator!=(const InstRef &Other) const { return Data != Other.Data; }
732 bool operator<(const InstRef &Other) const {
733 return Data.first < Other.Data.first;
734 }
735
736 unsigned getSourceIndex() const { return Data.first; }
737 Instruction *getInstruction() { return Data.second; }
738 const Instruction *getInstruction() const { return Data.second; }
739
740 /// Returns true if this references a valid instruction.
741 explicit operator bool() const { return Data.second != nullptr; }
742
743 /// Invalidate this reference.
744 void invalidate() { Data.second = nullptr; }
745
746#ifndef NDEBUG
747 void print(raw_ostream &OS) const { OS << getSourceIndex(); }
748#endif
749};
750
751#ifndef NDEBUG
753 IR.print(OS);
754 return OS;
755}
756#endif
757
758} // namespace mca
759} // namespace llvm
760
761#endif // LLVM_MCA_INSTRUCTION_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_ABI
Definition Compiler.h:213
Legalize the Machine IR a function s Machine IR
Definition Legalizer.cpp:80
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
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.
Definition Use.h:35
A sequence of cycles.
CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved=false)
bool operator<(const CycleSegment &Other) const
bool startsAfter(const CycleSegment &CS) const
bool contains(unsigned Cycle) const
void setEnd(unsigned NewEnd)
void subtract(unsigned Cycles)
CycleSegment & operator--()
unsigned end() const
unsigned size() const
bool endsBefore(const CycleSegment &CS) const
unsigned begin() const
bool overlaps(const CycleSegment &CS) const
An InstRef contains both a SourceMgr index and Instruction pair.
void invalidate()
Invalidate this reference.
bool operator<(const InstRef &Other) const
const Instruction * getInstruction() const
InstRef(unsigned Index, Instruction *I)
Instruction * getInstruction()
unsigned getSourceIndex() const
bool operator!=(const InstRef &Other) const
bool operator==(const InstRef &Other) const
void print(raw_ostream &OS) const
void setEndGroup(bool newVal)
unsigned getOpcode() const
void setRetireOOO(bool newVal)
ArrayRef< WriteState > getDefs() const
void addOperand(const MCAOperand Op)
unsigned getNumMicroOps() const
const InstrDesc & getDesc() const
const MCAOperand * getOperand(const unsigned Idx) const
Return the MCAOperand which corresponds to index Idx within the original MCInst.
SmallVectorImpl< WriteState > & getDefs()
unsigned getLatency() const
void setBeginGroup(bool newVal)
SmallVectorImpl< ReadState > & getUses()
void setLoadBarrier(bool IsBarrier)
unsigned getNumOperands() const
void setStoreBarrier(bool IsBarrier)
void setHasSideEffects(bool newVal)
void setMayStore(bool newVal)
ArrayRef< ReadState > getUses() const
InstructionBase(const InstrDesc &D, const unsigned Opcode)
unsigned getNumUsers() const
void setMayLoad(bool newVal)
An instruction propagated through the simulated instruction pipeline.
LLVM_ABI void cycleEvent()
bool isDispatched() const
bool isEliminated() const
Instruction(const InstrDesc &D, const unsigned Opcode)
bool isExecuted() const
uint64_t getCriticalResourceMask() const
unsigned getRCUTokenID() const
LLVM_ABI bool updateDispatched()
const CriticalDependency & getCriticalMemDep() const
const CriticalDependency & getCriticalRegDep() const
bool isExecuting() const
LLVM_ABI void forceExecuted()
int getCyclesLeft() const
void setCriticalResourceMask(uint64_t ResourceMask)
LLVM_ABI const CriticalDependency & computeCriticalRegDep()
LLVM_ABI void execute(unsigned IID)
LLVM_ABI bool updatePending()
void setLSUTokenID(unsigned LSUTok)
void setUsedBuffers(uint64_t Mask)
void setCriticalMemDep(const CriticalDependency &MemDep)
LLVM_ABI void dispatch(unsigned RCUTokenID)
LLVM_ABI void update()
uint64_t getUsedBuffers() const
LLVM_ABI void reset()
unsigned getLSUTokenID() const
A representation of an mca::Instruction operand for use in mca::CustomBehaviour.
Definition Instruction.h:37
unsigned getReg() const
Returns the register number.
Definition Instruction.h:73
static MCAOperand createSFPImm(uint32_t Val)
uint32_t getSFPImm() const
Definition Instruction.h:83
static MCAOperand createInvalid()
static MCAOperand createDFPImm(uint64_t Val)
static MCAOperand createImm(int64_t Val)
static MCAOperand createReg(unsigned Reg)
Definition Instruction.h:97
unsigned getIndex() const
Definition Instruction.h:95
bool isDFPImm() const
Definition Instruction.h:70
bool isSFPImm() const
Definition Instruction.h:69
int64_t getImm() const
Definition Instruction.h:78
uint64_t getDFPImm() const
Definition Instruction.h:88
void setIndex(const unsigned Idx)
Definition Instruction.h:93
bool isValid() const
Definition Instruction.h:66
Tracks register operand latency in cycles.
unsigned getRegisterFileID() const
unsigned getSchedClass() const
LLVM_ABI void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles)
bool isIndependentFromDef() const
const ReadDescriptor & getDescriptor() const
void setPRF(unsigned ID)
const CriticalDependency & getCriticalRegDep() const
LLVM_ABI void cycleEvent()
void setDependentWrites(unsigned Writes)
bool isReady() const
MCPhysReg getRegisterID() const
bool isImplicitRead() const
ReadState(const ReadDescriptor &Desc, MCPhysReg RegID)
bool isPending() const
bool isReadZero() const
Tracks uses of a register definition (e.g.
unsigned getRegisterFileID() const
bool isEliminated() const
const WriteState * getDependentWrite() const
LLVM_ABI void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles)
unsigned getDependentWriteCyclesLeft() const
void setRegisterID(const MCPhysReg RegID)
unsigned getLatency() const
WriteState & operator=(const WriteState &Other)=default
void setPRF(unsigned PRF)
void setDependentWrite(const WriteState *Other)
int getCyclesLeft() const
LLVM_ABI void cycleEvent()
WriteState(const WriteDescriptor &Desc, MCPhysReg RegID, bool clearsSuperRegs=false, bool writesZero=false)
const CriticalDependency & getCriticalRegDep() const
LLVM_ABI void onInstructionIssued(unsigned IID)
WriteState(const WriteState &Other)=default
bool clearsSuperRegisters() const
unsigned getNumUsers() const
MCPhysReg getRegisterID() const
bool isWriteZero() const
bool isExecuted() const
unsigned getWriteResourceID() const
LLVM_ABI void addUser(unsigned IID, ReadState *Use, int ReadAdvance)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
char InstructionError< T >::ID
Definition Support.h:44
raw_ostream & operator<<(raw_ostream &OS, const InstRef &IR)
constexpr int UNKNOWN_CYCLES
Definition Instruction.h:33
This is an optimization pass for GlobalISel generic memory operations.
Op::Description Desc
CycleInfo::CycleT Cycle
Definition CycleInfo.h:24
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1732
@ Other
Any other memory.
Definition ModRef.h:68
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1758
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:867
A critical data dependency descriptor.
An instruction descriptor.
SmallVector< WriteDescriptor, 2 > Writes
InstrDesc(const InstrDesc &Other)=delete
SmallVector< std::pair< uint64_t, ResourceUsage >, 4 > Resources
unsigned HasPartiallyOverlappingGroups
SmallVector< ReadDescriptor, 4 > Reads
bool isZeroLatency() const
InstrDesc & operator=(const InstrDesc &Other)=delete
unsigned MustIssueImmediately
A register read descriptor.
ResourceUsage(CycleSegment Cycles, unsigned Units=1)
unsigned size() const
A register write descriptor.