Instruction.cpp 6.9 KB

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