2
0

ScoreboardHazardRecognizer.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. //===----- ScoreboardHazardRecognizer.cpp - Scheduler Support -------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements the ScoreboardHazardRecognizer class, which
  11. // encapsultes hazard-avoidance heuristics for scheduling, based on the
  12. // scheduling itineraries specified for the target.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
  16. #include "llvm/CodeGen/ScheduleDAG.h"
  17. #include "llvm/MC/MCInstrItineraries.h"
  18. #include "llvm/Support/Debug.h"
  19. #include "llvm/Support/ErrorHandling.h"
  20. #include "llvm/Support/raw_ostream.h"
  21. #include "llvm/Target/TargetInstrInfo.h"
  22. using namespace llvm;
  23. #define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType
  24. #ifndef NDEBUG
  25. const char *ScoreboardHazardRecognizer::DebugType = "";
  26. #endif
  27. ScoreboardHazardRecognizer::
  28. ScoreboardHazardRecognizer(const InstrItineraryData *II,
  29. const ScheduleDAG *SchedDAG,
  30. const char *ParentDebugType) :
  31. ScheduleHazardRecognizer(), ItinData(II), DAG(SchedDAG), IssueWidth(0),
  32. IssueCount(0) {
  33. #ifndef NDEBUG
  34. DebugType = ParentDebugType;
  35. #endif
  36. // Determine the maximum depth of any itinerary. This determines the depth of
  37. // the scoreboard. We always make the scoreboard at least 1 cycle deep to
  38. // avoid dealing with the boundary condition.
  39. unsigned ScoreboardDepth = 1;
  40. if (ItinData && !ItinData->isEmpty()) {
  41. for (unsigned idx = 0; ; ++idx) {
  42. if (ItinData->isEndMarker(idx))
  43. break;
  44. const InstrStage *IS = ItinData->beginStage(idx);
  45. const InstrStage *E = ItinData->endStage(idx);
  46. unsigned CurCycle = 0;
  47. unsigned ItinDepth = 0;
  48. for (; IS != E; ++IS) {
  49. unsigned StageDepth = CurCycle + IS->getCycles();
  50. if (ItinDepth < StageDepth) ItinDepth = StageDepth;
  51. CurCycle += IS->getNextCycles();
  52. }
  53. // Find the next power-of-2 >= ItinDepth
  54. while (ItinDepth > ScoreboardDepth) {
  55. ScoreboardDepth *= 2;
  56. // Don't set MaxLookAhead until we find at least one nonzero stage.
  57. // This way, an itinerary with no stages has MaxLookAhead==0, which
  58. // completely bypasses the scoreboard hazard logic.
  59. MaxLookAhead = ScoreboardDepth;
  60. }
  61. }
  62. }
  63. ReservedScoreboard.reset(ScoreboardDepth);
  64. RequiredScoreboard.reset(ScoreboardDepth);
  65. // If MaxLookAhead is not set above, then we are not enabled.
  66. if (!isEnabled())
  67. DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n");
  68. else {
  69. // A nonempty itinerary must have a SchedModel.
  70. IssueWidth = ItinData->SchedModel.IssueWidth;
  71. DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
  72. << ScoreboardDepth << '\n');
  73. }
  74. }
  75. void ScoreboardHazardRecognizer::Reset() {
  76. IssueCount = 0;
  77. RequiredScoreboard.reset();
  78. ReservedScoreboard.reset();
  79. }
  80. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  81. void ScoreboardHazardRecognizer::Scoreboard::dump() const {
  82. dbgs() << "Scoreboard:\n";
  83. unsigned last = Depth - 1;
  84. while ((last > 0) && ((*this)[last] == 0))
  85. last--;
  86. for (unsigned i = 0; i <= last; i++) {
  87. unsigned FUs = (*this)[i];
  88. dbgs() << "\t";
  89. for (int j = 31; j >= 0; j--)
  90. dbgs() << ((FUs & (1 << j)) ? '1' : '0');
  91. dbgs() << '\n';
  92. }
  93. }
  94. #endif
  95. bool ScoreboardHazardRecognizer::atIssueLimit() const {
  96. if (IssueWidth == 0)
  97. return false;
  98. return IssueCount == IssueWidth;
  99. }
  100. ScheduleHazardRecognizer::HazardType
  101. ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
  102. if (!ItinData || ItinData->isEmpty())
  103. return NoHazard;
  104. // Note that stalls will be negative for bottom-up scheduling.
  105. int cycle = Stalls;
  106. // Use the itinerary for the underlying instruction to check for
  107. // free FU's in the scoreboard at the appropriate future cycles.
  108. const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
  109. if (!MCID) {
  110. // Don't check hazards for non-machineinstr Nodes.
  111. return NoHazard;
  112. }
  113. unsigned idx = MCID->getSchedClass();
  114. for (const InstrStage *IS = ItinData->beginStage(idx),
  115. *E = ItinData->endStage(idx); IS != E; ++IS) {
  116. // We must find one of the stage's units free for every cycle the
  117. // stage is occupied. FIXME it would be more accurate to find the
  118. // same unit free in all the cycles.
  119. for (unsigned int i = 0; i < IS->getCycles(); ++i) {
  120. int StageCycle = cycle + (int)i;
  121. if (StageCycle < 0)
  122. continue;
  123. if (StageCycle >= (int)RequiredScoreboard.getDepth()) {
  124. assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() &&
  125. "Scoreboard depth exceeded!");
  126. // This stage was stalled beyond pipeline depth, so cannot conflict.
  127. break;
  128. }
  129. unsigned freeUnits = IS->getUnits();
  130. switch (IS->getReservationKind()) {
  131. case InstrStage::Required:
  132. // Required FUs conflict with both reserved and required ones
  133. freeUnits &= ~ReservedScoreboard[StageCycle];
  134. // FALLTHROUGH
  135. case InstrStage::Reserved:
  136. // Reserved FUs can conflict only with required ones.
  137. freeUnits &= ~RequiredScoreboard[StageCycle];
  138. break;
  139. }
  140. if (!freeUnits) {
  141. DEBUG(dbgs() << "*** Hazard in cycle +" << StageCycle << ", ");
  142. DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
  143. DEBUG(DAG->dumpNode(SU));
  144. return Hazard;
  145. }
  146. }
  147. // Advance the cycle to the next stage.
  148. cycle += IS->getNextCycles();
  149. }
  150. return NoHazard;
  151. }
  152. void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
  153. if (!ItinData || ItinData->isEmpty())
  154. return;
  155. // Use the itinerary for the underlying instruction to reserve FU's
  156. // in the scoreboard at the appropriate future cycles.
  157. const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
  158. assert(MCID && "The scheduler must filter non-machineinstrs");
  159. if (DAG->TII->isZeroCost(MCID->Opcode))
  160. return;
  161. ++IssueCount;
  162. unsigned cycle = 0;
  163. unsigned idx = MCID->getSchedClass();
  164. for (const InstrStage *IS = ItinData->beginStage(idx),
  165. *E = ItinData->endStage(idx); IS != E; ++IS) {
  166. // We must reserve one of the stage's units for every cycle the
  167. // stage is occupied. FIXME it would be more accurate to reserve
  168. // the same unit free in all the cycles.
  169. for (unsigned int i = 0; i < IS->getCycles(); ++i) {
  170. assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
  171. "Scoreboard depth exceeded!");
  172. unsigned freeUnits = IS->getUnits();
  173. switch (IS->getReservationKind()) {
  174. case InstrStage::Required:
  175. // Required FUs conflict with both reserved and required ones
  176. freeUnits &= ~ReservedScoreboard[cycle + i];
  177. // FALLTHROUGH
  178. case InstrStage::Reserved:
  179. // Reserved FUs can conflict only with required ones.
  180. freeUnits &= ~RequiredScoreboard[cycle + i];
  181. break;
  182. }
  183. // reduce to a single unit
  184. unsigned freeUnit = 0;
  185. do {
  186. freeUnit = freeUnits;
  187. freeUnits = freeUnit & (freeUnit - 1);
  188. } while (freeUnits);
  189. if (IS->getReservationKind() == InstrStage::Required)
  190. RequiredScoreboard[cycle + i] |= freeUnit;
  191. else
  192. ReservedScoreboard[cycle + i] |= freeUnit;
  193. }
  194. // Advance the cycle to the next stage.
  195. cycle += IS->getNextCycles();
  196. }
  197. DEBUG(ReservedScoreboard.dump());
  198. DEBUG(RequiredScoreboard.dump());
  199. }
  200. void ScoreboardHazardRecognizer::AdvanceCycle() {
  201. IssueCount = 0;
  202. ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
  203. RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
  204. }
  205. void ScoreboardHazardRecognizer::RecedeCycle() {
  206. IssueCount = 0;
  207. ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
  208. ReservedScoreboard.recede();
  209. RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
  210. RequiredScoreboard.recede();
  211. }