Instruction.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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::dispatch(unsigned RCUToken) {
  128. assert(Stage == IS_INVALID);
  129. Stage = IS_DISPATCHED;
  130. RCUTokenID = RCUToken;
  131. // Check if input operands are already available.
  132. if (updateDispatched())
  133. updatePending();
  134. }
  135. void Instruction::execute(unsigned IID) {
  136. assert(Stage == IS_READY);
  137. Stage = IS_EXECUTING;
  138. // Set the cycles left before the write-back stage.
  139. CyclesLeft = getLatency();
  140. for (WriteState &WS : getDefs())
  141. WS.onInstructionIssued(IID);
  142. // Transition to the "executed" stage if this is a zero-latency instruction.
  143. if (!CyclesLeft)
  144. Stage = IS_EXECUTED;
  145. }
  146. void Instruction::forceExecuted() {
  147. assert(Stage == IS_READY && "Invalid internal state!");
  148. CyclesLeft = 0;
  149. Stage = IS_EXECUTED;
  150. }
  151. bool Instruction::updatePending() {
  152. assert(isPending() && "Unexpected instruction stage found!");
  153. if (!all_of(getUses(), [](const ReadState &Use) { return Use.isReady(); }))
  154. return false;
  155. // A partial register write cannot complete before a dependent write.
  156. if (!all_of(getDefs(), [](const WriteState &Def) { return Def.isReady(); }))
  157. return false;
  158. Stage = IS_READY;
  159. return true;
  160. }
  161. bool Instruction::updateDispatched() {
  162. assert(isDispatched() && "Unexpected instruction stage found!");
  163. if (!all_of(getUses(), [](const ReadState &Use) {
  164. return Use.isPending() || Use.isReady();
  165. }))
  166. return false;
  167. // A partial register write cannot complete before a dependent write.
  168. if (!all_of(getDefs(),
  169. [](const WriteState &Def) { return !Def.getDependentWrite(); }))
  170. return false;
  171. Stage = IS_PENDING;
  172. return true;
  173. }
  174. void Instruction::update() {
  175. if (isDispatched())
  176. updateDispatched();
  177. if (isPending())
  178. updatePending();
  179. }
  180. void Instruction::cycleEvent() {
  181. if (isReady())
  182. return;
  183. if (isDispatched() || isPending()) {
  184. for (ReadState &Use : getUses())
  185. Use.cycleEvent();
  186. for (WriteState &Def : getDefs())
  187. Def.cycleEvent();
  188. update();
  189. return;
  190. }
  191. assert(isExecuting() && "Instruction not in-flight?");
  192. assert(CyclesLeft && "Instruction already executed?");
  193. for (WriteState &Def : getDefs())
  194. Def.cycleEvent();
  195. CyclesLeft--;
  196. if (!CyclesLeft)
  197. Stage = IS_EXECUTED;
  198. }
  199. } // namespace mca
  200. } // namespace llvm