Instruction.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. //===--------------------- Instruction.cpp ----------------------*- 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. //
  9. // This file defines abstractions used by the Pipeline to model register reads,
  10. // register writes and instructions.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/MCA/Instruction.h"
  14. #include "llvm/Support/Debug.h"
  15. #include "llvm/Support/raw_ostream.h"
  16. namespace llvm {
  17. namespace mca {
  18. void WriteState::writeStartEvent(unsigned IID, MCPhysReg RegID,
  19. unsigned Cycles) {
  20. CRD.IID = IID;
  21. CRD.RegID = RegID;
  22. CRD.Cycles = Cycles;
  23. DependentWriteCyclesLeft = Cycles;
  24. DependentWrite = nullptr;
  25. }
  26. void ReadState::writeStartEvent(unsigned IID, MCPhysReg RegID,
  27. unsigned Cycles) {
  28. assert(DependentWrites);
  29. assert(CyclesLeft == UNKNOWN_CYCLES);
  30. // This read may be dependent on more than one write. This typically occurs
  31. // when a definition is the result of multiple writes where at least one
  32. // write does a partial register update.
  33. // The HW is forced to do some extra bookkeeping to track of all the
  34. // dependent writes, and implement a merging scheme for the partial writes.
  35. --DependentWrites;
  36. if (TotalCycles < Cycles) {
  37. CRD.IID = IID;
  38. CRD.RegID = RegID;
  39. CRD.Cycles = Cycles;
  40. TotalCycles = Cycles;
  41. }
  42. if (!DependentWrites) {
  43. CyclesLeft = TotalCycles;
  44. IsReady = !CyclesLeft;
  45. }
  46. }
  47. void WriteState::onInstructionIssued(unsigned IID) {
  48. assert(CyclesLeft == UNKNOWN_CYCLES);
  49. // Update the number of cycles left based on the WriteDescriptor info.
  50. CyclesLeft = getLatency();
  51. // Now that the time left before write-back is known, notify
  52. // all the users.
  53. for (const std::pair<ReadState *, int> &User : Users) {
  54. ReadState *RS = User.first;
  55. unsigned ReadCycles = std::max(0, CyclesLeft - User.second);
  56. RS->writeStartEvent(IID, RegisterID, ReadCycles);
  57. }
  58. // Notify any writes that are in a false dependency with this write.
  59. if (PartialWrite)
  60. PartialWrite->writeStartEvent(IID, RegisterID, CyclesLeft);
  61. }
  62. void WriteState::addUser(unsigned IID, ReadState *User, int ReadAdvance) {
  63. // If CyclesLeft is different than -1, then we don't need to
  64. // update the list of users. We can just notify the user with
  65. // the actual number of cycles left (which may be zero).
  66. if (CyclesLeft != UNKNOWN_CYCLES) {
  67. unsigned ReadCycles = std::max(0, CyclesLeft - ReadAdvance);
  68. User->writeStartEvent(IID, RegisterID, ReadCycles);
  69. return;
  70. }
  71. Users.emplace_back(User, ReadAdvance);
  72. }
  73. void WriteState::addUser(unsigned IID, WriteState *User) {
  74. if (CyclesLeft != UNKNOWN_CYCLES) {
  75. User->writeStartEvent(IID, RegisterID, std::max(0, CyclesLeft));
  76. return;
  77. }
  78. assert(!PartialWrite && "PartialWrite already set!");
  79. PartialWrite = User;
  80. User->setDependentWrite(this);
  81. }
  82. void WriteState::cycleEvent() {
  83. // Note: CyclesLeft can be a negative number. It is an error to
  84. // make it an unsigned quantity because users of this write may
  85. // specify a negative ReadAdvance.
  86. if (CyclesLeft != UNKNOWN_CYCLES)
  87. CyclesLeft--;
  88. if (DependentWriteCyclesLeft)
  89. DependentWriteCyclesLeft--;
  90. }
  91. void ReadState::cycleEvent() {
  92. // Update the total number of cycles.
  93. if (DependentWrites && TotalCycles) {
  94. --TotalCycles;
  95. return;
  96. }
  97. // Bail out immediately if we don't know how many cycles are left.
  98. if (CyclesLeft == UNKNOWN_CYCLES)
  99. return;
  100. if (CyclesLeft) {
  101. --CyclesLeft;
  102. IsReady = !CyclesLeft;
  103. }
  104. }
  105. #ifndef NDEBUG
  106. void WriteState::dump() const {
  107. dbgs() << "{ OpIdx=" << WD->OpIndex << ", Lat=" << getLatency() << ", RegID "
  108. << getRegisterID() << ", Cycles Left=" << getCyclesLeft() << " }";
  109. }
  110. #endif
  111. const CriticalDependency &Instruction::computeCriticalRegDep() {
  112. if (CriticalRegDep.Cycles)
  113. return CriticalRegDep;
  114. unsigned MaxLatency = 0;
  115. for (const WriteState &WS : getDefs()) {
  116. const CriticalDependency &WriteCRD = WS.getCriticalRegDep();
  117. if (WriteCRD.Cycles > MaxLatency)
  118. CriticalRegDep = WriteCRD;
  119. }
  120. for (const ReadState &RS : getUses()) {
  121. const CriticalDependency &ReadCRD = RS.getCriticalRegDep();
  122. if (ReadCRD.Cycles > MaxLatency)
  123. CriticalRegDep = ReadCRD;
  124. }
  125. return CriticalRegDep;
  126. }
  127. void Instruction::reset() {
  128. // Note that this won't clear read/write descriptors
  129. // or other non-trivial fields
  130. Stage = IS_INVALID;
  131. CyclesLeft = UNKNOWN_CYCLES;
  132. clearOptimizableMove();
  133. RCUTokenID = 0;
  134. LSUTokenID = 0;
  135. CriticalResourceMask = 0;
  136. IsEliminated = false;
  137. }
  138. void Instruction::dispatch(unsigned RCUToken) {
  139. assert(Stage == IS_INVALID);
  140. Stage = IS_DISPATCHED;
  141. RCUTokenID = RCUToken;
  142. // Check if input operands are already available.
  143. if (updateDispatched())
  144. updatePending();
  145. }
  146. void Instruction::execute(unsigned IID) {
  147. assert(Stage == IS_READY);
  148. Stage = IS_EXECUTING;
  149. // Set the cycles left before the write-back stage.
  150. CyclesLeft = getLatency();
  151. for (WriteState &WS : getDefs())
  152. WS.onInstructionIssued(IID);
  153. // Transition to the "executed" stage if this is a zero-latency instruction.
  154. if (!CyclesLeft)
  155. Stage = IS_EXECUTED;
  156. }
  157. void Instruction::forceExecuted() {
  158. assert(Stage == IS_READY && "Invalid internal state!");
  159. CyclesLeft = 0;
  160. Stage = IS_EXECUTED;
  161. }
  162. bool Instruction::updatePending() {
  163. assert(isPending() && "Unexpected instruction stage found!");
  164. if (!all_of(getUses(), [](const ReadState &Use) { return Use.isReady(); }))
  165. return false;
  166. // A partial register write cannot complete before a dependent write.
  167. if (!all_of(getDefs(), [](const WriteState &Def) { return Def.isReady(); }))
  168. return false;
  169. Stage = IS_READY;
  170. return true;
  171. }
  172. bool Instruction::updateDispatched() {
  173. assert(isDispatched() && "Unexpected instruction stage found!");
  174. if (!all_of(getUses(), [](const ReadState &Use) {
  175. return Use.isPending() || Use.isReady();
  176. }))
  177. return false;
  178. // A partial register write cannot complete before a dependent write.
  179. if (!all_of(getDefs(),
  180. [](const WriteState &Def) { return !Def.getDependentWrite(); }))
  181. return false;
  182. Stage = IS_PENDING;
  183. return true;
  184. }
  185. void Instruction::update() {
  186. if (isDispatched())
  187. updateDispatched();
  188. if (isPending())
  189. updatePending();
  190. }
  191. void Instruction::cycleEvent() {
  192. if (isReady())
  193. return;
  194. if (isDispatched() || isPending()) {
  195. for (ReadState &Use : getUses())
  196. Use.cycleEvent();
  197. for (WriteState &Def : getDefs())
  198. Def.cycleEvent();
  199. update();
  200. return;
  201. }
  202. assert(isExecuting() && "Instruction not in-flight?");
  203. assert(CyclesLeft && "Instruction already executed?");
  204. for (WriteState &Def : getDefs())
  205. Def.cycleEvent();
  206. CyclesLeft--;
  207. if (!CyclesLeft)
  208. Stage = IS_EXECUTED;
  209. }
  210. } // namespace mca
  211. } // namespace llvm