• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/MC/MCRegister.h" // definition of MCPhysReg.
22 #include "llvm/Support/MathExtras.h"
23 
24 #ifndef NDEBUG
25 #include "llvm/Support/raw_ostream.h"
26 #endif
27 
28 #include <memory>
29 
30 namespace llvm {
31 
32 namespace mca {
33 
34 constexpr int UNKNOWN_CYCLES = -512;
35 
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;
60 
isImplicitWriteWriteDescriptor61   bool isImplicitWrite() const { return OpIndex < 0; };
62 };
63 
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;
78 
isImplicitReadReadDescriptor79   bool isImplicitRead() const { return OpIndex < 0; };
80 };
81 
82 class ReadState;
83 
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;
91 };
92 
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;
105 
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;
111 
112   // Physical register file that serves register RegisterID.
113   unsigned PRFID;
114 
115   // True if this write implicitly clears the upper portion of RegisterID's
116   // super-registers.
117   bool ClearsSuperRegs;
118 
119   // True if this write is from a dependency breaking zero-idiom instruction.
120   bool WritesZero;
121 
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;
127 
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;
133 
134   // A partial write that is in a false dependency with this write.
135   WriteState *PartialWrite;
136   unsigned DependentWriteCyclesLeft;
137 
138   // Critical register dependency for this write.
139   CriticalDependency CRD;
140 
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.
145 
146   // The 'second' element of a pair is a "ReadAdvance" number of cycles.
147   SmallVector<std::pair<ReadState *, int>, 4> Users;
148 
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() {}
156 
157   WriteState(const WriteState &Other) = default;
158   WriteState &operator=(const WriteState &Other) = default;
159 
getCyclesLeft()160   int getCyclesLeft() const { return CyclesLeft; }
getWriteResourceID()161   unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; }
getRegisterID()162   MCPhysReg getRegisterID() const { return RegisterID; }
getRegisterFileID()163   unsigned getRegisterFileID() const { return PRFID; }
getLatency()164   unsigned getLatency() const { return WD->Latency; }
getDependentWriteCyclesLeft()165   unsigned getDependentWriteCyclesLeft() const {
166     return DependentWriteCyclesLeft;
167   }
getDependentWrite()168   const WriteState *getDependentWrite() const { return DependentWrite; }
getCriticalRegDep()169   const CriticalDependency &getCriticalRegDep() const { return CRD; }
170 
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);
176 
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);
180 
getNumUsers()181   unsigned getNumUsers() const {
182     unsigned NumUsers = Users.size();
183     if (PartialWrite)
184       ++NumUsers;
185     return NumUsers;
186   }
187 
clearsSuperRegisters()188   bool clearsSuperRegisters() const { return ClearsSuperRegs; }
isWriteZero()189   bool isWriteZero() const { return WritesZero; }
isEliminated()190   bool isEliminated() const { return IsEliminated; }
191 
isReady()192   bool isReady() const {
193     if (DependentWrite)
194       return false;
195     unsigned CyclesLeft = getDependentWriteCyclesLeft();
196     return !CyclesLeft || CyclesLeft < getLatency();
197   }
198 
isExecuted()199   bool isExecuted() const {
200     return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0;
201   }
202 
setDependentWrite(const WriteState * Other)203   void setDependentWrite(const WriteState *Other) { DependentWrite = Other; }
204   void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
setWriteZero()205   void setWriteZero() { WritesZero = true; }
setEliminated()206   void setEliminated() {
207     assert(Users.empty() && "Write is in an inconsistent state.");
208     CyclesLeft = 0;
209     IsEliminated = true;
210   }
211 
setPRF(unsigned PRF)212   void setPRF(unsigned PRF) { PRFID = PRF; }
213 
214   // On every cycle, update CyclesLeft and notify dependent users.
215   void cycleEvent();
216   void onInstructionIssued(unsigned IID);
217 
218 #ifndef NDEBUG
219   void dump() const;
220 #endif
221 };
222 
223 /// Tracks register operand latency in cycles.
224 ///
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;
255 
256 public:
ReadState(const ReadDescriptor & Desc,MCPhysReg RegID)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) {}
261 
getDescriptor()262   const ReadDescriptor &getDescriptor() const { return *RD; }
getSchedClass()263   unsigned getSchedClass() const { return RD->SchedClassID; }
getRegisterID()264   MCPhysReg getRegisterID() const { return RegisterID; }
getRegisterFileID()265   unsigned getRegisterFileID() const { return PRFID; }
getCriticalRegDep()266   const CriticalDependency &getCriticalRegDep() const { return CRD; }
267 
isPending()268   bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; }
isReady()269   bool isReady() const { return IsReady; }
isImplicitRead()270   bool isImplicitRead() const { return RD->isImplicitRead(); }
271 
isIndependentFromDef()272   bool isIndependentFromDef() const { return IndependentFromDef; }
setIndependentFromDef()273   void setIndependentFromDef() { IndependentFromDef = true; }
274 
275   void cycleEvent();
276   void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
setDependentWrites(unsigned Writes)277   void setDependentWrites(unsigned Writes) {
278     DependentWrites = Writes;
279     IsReady = !Writes;
280   }
281 
isReadZero()282   bool isReadZero() const { return IsZero; }
setReadZero()283   void setReadZero() { IsZero = true; }
setPRF(unsigned ID)284   void setPRF(unsigned ID) { PRFID = ID; }
285 };
286 
287 /// A sequence of cycles.
288 ///
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.
294 
295 public:
296   CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false)
Begin(StartCycle)297       : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {}
298 
contains(unsigned Cycle)299   bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; }
startsAfter(const CycleSegment & CS)300   bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; }
endsBefore(const CycleSegment & CS)301   bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; }
overlaps(const CycleSegment & CS)302   bool overlaps(const CycleSegment &CS) const {
303     return !startsAfter(CS) && !endsBefore(CS);
304   }
isExecuting()305   bool isExecuting() const { return Begin == 0 && End != 0; }
isExecuted()306   bool isExecuted() const { return End == 0; }
307   bool operator<(const CycleSegment &Other) const {
308     return Begin < Other.Begin;
309   }
310   CycleSegment &operator--(void) {
311     if (Begin)
312       Begin--;
313     if (End)
314       End--;
315     return *this;
316   }
317 
isValid()318   bool isValid() const { return Begin <= End; }
size()319   unsigned size() const { return End - Begin; };
subtract(unsigned Cycles)320   void subtract(unsigned Cycles) {
321     assert(End >= Cycles);
322     End -= Cycles;
323   }
324 
begin()325   unsigned begin() const { return Begin; }
end()326   unsigned end() const { return End; }
setEnd(unsigned NewEnd)327   void setEnd(unsigned NewEnd) { End = NewEnd; }
isReserved()328   bool isReserved() const { return Reserved; }
setReserved()329   void setReserved() { Reserved = true; }
330 };
331 
332 /// Helper used by class InstrDesc to describe how hardware resources
333 /// are used.
334 ///
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)
CSResourceUsage341       : CS(Cycles), NumUnits(Units) {}
sizeResourceUsage342   unsigned size() const { return CS.size(); }
isReservedResourceUsage343   bool isReserved() const { return CS.isReserved(); }
setReservedResourceUsage344   void setReserved() { CS.setReserved(); }
345 };
346 
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.
351 
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;
355 
356   // A bitmask of used hardware buffers.
357   uint64_t UsedBuffers;
358 
359   // A bitmask of used processor resource units.
360   uint64_t UsedProcResUnits;
361 
362   // A bitmask of used processor resource groups.
363   uint64_t UsedProcResGroups;
364 
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;
372 
373   bool MayLoad;
374   bool MayStore;
375   bool HasSideEffects;
376   bool BeginGroup;
377   bool EndGroup;
378 
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;
382 
383   // A zero latency instruction doesn't consume any scheduler resources.
isZeroLatencyInstrDesc384   bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
385 
386   InstrDesc() = default;
387   InstrDesc(const InstrDesc &Other) = delete;
388   InstrDesc &operator=(const InstrDesc &Other) = delete;
389 };
390 
391 /// Base class for instructions consumed by the simulation pipeline.
392 ///
393 /// This class tracks data dependencies as well as generic properties
394 /// of the instruction.
395 class InstructionBase {
396   const InstrDesc &Desc;
397 
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;
402 
403   // Output dependencies.
404   // One entry per each implicit and explicit register definition.
405   SmallVector<WriteState, 4> Defs;
406 
407   // Input dependencies.
408   // One entry per each implicit and explicit register use.
409   SmallVector<ReadState, 4> Uses;
410 
411 public:
InstructionBase(const InstrDesc & D)412   InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {}
413 
getDefs()414   SmallVectorImpl<WriteState> &getDefs() { return Defs; }
getDefs()415   const ArrayRef<WriteState> getDefs() const { return Defs; }
getUses()416   SmallVectorImpl<ReadState> &getUses() { return Uses; }
getUses()417   const ArrayRef<ReadState> getUses() const { return Uses; }
getDesc()418   const InstrDesc &getDesc() const { return Desc; }
419 
getLatency()420   unsigned getLatency() const { return Desc.MaxLatency; }
getNumMicroOps()421   unsigned getNumMicroOps() const { return Desc.NumMicroOps; }
422 
hasDependentUsers()423   bool hasDependentUsers() const {
424     return any_of(Defs,
425                   [](const WriteState &Def) { return Def.getNumUsers() > 0; });
426   }
427 
getNumUsers()428   unsigned getNumUsers() const {
429     unsigned NumUsers = 0;
430     for (const WriteState &Def : Defs)
431       NumUsers += Def.getNumUsers();
432     return NumUsers;
433   }
434 
435   // Returns true if this instruction is a candidate for move elimination.
isOptimizableMove()436   bool isOptimizableMove() const { return IsOptimizableMove; }
setOptimizableMove()437   void setOptimizableMove() { IsOptimizableMove = true; }
isMemOp()438   bool isMemOp() const { return Desc.MayLoad || Desc.MayStore; }
439 };
440 
441 /// An instruction propagated through the simulated instruction pipeline.
442 ///
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.
454   };
455 
456   // The current instruction stage.
457   enum InstrStage Stage;
458 
459   // This value defaults to the instruction latency. This instruction is
460   // considered executed when field CyclesLeft goes to zero.
461   int CyclesLeft;
462 
463   // Retire Unit token ID for this instruction.
464   unsigned RCUTokenID;
465 
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;
470 
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;
476 
477   // Critical register dependency.
478   CriticalDependency CriticalRegDep;
479 
480   // Critical memory dependency.
481   CriticalDependency CriticalMemDep;
482 
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;
487 
488   // True if this instruction has been optimized at register renaming stage.
489   bool IsEliminated;
490 
491 public:
Instruction(const InstrDesc & D)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) {}
497 
getRCUTokenID()498   unsigned getRCUTokenID() const { return RCUTokenID; }
getLSUTokenID()499   unsigned getLSUTokenID() const { return LSUTokenID; }
setLSUTokenID(unsigned LSUTok)500   void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; }
501 
getUsedBuffers()502   uint64_t getUsedBuffers() const { return UsedBuffers; }
setUsedBuffers(uint64_t Mask)503   void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; }
clearUsedBuffers()504   void clearUsedBuffers() { UsedBuffers = 0ULL; }
505 
getCyclesLeft()506   int getCyclesLeft() const { return CyclesLeft; }
507 
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);
512 
513   // Instruction issued. Transition to the IS_EXECUTING state, and update
514   // all the register definitions.
515   void execute(unsigned IID);
516 
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();
526 
isDispatched()527   bool isDispatched() const { return Stage == IS_DISPATCHED; }
isPending()528   bool isPending() const { return Stage == IS_PENDING; }
isReady()529   bool isReady() const { return Stage == IS_READY; }
isExecuting()530   bool isExecuting() const { return Stage == IS_EXECUTING; }
isExecuted()531   bool isExecuted() const { return Stage == IS_EXECUTED; }
isRetired()532   bool isRetired() const { return Stage == IS_RETIRED; }
isEliminated()533   bool isEliminated() const { return IsEliminated; }
534 
535   // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
536   void forceExecuted();
setEliminated()537   void setEliminated() { IsEliminated = true; }
538 
retire()539   void retire() {
540     assert(isExecuted() && "Instruction is in an invalid state!");
541     Stage = IS_RETIRED;
542   }
543 
getCriticalRegDep()544   const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; }
getCriticalMemDep()545   const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; }
546   const CriticalDependency &computeCriticalRegDep();
setCriticalMemDep(const CriticalDependency & MemDep)547   void setCriticalMemDep(const CriticalDependency &MemDep) {
548     CriticalMemDep = MemDep;
549   }
550 
getCriticalResourceMask()551   uint64_t getCriticalResourceMask() const { return CriticalResourceMask; }
setCriticalResourceMask(uint64_t ResourceMask)552   void setCriticalResourceMask(uint64_t ResourceMask) {
553     CriticalResourceMask = ResourceMask;
554   }
555 
556   void cycleEvent();
557 };
558 
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;
564 
565 public:
InstRef()566   InstRef() : Data(std::make_pair(0, nullptr)) {}
InstRef(unsigned Index,Instruction * I)567   InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {}
568 
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;
573   }
574 
getSourceIndex()575   unsigned getSourceIndex() const { return Data.first; }
getInstruction()576   Instruction *getInstruction() { return Data.second; }
getInstruction()577   const Instruction *getInstruction() const { return Data.second; }
578 
579   /// Returns true if this references a valid instruction.
580   explicit operator bool() const { return Data.second != nullptr; }
581 
582   /// Invalidate this reference.
invalidate()583   void invalidate() { Data.second = nullptr; }
584 
585 #ifndef NDEBUG
print(raw_ostream & OS)586   void print(raw_ostream &OS) const { OS << getSourceIndex(); }
587 #endif
588 };
589 
590 #ifndef NDEBUG
591 inline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) {
592   IR.print(OS);
593   return OS;
594 }
595 #endif
596 
597 /// A reference to a register write.
598 ///
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;
605 
606 public:
WriteRef()607   WriteRef() : Data(INVALID_IID, nullptr) {}
WriteRef(unsigned SourceIndex,WriteState * WS)608   WriteRef(unsigned SourceIndex, WriteState *WS) : Data(SourceIndex, WS) {}
609 
getSourceIndex()610   unsigned getSourceIndex() const { return Data.first; }
getWriteState()611   const WriteState *getWriteState() const { return Data.second; }
getWriteState()612   WriteState *getWriteState() { return Data.second; }
invalidate()613   void invalidate() { Data.second = nullptr; }
isWriteZero()614   bool isWriteZero() const {
615     assert(isValid() && "Invalid null WriteState found!");
616     return getWriteState()->isWriteZero();
617   }
618 
619   /// Returns true if this register write has been executed, and the new
620   /// register value is therefore available to users.
isAvailable()621   bool isAvailable() const {
622     if (getSourceIndex() == INVALID_IID)
623       return false;
624     const WriteState *WS = getWriteState();
625     return !WS || WS->isExecuted();
626   }
627 
isValid()628   bool isValid() const { return Data.second && Data.first != INVALID_IID; }
629   bool operator==(const WriteRef &Other) const { return Data == Other.Data; }
630 
631 #ifndef NDEBUG
632   void dump() const;
633 #endif
634 };
635 
636 } // namespace mca
637 } // namespace llvm
638 
639 #endif // LLVM_MCA_INSTRUCTION_H
640