Instruction.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  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. #ifndef LLVM_MCA_INSTRUCTION_H
  15. #define LLVM_MCA_INSTRUCTION_H
  16. #include "llvm/ADT/ArrayRef.h"
  17. #include "llvm/ADT/STLExtras.h"
  18. #include "llvm/ADT/SmallVector.h"
  19. #include "llvm/MC/MCRegister.h" // definition of MCPhysReg.
  20. #include "llvm/Support/MathExtras.h"
  21. #ifndef NDEBUG
  22. #include "llvm/Support/raw_ostream.h"
  23. #endif
  24. #include <memory>
  25. namespace llvm {
  26. namespace mca {
  27. constexpr int UNKNOWN_CYCLES = -512;
  28. /// A register write descriptor.
  29. struct WriteDescriptor {
  30. // Operand index. The index is negative for implicit writes only.
  31. // For implicit writes, the actual operand index is computed performing
  32. // a bitwise not of the OpIndex.
  33. int OpIndex;
  34. // Write latency. Number of cycles before write-back stage.
  35. unsigned Latency;
  36. // This field is set to a value different than zero only if this
  37. // is an implicit definition.
  38. MCPhysReg RegisterID;
  39. // Instruction itineraries would set this field to the SchedClass ID.
  40. // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry
  41. // element associated to this write.
  42. // When computing read latencies, this value is matched against the
  43. // "ReadAdvance" information. The hardware backend may implement
  44. // dedicated forwarding paths to quickly propagate write results to dependent
  45. // instructions waiting in the reservation station (effectively bypassing the
  46. // write-back stage).
  47. unsigned SClassOrWriteResourceID;
  48. // True only if this is a write obtained from an optional definition.
  49. // Optional definitions are allowed to reference regID zero (i.e. "no
  50. // register").
  51. bool IsOptionalDef;
  52. bool isImplicitWrite() const { return OpIndex < 0; };
  53. };
  54. /// A register read descriptor.
  55. struct ReadDescriptor {
  56. // A MCOperand index. This is used by the Dispatch logic to identify register
  57. // reads. Implicit reads have negative indices. The actual operand index of an
  58. // implicit read is the bitwise not of field OpIndex.
  59. int OpIndex;
  60. // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit
  61. // uses always come first in the sequence of uses.
  62. unsigned UseIndex;
  63. // This field is only set if this is an implicit read.
  64. MCPhysReg RegisterID;
  65. // Scheduling Class Index. It is used to query the scheduling model for the
  66. // MCSchedClassDesc object.
  67. unsigned SchedClassID;
  68. bool isImplicitRead() const { return OpIndex < 0; };
  69. };
  70. class ReadState;
  71. /// A critical data dependency descriptor.
  72. ///
  73. /// Field RegID is set to the invalid register for memory dependencies.
  74. struct CriticalDependency {
  75. unsigned IID;
  76. MCPhysReg RegID;
  77. unsigned Cycles;
  78. };
  79. /// Tracks uses of a register definition (e.g. register write).
  80. ///
  81. /// Each implicit/explicit register write is associated with an instance of
  82. /// this class. A WriteState object tracks the dependent users of a
  83. /// register write. It also tracks how many cycles are left before the write
  84. /// back stage.
  85. class WriteState {
  86. const WriteDescriptor *WD;
  87. // On instruction issue, this field is set equal to the write latency.
  88. // Before instruction issue, this field defaults to -512, a special
  89. // value that represents an "unknown" number of cycles.
  90. int CyclesLeft;
  91. // Actual register defined by this write. This field is only used
  92. // to speedup queries on the register file.
  93. // For implicit writes, this field always matches the value of
  94. // field RegisterID from WD.
  95. MCPhysReg RegisterID;
  96. // Physical register file that serves register RegisterID.
  97. unsigned PRFID;
  98. // True if this write implicitly clears the upper portion of RegisterID's
  99. // super-registers.
  100. bool ClearsSuperRegs;
  101. // True if this write is from a dependency breaking zero-idiom instruction.
  102. bool WritesZero;
  103. // True if this write has been eliminated at register renaming stage.
  104. // Example: a register move doesn't consume scheduler/pipleline resources if
  105. // it is eliminated at register renaming stage. It still consumes
  106. // decode bandwidth, and ROB entries.
  107. bool IsEliminated;
  108. // This field is set if this is a partial register write, and it has a false
  109. // dependency on any previous write of the same register (or a portion of it).
  110. // DependentWrite must be able to complete before this write completes, so
  111. // that we don't break the WAW, and the two writes can be merged together.
  112. const WriteState *DependentWrite;
  113. // A partial write that is in a false dependency with this write.
  114. WriteState *PartialWrite;
  115. unsigned DependentWriteCyclesLeft;
  116. // Critical register dependency for this write.
  117. CriticalDependency CRD;
  118. // A list of dependent reads. Users is a set of dependent
  119. // reads. A dependent read is added to the set only if CyclesLeft
  120. // is "unknown". As soon as CyclesLeft is 'known', each user in the set
  121. // gets notified with the actual CyclesLeft.
  122. // The 'second' element of a pair is a "ReadAdvance" number of cycles.
  123. SmallVector<std::pair<ReadState *, int>, 4> Users;
  124. public:
  125. WriteState(const WriteDescriptor &Desc, MCPhysReg RegID,
  126. bool clearsSuperRegs = false, bool writesZero = false)
  127. : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0),
  128. ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero),
  129. IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr),
  130. DependentWriteCyclesLeft(0), CRD() {}
  131. WriteState(const WriteState &Other) = default;
  132. WriteState &operator=(const WriteState &Other) = default;
  133. int getCyclesLeft() const { return CyclesLeft; }
  134. unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; }
  135. MCPhysReg getRegisterID() const { return RegisterID; }
  136. unsigned getRegisterFileID() const { return PRFID; }
  137. unsigned getLatency() const { return WD->Latency; }
  138. unsigned getDependentWriteCyclesLeft() const {
  139. return DependentWriteCyclesLeft;
  140. }
  141. const WriteState *getDependentWrite() const { return DependentWrite; }
  142. const CriticalDependency &getCriticalRegDep() const { return CRD; }
  143. // This method adds Use to the set of data dependent reads. IID is the
  144. // instruction identifier associated with this write. ReadAdvance is the
  145. // number of cycles to subtract from the latency of this data dependency.
  146. // Use is in a RAW dependency with this write.
  147. void addUser(unsigned IID, ReadState *Use, int ReadAdvance);
  148. // Use is a younger register write that is in a false dependency with this
  149. // write. IID is the instruction identifier associated with this write.
  150. void addUser(unsigned IID, WriteState *Use);
  151. unsigned getNumUsers() const {
  152. unsigned NumUsers = Users.size();
  153. if (PartialWrite)
  154. ++NumUsers;
  155. return NumUsers;
  156. }
  157. bool clearsSuperRegisters() const { return ClearsSuperRegs; }
  158. bool isWriteZero() const { return WritesZero; }
  159. bool isEliminated() const { return IsEliminated; }
  160. bool isReady() const {
  161. if (DependentWrite)
  162. return false;
  163. unsigned CyclesLeft = getDependentWriteCyclesLeft();
  164. return !CyclesLeft || CyclesLeft < getLatency();
  165. }
  166. bool isExecuted() const {
  167. return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0;
  168. }
  169. void setDependentWrite(const WriteState *Other) { DependentWrite = Other; }
  170. void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
  171. void setWriteZero() { WritesZero = true; }
  172. void setEliminated() {
  173. assert(Users.empty() && "Write is in an inconsistent state.");
  174. CyclesLeft = 0;
  175. IsEliminated = true;
  176. }
  177. void setPRF(unsigned PRF) { PRFID = PRF; }
  178. // On every cycle, update CyclesLeft and notify dependent users.
  179. void cycleEvent();
  180. void onInstructionIssued(unsigned IID);
  181. #ifndef NDEBUG
  182. void dump() const;
  183. #endif
  184. };
  185. /// Tracks register operand latency in cycles.
  186. ///
  187. /// A read may be dependent on more than one write. This occurs when some
  188. /// writes only partially update the register associated to this read.
  189. class ReadState {
  190. const ReadDescriptor *RD;
  191. // Physical register identified associated to this read.
  192. MCPhysReg RegisterID;
  193. // Physical register file that serves register RegisterID.
  194. unsigned PRFID;
  195. // Number of writes that contribute to the definition of RegisterID.
  196. // In the absence of partial register updates, the number of DependentWrites
  197. // cannot be more than one.
  198. unsigned DependentWrites;
  199. // Number of cycles left before RegisterID can be read. This value depends on
  200. // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES.
  201. // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of
  202. // every dependent write is known.
  203. int CyclesLeft;
  204. // This field is updated on every writeStartEvent(). When the number of
  205. // dependent writes (i.e. field DependentWrite) is zero, this value is
  206. // propagated to field CyclesLeft.
  207. unsigned TotalCycles;
  208. // Longest register dependency.
  209. CriticalDependency CRD;
  210. // This field is set to true only if there are no dependent writes, and
  211. // there are no `CyclesLeft' to wait.
  212. bool IsReady;
  213. // True if this is a read from a known zero register.
  214. bool IsZero;
  215. // True if this register read is from a dependency-breaking instruction.
  216. bool IndependentFromDef;
  217. public:
  218. ReadState(const ReadDescriptor &Desc, MCPhysReg RegID)
  219. : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0),
  220. CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true),
  221. IsZero(false), IndependentFromDef(false) {}
  222. const ReadDescriptor &getDescriptor() const { return *RD; }
  223. unsigned getSchedClass() const { return RD->SchedClassID; }
  224. MCPhysReg getRegisterID() const { return RegisterID; }
  225. unsigned getRegisterFileID() const { return PRFID; }
  226. const CriticalDependency &getCriticalRegDep() const { return CRD; }
  227. bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; }
  228. bool isReady() const { return IsReady; }
  229. bool isImplicitRead() const { return RD->isImplicitRead(); }
  230. bool isIndependentFromDef() const { return IndependentFromDef; }
  231. void setIndependentFromDef() { IndependentFromDef = true; }
  232. void cycleEvent();
  233. void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
  234. void setDependentWrites(unsigned Writes) {
  235. DependentWrites = Writes;
  236. IsReady = !Writes;
  237. }
  238. bool isReadZero() const { return IsZero; }
  239. void setReadZero() { IsZero = true; }
  240. void setPRF(unsigned ID) { PRFID = ID; }
  241. };
  242. /// A sequence of cycles.
  243. ///
  244. /// This class can be used as a building block to construct ranges of cycles.
  245. class CycleSegment {
  246. unsigned Begin; // Inclusive.
  247. unsigned End; // Exclusive.
  248. bool Reserved; // Resources associated to this segment must be reserved.
  249. public:
  250. CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false)
  251. : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {}
  252. bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; }
  253. bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; }
  254. bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; }
  255. bool overlaps(const CycleSegment &CS) const {
  256. return !startsAfter(CS) && !endsBefore(CS);
  257. }
  258. bool isExecuting() const { return Begin == 0 && End != 0; }
  259. bool isExecuted() const { return End == 0; }
  260. bool operator<(const CycleSegment &Other) const {
  261. return Begin < Other.Begin;
  262. }
  263. CycleSegment &operator--(void) {
  264. if (Begin)
  265. Begin--;
  266. if (End)
  267. End--;
  268. return *this;
  269. }
  270. bool isValid() const { return Begin <= End; }
  271. unsigned size() const { return End - Begin; };
  272. void subtract(unsigned Cycles) {
  273. assert(End >= Cycles);
  274. End -= Cycles;
  275. }
  276. unsigned begin() const { return Begin; }
  277. unsigned end() const { return End; }
  278. void setEnd(unsigned NewEnd) { End = NewEnd; }
  279. bool isReserved() const { return Reserved; }
  280. void setReserved() { Reserved = true; }
  281. };
  282. /// Helper used by class InstrDesc to describe how hardware resources
  283. /// are used.
  284. ///
  285. /// This class describes how many resource units of a specific resource kind
  286. /// (and how many cycles) are "used" by an instruction.
  287. struct ResourceUsage {
  288. CycleSegment CS;
  289. unsigned NumUnits;
  290. ResourceUsage(CycleSegment Cycles, unsigned Units = 1)
  291. : CS(Cycles), NumUnits(Units) {}
  292. unsigned size() const { return CS.size(); }
  293. bool isReserved() const { return CS.isReserved(); }
  294. void setReserved() { CS.setReserved(); }
  295. };
  296. /// An instruction descriptor
  297. struct InstrDesc {
  298. SmallVector<WriteDescriptor, 4> Writes; // Implicit writes are at the end.
  299. SmallVector<ReadDescriptor, 4> Reads; // Implicit reads are at the end.
  300. // For every resource used by an instruction of this kind, this vector
  301. // reports the number of "consumed cycles".
  302. SmallVector<std::pair<uint64_t, ResourceUsage>, 4> Resources;
  303. // A bitmask of used hardware buffers.
  304. uint64_t UsedBuffers;
  305. // A bitmask of used processor resource units.
  306. uint64_t UsedProcResUnits;
  307. // A bitmask of used processor resource groups.
  308. uint64_t UsedProcResGroups;
  309. unsigned MaxLatency;
  310. // Number of MicroOps for this instruction.
  311. unsigned NumMicroOps;
  312. // SchedClassID used to construct this InstrDesc.
  313. // This information is currently used by views to do fast queries on the
  314. // subtarget when computing the reciprocal throughput.
  315. unsigned SchedClassID;
  316. bool MayLoad;
  317. bool MayStore;
  318. bool HasSideEffects;
  319. bool BeginGroup;
  320. bool EndGroup;
  321. bool RetireOOO;
  322. // True if all buffered resources are in-order, and there is at least one
  323. // buffer which is a dispatch hazard (BufferSize = 0).
  324. bool MustIssueImmediately;
  325. // A zero latency instruction doesn't consume any scheduler resources.
  326. bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
  327. InstrDesc() = default;
  328. InstrDesc(const InstrDesc &Other) = delete;
  329. InstrDesc &operator=(const InstrDesc &Other) = delete;
  330. };
  331. /// Base class for instructions consumed by the simulation pipeline.
  332. ///
  333. /// This class tracks data dependencies as well as generic properties
  334. /// of the instruction.
  335. class InstructionBase {
  336. const InstrDesc &Desc;
  337. // This field is set for instructions that are candidates for move
  338. // elimination. For more information about move elimination, see the
  339. // definition of RegisterMappingTracker in RegisterFile.h
  340. bool IsOptimizableMove;
  341. // Output dependencies.
  342. // One entry per each implicit and explicit register definition.
  343. SmallVector<WriteState, 4> Defs;
  344. // Input dependencies.
  345. // One entry per each implicit and explicit register use.
  346. SmallVector<ReadState, 4> Uses;
  347. public:
  348. InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {}
  349. SmallVectorImpl<WriteState> &getDefs() { return Defs; }
  350. ArrayRef<WriteState> getDefs() const { return Defs; }
  351. SmallVectorImpl<ReadState> &getUses() { return Uses; }
  352. ArrayRef<ReadState> getUses() const { return Uses; }
  353. const InstrDesc &getDesc() const { return Desc; }
  354. unsigned getLatency() const { return Desc.MaxLatency; }
  355. unsigned getNumMicroOps() const { return Desc.NumMicroOps; }
  356. bool hasDependentUsers() const {
  357. return any_of(Defs,
  358. [](const WriteState &Def) { return Def.getNumUsers() > 0; });
  359. }
  360. unsigned getNumUsers() const {
  361. unsigned NumUsers = 0;
  362. for (const WriteState &Def : Defs)
  363. NumUsers += Def.getNumUsers();
  364. return NumUsers;
  365. }
  366. // Returns true if this instruction is a candidate for move elimination.
  367. bool isOptimizableMove() const { return IsOptimizableMove; }
  368. void setOptimizableMove() { IsOptimizableMove = true; }
  369. bool isMemOp() const { return Desc.MayLoad || Desc.MayStore; }
  370. };
  371. /// An instruction propagated through the simulated instruction pipeline.
  372. ///
  373. /// This class is used to monitor changes to the internal state of instructions
  374. /// that are sent to the various components of the simulated hardware pipeline.
  375. class Instruction : public InstructionBase {
  376. enum InstrStage {
  377. IS_INVALID, // Instruction in an invalid state.
  378. IS_DISPATCHED, // Instruction dispatched but operands are not ready.
  379. IS_PENDING, // Instruction is not ready, but operand latency is known.
  380. IS_READY, // Instruction dispatched and operands ready.
  381. IS_EXECUTING, // Instruction issued.
  382. IS_EXECUTED, // Instruction executed. Values are written back.
  383. IS_RETIRED // Instruction retired.
  384. };
  385. // The current instruction stage.
  386. enum InstrStage Stage;
  387. // This value defaults to the instruction latency. This instruction is
  388. // considered executed when field CyclesLeft goes to zero.
  389. int CyclesLeft;
  390. // Retire Unit token ID for this instruction.
  391. unsigned RCUTokenID;
  392. // LS token ID for this instruction.
  393. // This field is set to the invalid null token if this is not a memory
  394. // operation.
  395. unsigned LSUTokenID;
  396. // A resource mask which identifies buffered resources consumed by this
  397. // instruction at dispatch stage. In the absence of macro-fusion, this value
  398. // should always match the value of field `UsedBuffers` from the instruction
  399. // descriptor (see field InstrBase::Desc).
  400. uint64_t UsedBuffers;
  401. // Critical register dependency.
  402. CriticalDependency CriticalRegDep;
  403. // Critical memory dependency.
  404. CriticalDependency CriticalMemDep;
  405. // A bitmask of busy processor resource units.
  406. // This field is set to zero only if execution is not delayed during this
  407. // cycle because of unavailable pipeline resources.
  408. uint64_t CriticalResourceMask;
  409. // True if this instruction has been optimized at register renaming stage.
  410. bool IsEliminated;
  411. public:
  412. Instruction(const InstrDesc &D)
  413. : InstructionBase(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES),
  414. RCUTokenID(0), LSUTokenID(0), UsedBuffers(D.UsedBuffers),
  415. CriticalRegDep(), CriticalMemDep(), CriticalResourceMask(0),
  416. IsEliminated(false) {}
  417. unsigned getRCUTokenID() const { return RCUTokenID; }
  418. unsigned getLSUTokenID() const { return LSUTokenID; }
  419. void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; }
  420. uint64_t getUsedBuffers() const { return UsedBuffers; }
  421. void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; }
  422. void clearUsedBuffers() { UsedBuffers = 0ULL; }
  423. int getCyclesLeft() const { return CyclesLeft; }
  424. // Transition to the dispatch stage, and assign a RCUToken to this
  425. // instruction. The RCUToken is used to track the completion of every
  426. // register write performed by this instruction.
  427. void dispatch(unsigned RCUTokenID);
  428. // Instruction issued. Transition to the IS_EXECUTING state, and update
  429. // all the register definitions.
  430. void execute(unsigned IID);
  431. // Force a transition from the IS_DISPATCHED state to the IS_READY or
  432. // IS_PENDING state. State transitions normally occur either at the beginning
  433. // of a new cycle (see method cycleEvent()), or as a result of another issue
  434. // event. This method is called every time the instruction might have changed
  435. // in state. It internally delegates to method updateDispatched() and
  436. // updateWaiting().
  437. void update();
  438. bool updateDispatched();
  439. bool updatePending();
  440. bool isDispatched() const { return Stage == IS_DISPATCHED; }
  441. bool isPending() const { return Stage == IS_PENDING; }
  442. bool isReady() const { return Stage == IS_READY; }
  443. bool isExecuting() const { return Stage == IS_EXECUTING; }
  444. bool isExecuted() const { return Stage == IS_EXECUTED; }
  445. bool isRetired() const { return Stage == IS_RETIRED; }
  446. bool isEliminated() const { return IsEliminated; }
  447. // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
  448. void forceExecuted();
  449. void setEliminated() { IsEliminated = true; }
  450. void retire() {
  451. assert(isExecuted() && "Instruction is in an invalid state!");
  452. Stage = IS_RETIRED;
  453. }
  454. const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; }
  455. const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; }
  456. const CriticalDependency &computeCriticalRegDep();
  457. void setCriticalMemDep(const CriticalDependency &MemDep) {
  458. CriticalMemDep = MemDep;
  459. }
  460. uint64_t getCriticalResourceMask() const { return CriticalResourceMask; }
  461. void setCriticalResourceMask(uint64_t ResourceMask) {
  462. CriticalResourceMask = ResourceMask;
  463. }
  464. void cycleEvent();
  465. };
  466. /// An InstRef contains both a SourceMgr index and Instruction pair. The index
  467. /// is used as a unique identifier for the instruction. MCA will make use of
  468. /// this index as a key throughout MCA.
  469. class InstRef {
  470. std::pair<unsigned, Instruction *> Data;
  471. public:
  472. InstRef() : Data(std::make_pair(0, nullptr)) {}
  473. InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {}
  474. bool operator==(const InstRef &Other) const { return Data == Other.Data; }
  475. bool operator!=(const InstRef &Other) const { return Data != Other.Data; }
  476. bool operator<(const InstRef &Other) const {
  477. return Data.first < Other.Data.first;
  478. }
  479. unsigned getSourceIndex() const { return Data.first; }
  480. Instruction *getInstruction() { return Data.second; }
  481. const Instruction *getInstruction() const { return Data.second; }
  482. /// Returns true if this references a valid instruction.
  483. explicit operator bool() const { return Data.second != nullptr; }
  484. /// Invalidate this reference.
  485. void invalidate() { Data.second = nullptr; }
  486. #ifndef NDEBUG
  487. void print(raw_ostream &OS) const { OS << getSourceIndex(); }
  488. #endif
  489. };
  490. #ifndef NDEBUG
  491. inline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) {
  492. IR.print(OS);
  493. return OS;
  494. }
  495. #endif
  496. } // namespace mca
  497. } // namespace llvm
  498. #endif // LLVM_MCA_INSTRUCTION_H