]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/include/llvm/MCA/Instruction.h
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / include / llvm / MCA / Instruction.h
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"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/Support/MathExtras.h"
22
23 #ifndef NDEBUG
24 #include "llvm/Support/raw_ostream.h"
25 #endif
26
27 #include <memory>
28
29 namespace llvm {
30
31 namespace mca {
32
33 constexpr int UNKNOWN_CYCLES = -512;
34
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.
40   int OpIndex;
41   // Write latency. Number of cycles before write-back stage.
42   unsigned Latency;
43   // This field is set to a value different than zero only if this
44   // is an implicit definition.
45   unsigned RegisterID;
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
53   // write-back stage).
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
57   // register").
58   bool IsOptionalDef;
59
60   bool isImplicitWrite() const { return OpIndex < 0; };
61 };
62
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.
68   int OpIndex;
69   // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit
70   // uses always come first in the sequence of uses.
71   unsigned UseIndex;
72   // This field is only set if this is an implicit read.
73   unsigned RegisterID;
74   // Scheduling Class Index. It is used to query the scheduling model for the
75   // MCSchedClassDesc object.
76   unsigned SchedClassID;
77
78   bool isImplicitRead() const { return OpIndex < 0; };
79 };
80
81 class ReadState;
82
83 /// A critical data dependency descriptor.
84 ///
85 /// Field RegID is set to the invalid register for memory dependencies.
86 struct CriticalDependency {
87   unsigned IID;
88   unsigned RegID;
89   unsigned Cycles;
90 };
91
92 /// Tracks uses of a register definition (e.g. register write).
93 ///
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
97 /// back stage.
98 class WriteState {
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.
103   int CyclesLeft;
104
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.
109   unsigned RegisterID;
110
111   // Physical register file that serves register RegisterID.
112   unsigned PRFID;
113
114   // True if this write implicitly clears the upper portion of RegisterID's
115   // super-registers.
116   bool ClearsSuperRegs;
117
118   // True if this write is from a dependency breaking zero-idiom instruction.
119   bool WritesZero;
120
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.
125   bool IsEliminated;
126
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;
132
133   // A partial write that is in a false dependency with this write.
134   WriteState *PartialWrite;
135   unsigned DependentWriteCyclesLeft;
136
137   // Critical register dependency for this write.
138   CriticalDependency CRD;
139
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.
144
145   // The 'second' element of a pair is a "ReadAdvance" number of cycles.
146   SmallVector<std::pair<ReadState *, int>, 4> Users;
147
148 public:
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() {}
155
156   WriteState(const WriteState &Other) = default;
157   WriteState &operator=(const WriteState &Other) = default;
158
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;
166   }
167   const WriteState *getDependentWrite() const { return DependentWrite; }
168   const CriticalDependency &getCriticalRegDep() const { return CRD; }
169
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);
175
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);
179
180   unsigned getNumUsers() const {
181     unsigned NumUsers = Users.size();
182     if (PartialWrite)
183       ++NumUsers;
184     return NumUsers;
185   }
186
187   bool clearsSuperRegisters() const { return ClearsSuperRegs; }
188   bool isWriteZero() const { return WritesZero; }
189   bool isEliminated() const { return IsEliminated; }
190
191   bool isReady() const {
192     if (DependentWrite)
193       return false;
194     unsigned CyclesLeft = getDependentWriteCyclesLeft();
195     return !CyclesLeft || CyclesLeft < getLatency();
196   }
197
198   bool isExecuted() const {
199     return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0;
200   }
201
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.");
207     CyclesLeft = 0;
208     IsEliminated = true;
209   }
210
211   void setPRF(unsigned PRF) { PRFID = PRF; }
212
213   // On every cycle, update CyclesLeft and notify dependent users.
214   void cycleEvent();
215   void onInstructionIssued(unsigned IID);
216
217 #ifndef NDEBUG
218   void dump() const;
219 #endif
220 };
221
222 /// Tracks register operand latency in cycles.
223 ///
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.
226 class ReadState {
227   const ReadDescriptor *RD;
228   // Physical register identified associated to this read.
229   unsigned RegisterID;
230   // Physical register file that serves register RegisterID.
231   unsigned PRFID;
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.
240   int CyclesLeft;
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.
249   bool IsReady;
250   // True if this is a read from a known zero register.
251   bool IsZero;
252   // True if this register read is from a dependency-breaking instruction.
253   bool IndependentFromDef;
254
255 public:
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) {}
260
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; }
266
267   bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; }
268   bool isReady() const { return IsReady; }
269   bool isImplicitRead() const { return RD->isImplicitRead(); }
270
271   bool isIndependentFromDef() const { return IndependentFromDef; }
272   void setIndependentFromDef() { IndependentFromDef = true; }
273
274   void cycleEvent();
275   void writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles);
276   void setDependentWrites(unsigned Writes) {
277     DependentWrites = Writes;
278     IsReady = !Writes;
279   }
280
281   bool isReadZero() const { return IsZero; }
282   void setReadZero() { IsZero = true; }
283   void setPRF(unsigned ID) { PRFID = ID; }
284 };
285
286 /// A sequence of cycles.
287 ///
288 /// This class can be used as a building block to construct ranges of cycles.
289 class CycleSegment {
290   unsigned Begin; // Inclusive.
291   unsigned End;   // Exclusive.
292   bool Reserved;  // Resources associated to this segment must be reserved.
293
294 public:
295   CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false)
296       : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {}
297
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);
303   }
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;
308   }
309   CycleSegment &operator--(void) {
310     if (Begin)
311       Begin--;
312     if (End)
313       End--;
314     return *this;
315   }
316
317   bool isValid() const { return Begin <= End; }
318   unsigned size() const { return End - Begin; };
319   void subtract(unsigned Cycles) {
320     assert(End >= Cycles);
321     End -= Cycles;
322   }
323
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; }
329 };
330
331 /// Helper used by class InstrDesc to describe how hardware resources
332 /// are used.
333 ///
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 {
337   CycleSegment CS;
338   unsigned NumUnits;
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(); }
344 };
345
346 /// An instruction descriptor
347 struct InstrDesc {
348   SmallVector<WriteDescriptor, 4> Writes; // Implicit writes are at the end.
349   SmallVector<ReadDescriptor, 4> Reads;   // Implicit reads are at the end.
350
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;
354
355   // A list of buffered resources consumed by this instruction.
356   SmallVector<uint64_t, 4> Buffers;
357
358   unsigned UsedProcResUnits;
359   unsigned UsedProcResGroups;
360
361   unsigned MaxLatency;
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;
368
369   bool MayLoad;
370   bool MayStore;
371   bool HasSideEffects;
372   bool BeginGroup;
373   bool EndGroup;
374
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;
378
379   // A zero latency instruction doesn't consume any scheduler resources.
380   bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
381
382   InstrDesc() = default;
383   InstrDesc(const InstrDesc &Other) = delete;
384   InstrDesc &operator=(const InstrDesc &Other) = delete;
385 };
386
387 /// Base class for instructions consumed by the simulation pipeline.
388 ///
389 /// This class tracks data dependencies as well as generic properties
390 /// of the instruction.
391 class InstructionBase {
392   const InstrDesc &Desc;
393
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;
398
399   // Output dependencies.
400   // One entry per each implicit and explicit register definition.
401   SmallVector<WriteState, 4> Defs;
402
403   // Input dependencies.
404   // One entry per each implicit and explicit register use.
405   SmallVector<ReadState, 4> Uses;
406
407 public:
408   InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {}
409
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; }
415
416   unsigned getLatency() const { return Desc.MaxLatency; }
417
418   bool hasDependentUsers() const {
419     return any_of(Defs,
420                   [](const WriteState &Def) { return Def.getNumUsers() > 0; });
421   }
422
423   unsigned getNumUsers() const {
424     unsigned NumUsers = 0;
425     for (const WriteState &Def : Defs)
426       NumUsers += Def.getNumUsers();
427     return NumUsers;
428   }
429
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; }
434 };
435
436 /// An instruction propagated through the simulated instruction pipeline.
437 ///
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 {
441   enum InstrStage {
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.
449   };
450
451   // The current instruction stage.
452   enum InstrStage Stage;
453
454   // This value defaults to the instruction latency. This instruction is
455   // considered executed when field CyclesLeft goes to zero.
456   int CyclesLeft;
457
458   // Retire Unit token ID for this instruction.
459   unsigned RCUTokenID;
460
461   // LS token ID for this instruction.
462   // This field is set to the invalid null token if this is not a memory
463   // operation.
464   unsigned LSUTokenID;
465
466   // Critical register dependency.
467   CriticalDependency CriticalRegDep;
468
469   // Critical memory dependency.
470   CriticalDependency CriticalMemDep;
471
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;
476
477   // True if this instruction has been optimized at register renaming stage.
478   bool IsEliminated;
479
480 public:
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) {}
485
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; }
490
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);
495
496   // Instruction issued. Transition to the IS_EXECUTING state, and update
497   // all the register definitions.
498   void execute(unsigned IID);
499
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
505   // updateWaiting().
506   void update();
507   bool updateDispatched();
508   bool updatePending();
509
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; }
517
518   // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
519   void forceExecuted();
520   void setEliminated() { IsEliminated = true; }
521
522   void retire() {
523     assert(isExecuted() && "Instruction is in an invalid state!");
524     Stage = IS_RETIRED;
525   }
526
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;
532   }
533
534   uint64_t getCriticalResourceMask() const { return CriticalResourceMask; }
535   void setCriticalResourceMask(uint64_t ResourceMask) {
536     CriticalResourceMask = ResourceMask;
537   }
538
539   void cycleEvent();
540 };
541
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.
545 class InstRef {
546   std::pair<unsigned, Instruction *> Data;
547
548 public:
549   InstRef() : Data(std::make_pair(0, nullptr)) {}
550   InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {}
551
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;
556   }
557
558   unsigned getSourceIndex() const { return Data.first; }
559   Instruction *getInstruction() { return Data.second; }
560   const Instruction *getInstruction() const { return Data.second; }
561
562   /// Returns true if this references a valid instruction.
563   explicit operator bool() const { return Data.second != nullptr; }
564
565   /// Invalidate this reference.
566   void invalidate() { Data.second = nullptr; }
567
568 #ifndef NDEBUG
569   void print(raw_ostream &OS) const { OS << getSourceIndex(); }
570 #endif
571 };
572
573 #ifndef NDEBUG
574 inline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) {
575   IR.print(OS);
576   return OS;
577 }
578 #endif
579
580 /// A reference to a register write.
581 ///
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.
585 class WriteRef {
586   std::pair<unsigned, WriteState *> Data;
587   static const unsigned INVALID_IID;
588
589 public:
590   WriteRef() : Data(INVALID_IID, nullptr) {}
591   WriteRef(unsigned SourceIndex, WriteState *WS) : Data(SourceIndex, WS) {}
592
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();
600   }
601
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)
606       return false;
607     const WriteState *WS = getWriteState();
608     return !WS || WS->isExecuted();
609   }
610
611   bool isValid() const { return Data.second && Data.first != INVALID_IID; }
612   bool operator==(const WriteRef &Other) const { return Data == Other.Data; }
613
614 #ifndef NDEBUG
615   void dump() const;
616 #endif
617 };
618
619 } // namespace mca
620 } // namespace llvm
621
622 #endif // LLVM_MCA_INSTRUCTION_H