Home | History | Annotate | Line # | Download | only in MCA
      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 
     61   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 
     79   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 
    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;
    167   }
    168   const WriteState *getDependentWrite() const { return DependentWrite; }
    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 
    181   unsigned getNumUsers() const {
    182     unsigned NumUsers = Users.size();
    183     if (PartialWrite)
    184       ++NumUsers;
    185     return NumUsers;
    186   }
    187 
    188   bool clearsSuperRegisters() const { return ClearsSuperRegs; }
    189   bool isWriteZero() const { return WritesZero; }
    190   bool isEliminated() const { return IsEliminated; }
    191 
    192   bool isReady() const {
    193     if (DependentWrite)
    194       return false;
    195     unsigned CyclesLeft = getDependentWriteCyclesLeft();
    196     return !CyclesLeft || CyclesLeft < getLatency();
    197   }
    198 
    199   bool isExecuted() const {
    200     return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0;
    201   }
    202 
    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;
    210   }
    211 
    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:
    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 
    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; }
    267 
    268   bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; }
    269   bool isReady() const { return IsReady; }
    270   bool isImplicitRead() const { return RD->isImplicitRead(); }
    271 
    272   bool isIndependentFromDef() const { return IndependentFromDef; }
    273   void setIndependentFromDef() { IndependentFromDef = true; }
    274 
    275   void cycleEvent();
    276   void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
    277   void setDependentWrites(unsigned Writes) {
    278     DependentWrites = Writes;
    279     IsReady = !Writes;
    280   }
    281 
    282   bool isReadZero() const { return IsZero; }
    283   void setReadZero() { IsZero = true; }
    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)
    297       : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {}
    298 
    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);
    304   }
    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;
    309   }
    310   CycleSegment &operator--(void) {
    311     if (Begin)
    312       Begin--;
    313     if (End)
    314       End--;
    315     return *this;
    316   }
    317 
    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;
    323   }
    324 
    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; }
    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)
    341       : CS(Cycles), NumUnits(Units) {}
    342   unsigned size() const { return CS.size(); }
    343   bool isReserved() const { return CS.isReserved(); }
    344   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   bool RetireOOO;
    379 
    380   // True if all buffered resources are in-order, and there is at least one
    381   // buffer which is a dispatch hazard (BufferSize = 0).
    382   bool MustIssueImmediately;
    383 
    384   // A zero latency instruction doesn't consume any scheduler resources.
    385   bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
    386 
    387   InstrDesc() = default;
    388   InstrDesc(const InstrDesc &Other) = delete;
    389   InstrDesc &operator=(const InstrDesc &Other) = delete;
    390 };
    391 
    392 /// Base class for instructions consumed by the simulation pipeline.
    393 ///
    394 /// This class tracks data dependencies as well as generic properties
    395 /// of the instruction.
    396 class InstructionBase {
    397   const InstrDesc &Desc;
    398 
    399   // This field is set for instructions that are candidates for move
    400   // elimination. For more information about move elimination, see the
    401   // definition of RegisterMappingTracker in RegisterFile.h
    402   bool IsOptimizableMove;
    403 
    404   // Output dependencies.
    405   // One entry per each implicit and explicit register definition.
    406   SmallVector<WriteState, 4> Defs;
    407 
    408   // Input dependencies.
    409   // One entry per each implicit and explicit register use.
    410   SmallVector<ReadState, 4> Uses;
    411 
    412 public:
    413   InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {}
    414 
    415   SmallVectorImpl<WriteState> &getDefs() { return Defs; }
    416   ArrayRef<WriteState> getDefs() const { return Defs; }
    417   SmallVectorImpl<ReadState> &getUses() { return Uses; }
    418   ArrayRef<ReadState> getUses() const { return Uses; }
    419   const InstrDesc &getDesc() const { return Desc; }
    420 
    421   unsigned getLatency() const { return Desc.MaxLatency; }
    422   unsigned getNumMicroOps() const { return Desc.NumMicroOps; }
    423 
    424   bool hasDependentUsers() const {
    425     return any_of(Defs,
    426                   [](const WriteState &Def) { return Def.getNumUsers() > 0; });
    427   }
    428 
    429   unsigned getNumUsers() const {
    430     unsigned NumUsers = 0;
    431     for (const WriteState &Def : Defs)
    432       NumUsers += Def.getNumUsers();
    433     return NumUsers;
    434   }
    435 
    436   // Returns true if this instruction is a candidate for move elimination.
    437   bool isOptimizableMove() const { return IsOptimizableMove; }
    438   void setOptimizableMove() { IsOptimizableMove = true; }
    439   bool isMemOp() const { return Desc.MayLoad || Desc.MayStore; }
    440 };
    441 
    442 /// An instruction propagated through the simulated instruction pipeline.
    443 ///
    444 /// This class is used to monitor changes to the internal state of instructions
    445 /// that are sent to the various components of the simulated hardware pipeline.
    446 class Instruction : public InstructionBase {
    447   enum InstrStage {
    448     IS_INVALID,    // Instruction in an invalid state.
    449     IS_DISPATCHED, // Instruction dispatched but operands are not ready.
    450     IS_PENDING,    // Instruction is not ready, but operand latency is known.
    451     IS_READY,      // Instruction dispatched and operands ready.
    452     IS_EXECUTING,  // Instruction issued.
    453     IS_EXECUTED,   // Instruction executed. Values are written back.
    454     IS_RETIRED     // Instruction retired.
    455   };
    456 
    457   // The current instruction stage.
    458   enum InstrStage Stage;
    459 
    460   // This value defaults to the instruction latency. This instruction is
    461   // considered executed when field CyclesLeft goes to zero.
    462   int CyclesLeft;
    463 
    464   // Retire Unit token ID for this instruction.
    465   unsigned RCUTokenID;
    466 
    467   // LS token ID for this instruction.
    468   // This field is set to the invalid null token if this is not a memory
    469   // operation.
    470   unsigned LSUTokenID;
    471 
    472   // A resource mask which identifies buffered resources consumed by this
    473   // instruction at dispatch stage. In the absence of macro-fusion, this value
    474   // should always match the value of field `UsedBuffers` from the instruction
    475   // descriptor (see field InstrBase::Desc).
    476   uint64_t UsedBuffers;
    477 
    478   // Critical register dependency.
    479   CriticalDependency CriticalRegDep;
    480 
    481   // Critical memory dependency.
    482   CriticalDependency CriticalMemDep;
    483 
    484   // A bitmask of busy processor resource units.
    485   // This field is set to zero only if execution is not delayed during this
    486   // cycle because of unavailable pipeline resources.
    487   uint64_t CriticalResourceMask;
    488 
    489   // True if this instruction has been optimized at register renaming stage.
    490   bool IsEliminated;
    491 
    492 public:
    493   Instruction(const InstrDesc &D)
    494       : InstructionBase(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES),
    495         RCUTokenID(0), LSUTokenID(0), UsedBuffers(D.UsedBuffers),
    496         CriticalRegDep(), CriticalMemDep(), CriticalResourceMask(0),
    497         IsEliminated(false) {}
    498 
    499   unsigned getRCUTokenID() const { return RCUTokenID; }
    500   unsigned getLSUTokenID() const { return LSUTokenID; }
    501   void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; }
    502 
    503   uint64_t getUsedBuffers() const { return UsedBuffers; }
    504   void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; }
    505   void clearUsedBuffers() { UsedBuffers = 0ULL; }
    506 
    507   int getCyclesLeft() const { return CyclesLeft; }
    508 
    509   // Transition to the dispatch stage, and assign a RCUToken to this
    510   // instruction. The RCUToken is used to track the completion of every
    511   // register write performed by this instruction.
    512   void dispatch(unsigned RCUTokenID);
    513 
    514   // Instruction issued. Transition to the IS_EXECUTING state, and update
    515   // all the register definitions.
    516   void execute(unsigned IID);
    517 
    518   // Force a transition from the IS_DISPATCHED state to the IS_READY or
    519   // IS_PENDING state. State transitions normally occur either at the beginning
    520   // of a new cycle (see method cycleEvent()), or as a result of another issue
    521   // event. This method is called every time the instruction might have changed
    522   // in state. It internally delegates to method updateDispatched() and
    523   // updateWaiting().
    524   void update();
    525   bool updateDispatched();
    526   bool updatePending();
    527 
    528   bool isDispatched() const { return Stage == IS_DISPATCHED; }
    529   bool isPending() const { return Stage == IS_PENDING; }
    530   bool isReady() const { return Stage == IS_READY; }
    531   bool isExecuting() const { return Stage == IS_EXECUTING; }
    532   bool isExecuted() const { return Stage == IS_EXECUTED; }
    533   bool isRetired() const { return Stage == IS_RETIRED; }
    534   bool isEliminated() const { return IsEliminated; }
    535 
    536   // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
    537   void forceExecuted();
    538   void setEliminated() { IsEliminated = true; }
    539 
    540   void retire() {
    541     assert(isExecuted() && "Instruction is in an invalid state!");
    542     Stage = IS_RETIRED;
    543   }
    544 
    545   const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; }
    546   const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; }
    547   const CriticalDependency &computeCriticalRegDep();
    548   void setCriticalMemDep(const CriticalDependency &MemDep) {
    549     CriticalMemDep = MemDep;
    550   }
    551 
    552   uint64_t getCriticalResourceMask() const { return CriticalResourceMask; }
    553   void setCriticalResourceMask(uint64_t ResourceMask) {
    554     CriticalResourceMask = ResourceMask;
    555   }
    556 
    557   void cycleEvent();
    558 };
    559 
    560 /// An InstRef contains both a SourceMgr index and Instruction pair.  The index
    561 /// is used as a unique identifier for the instruction.  MCA will make use of
    562 /// this index as a key throughout MCA.
    563 class InstRef {
    564   std::pair<unsigned, Instruction *> Data;
    565 
    566 public:
    567   InstRef() : Data(std::make_pair(0, nullptr)) {}
    568   InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {}
    569 
    570   bool operator==(const InstRef &Other) const { return Data == Other.Data; }
    571   bool operator!=(const InstRef &Other) const { return Data != Other.Data; }
    572   bool operator<(const InstRef &Other) const {
    573     return Data.first < Other.Data.first;
    574   }
    575 
    576   unsigned getSourceIndex() const { return Data.first; }
    577   Instruction *getInstruction() { return Data.second; }
    578   const Instruction *getInstruction() const { return Data.second; }
    579 
    580   /// Returns true if this references a valid instruction.
    581   explicit operator bool() const { return Data.second != nullptr; }
    582 
    583   /// Invalidate this reference.
    584   void invalidate() { Data.second = nullptr; }
    585 
    586 #ifndef NDEBUG
    587   void print(raw_ostream &OS) const { OS << getSourceIndex(); }
    588 #endif
    589 };
    590 
    591 #ifndef NDEBUG
    592 inline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) {
    593   IR.print(OS);
    594   return OS;
    595 }
    596 #endif
    597 
    598 } // namespace mca
    599 } // namespace llvm
    600 
    601 #endif // LLVM_MCA_INSTRUCTION_H
    602