ScoreboardHazardRecognizer.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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. #define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType
  16. #include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
  17. #include "llvm/CodeGen/ScheduleDAG.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. #include "llvm/Target/TargetInstrItineraries.h"
  23. using namespace llvm;
  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
  37. // depth of the scoreboard. We always make the scoreboard at least 1
  38. // cycle deep to avoid dealing with the boundary condition.
  39. unsigned ScoreboardDepth = 1;
  40. if (ItinData && !ItinData->isEmpty()) {
  41. IssueWidth = ItinData->IssueWidth;
  42. for (unsigned idx = 0; ; ++idx) {
  43. if (ItinData->isEndMarker(idx))
  44. break;
  45. const InstrStage *IS = ItinData->beginStage(idx);
  46. const InstrStage *E = ItinData->endStage(idx);
  47. unsigned CurCycle = 0;
  48. unsigned ItinDepth = 0;
  49. for (; IS != E; ++IS) {
  50. unsigned StageDepth = CurCycle + IS->getCycles();
  51. if (ItinDepth < StageDepth) ItinDepth = StageDepth;
  52. CurCycle += IS->getNextCycles();
  53. }
  54. // Find the next power-of-2 >= ItinDepth
  55. while (ItinDepth > ScoreboardDepth) {
  56. ScoreboardDepth *= 2;
  57. }
  58. }
  59. MaxLookAhead = ScoreboardDepth;
  60. }
  61. ReservedScoreboard.reset(ScoreboardDepth);
  62. RequiredScoreboard.reset(ScoreboardDepth);
  63. DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
  64. << ScoreboardDepth << '\n');
  65. }
  66. void ScoreboardHazardRecognizer::Reset() {
  67. IssueCount = 0;
  68. RequiredScoreboard.reset();
  69. ReservedScoreboard.reset();
  70. }
  71. void ScoreboardHazardRecognizer::Scoreboard::dump() const {
  72. dbgs() << "Scoreboard:\n";
  73. unsigned last = Depth - 1;
  74. while ((last > 0) && ((*this)[last] == 0))
  75. last--;
  76. for (unsigned i = 0; i <= last; i++) {
  77. unsigned FUs = (*this)[i];
  78. dbgs() << "\t";
  79. for (int j = 31; j >= 0; j--)
  80. dbgs() << ((FUs & (1 << j)) ? '1' : '0');
  81. dbgs() << '\n';
  82. }
  83. }
  84. bool ScoreboardHazardRecognizer::atIssueLimit() const {
  85. if (IssueWidth == 0)
  86. return false;
  87. return IssueCount == IssueWidth;
  88. }
  89. ScheduleHazardRecognizer::HazardType
  90. ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
  91. if (!ItinData || ItinData->isEmpty())
  92. return NoHazard;
  93. // Note that stalls will be negative for bottom-up scheduling.
  94. int cycle = Stalls;
  95. // Use the itinerary for the underlying instruction to check for
  96. // free FU's in the scoreboard at the appropriate future cycles.
  97. const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
  98. if (MCID == NULL) {
  99. // Don't check hazards for non-machineinstr Nodes.
  100. return NoHazard;
  101. }
  102. unsigned idx = MCID->getSchedClass();
  103. for (const InstrStage *IS = ItinData->beginStage(idx),
  104. *E = ItinData->endStage(idx); IS != E; ++IS) {
  105. // We must find one of the stage's units free for every cycle the
  106. // stage is occupied. FIXME it would be more accurate to find the
  107. // same unit free in all the cycles.
  108. for (unsigned int i = 0; i < IS->getCycles(); ++i) {
  109. int StageCycle = cycle + (int)i;
  110. if (StageCycle < 0)
  111. continue;
  112. if (StageCycle >= (int)RequiredScoreboard.getDepth()) {
  113. assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() &&
  114. "Scoreboard depth exceeded!");
  115. // This stage was stalled beyond pipeline depth, so cannot conflict.
  116. break;
  117. }
  118. unsigned freeUnits = IS->getUnits();
  119. switch (IS->getReservationKind()) {
  120. default:
  121. assert(0 && "Invalid FU reservation");
  122. case InstrStage::Required:
  123. // Required FUs conflict with both reserved and required ones
  124. freeUnits &= ~ReservedScoreboard[StageCycle];
  125. // FALLTHROUGH
  126. case InstrStage::Reserved:
  127. // Reserved FUs can conflict only with required ones.
  128. freeUnits &= ~RequiredScoreboard[StageCycle];
  129. break;
  130. }
  131. if (!freeUnits) {
  132. DEBUG(dbgs() << "*** Hazard in cycle " << (cycle + i) << ", ");
  133. DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
  134. DEBUG(DAG->dumpNode(SU));
  135. return Hazard;
  136. }
  137. }
  138. // Advance the cycle to the next stage.
  139. cycle += IS->getNextCycles();
  140. }
  141. return NoHazard;
  142. }
  143. void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
  144. if (!ItinData || ItinData->isEmpty())
  145. return;
  146. // Use the itinerary for the underlying instruction to reserve FU's
  147. // in the scoreboard at the appropriate future cycles.
  148. const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
  149. assert(MCID && "The scheduler must filter non-machineinstrs");
  150. if (DAG->TII->isZeroCost(MCID->Opcode))
  151. return;
  152. ++IssueCount;
  153. unsigned cycle = 0;
  154. unsigned idx = MCID->getSchedClass();
  155. for (const InstrStage *IS = ItinData->beginStage(idx),
  156. *E = ItinData->endStage(idx); IS != E; ++IS) {
  157. // We must reserve one of the stage's units for every cycle the
  158. // stage is occupied. FIXME it would be more accurate to reserve
  159. // the same unit free in all the cycles.
  160. for (unsigned int i = 0; i < IS->getCycles(); ++i) {
  161. assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
  162. "Scoreboard depth exceeded!");
  163. unsigned freeUnits = IS->getUnits();
  164. switch (IS->getReservationKind()) {
  165. default:
  166. assert(0 && "Invalid FU reservation");
  167. case InstrStage::Required:
  168. // Required FUs conflict with both reserved and required ones
  169. freeUnits &= ~ReservedScoreboard[cycle + i];
  170. // FALLTHROUGH
  171. case InstrStage::Reserved:
  172. // Reserved FUs can conflict only with required ones.
  173. freeUnits &= ~RequiredScoreboard[cycle + i];
  174. break;
  175. }
  176. // reduce to a single unit
  177. unsigned freeUnit = 0;
  178. do {
  179. freeUnit = freeUnits;
  180. freeUnits = freeUnit & (freeUnit - 1);
  181. } while (freeUnits);
  182. assert(freeUnit && "No function unit available!");
  183. if (IS->getReservationKind() == InstrStage::Required)
  184. RequiredScoreboard[cycle + i] |= freeUnit;
  185. else
  186. ReservedScoreboard[cycle + i] |= freeUnit;
  187. }
  188. // Advance the cycle to the next stage.
  189. cycle += IS->getNextCycles();
  190. }
  191. DEBUG(ReservedScoreboard.dump());
  192. DEBUG(RequiredScoreboard.dump());
  193. }
  194. void ScoreboardHazardRecognizer::AdvanceCycle() {
  195. IssueCount = 0;
  196. ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
  197. RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
  198. }
  199. void ScoreboardHazardRecognizer::RecedeCycle() {
  200. IssueCount = 0;
  201. ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
  202. ReservedScoreboard.recede();
  203. RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
  204. RequiredScoreboard.recede();
  205. }