Instruction.h 27 KB

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