LatencyPriorityQueue.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. //===---- LatencyPriorityQueue.cpp - A latency-oriented priority queue ----===//
  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 LatencyPriorityQueue class, which is a
  11. // SchedulingPriorityQueue that schedules using latency information to
  12. // reduce the length of the critical path through the basic block.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #define DEBUG_TYPE "scheduler"
  16. #include "llvm/CodeGen/LatencyPriorityQueue.h"
  17. #include "llvm/Support/Debug.h"
  18. using namespace llvm;
  19. bool latency_sort::operator()(const SUnit *LHS, const SUnit *RHS) const {
  20. unsigned LHSNum = LHS->NodeNum;
  21. unsigned RHSNum = RHS->NodeNum;
  22. // The most important heuristic is scheduling the critical path.
  23. unsigned LHSLatency = PQ->getLatency(LHSNum);
  24. unsigned RHSLatency = PQ->getLatency(RHSNum);
  25. if (LHSLatency < RHSLatency) return true;
  26. if (LHSLatency > RHSLatency) return false;
  27. // After that, if two nodes have identical latencies, look to see if one will
  28. // unblock more other nodes than the other.
  29. unsigned LHSBlocked = PQ->getNumSolelyBlockNodes(LHSNum);
  30. unsigned RHSBlocked = PQ->getNumSolelyBlockNodes(RHSNum);
  31. if (LHSBlocked < RHSBlocked) return true;
  32. if (LHSBlocked > RHSBlocked) return false;
  33. // Finally, just to provide a stable ordering, use the node number as a
  34. // deciding factor.
  35. return LHSNum < RHSNum;
  36. }
  37. /// CalcNodePriority - Calculate the maximal path from the node to the exit.
  38. ///
  39. int LatencyPriorityQueue::CalcLatency(const SUnit &SU) {
  40. int &Latency = Latencies[SU.NodeNum];
  41. if (Latency != -1)
  42. return Latency;
  43. std::vector<const SUnit*> WorkList;
  44. WorkList.push_back(&SU);
  45. while (!WorkList.empty()) {
  46. const SUnit *Cur = WorkList.back();
  47. unsigned CurLatency = Cur->Latency;
  48. bool AllDone = true;
  49. unsigned MaxSuccLatency = 0;
  50. for (SUnit::const_succ_iterator I = Cur->Succs.begin(),E = Cur->Succs.end();
  51. I != E; ++I) {
  52. int SuccLatency = Latencies[I->getSUnit()->NodeNum];
  53. if (SuccLatency == -1) {
  54. AllDone = false;
  55. WorkList.push_back(I->getSUnit());
  56. } else {
  57. // This assumes that there's no delay for reusing registers.
  58. unsigned NewLatency = SuccLatency + CurLatency;
  59. MaxSuccLatency = std::max(MaxSuccLatency, NewLatency);
  60. }
  61. }
  62. if (AllDone) {
  63. Latencies[Cur->NodeNum] = MaxSuccLatency;
  64. WorkList.pop_back();
  65. }
  66. }
  67. return Latency;
  68. }
  69. /// CalculatePriorities - Calculate priorities of all scheduling units.
  70. void LatencyPriorityQueue::CalculatePriorities() {
  71. Latencies.assign(SUnits->size(), -1);
  72. NumNodesSolelyBlocking.assign(SUnits->size(), 0);
  73. // For each node, calculate the maximal path from the node to the exit.
  74. std::vector<std::pair<const SUnit*, unsigned> > WorkList;
  75. for (unsigned i = 0, e = SUnits->size(); i != e; ++i) {
  76. const SUnit *SU = &(*SUnits)[i];
  77. if (SU->Succs.empty())
  78. WorkList.push_back(std::make_pair(SU, 0U));
  79. }
  80. while (!WorkList.empty()) {
  81. const SUnit *SU = WorkList.back().first;
  82. unsigned SuccLat = WorkList.back().second;
  83. WorkList.pop_back();
  84. int &Latency = Latencies[SU->NodeNum];
  85. if (Latency == -1 || (SU->Latency + SuccLat) > (unsigned)Latency) {
  86. Latency = SU->Latency + SuccLat;
  87. for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end();
  88. I != E; ++I)
  89. WorkList.push_back(std::make_pair(I->getSUnit(), Latency));
  90. }
  91. }
  92. }
  93. /// getSingleUnscheduledPred - If there is exactly one unscheduled predecessor
  94. /// of SU, return it, otherwise return null.
  95. SUnit *LatencyPriorityQueue::getSingleUnscheduledPred(SUnit *SU) {
  96. SUnit *OnlyAvailablePred = 0;
  97. for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
  98. I != E; ++I) {
  99. SUnit &Pred = *I->getSUnit();
  100. if (!Pred.isScheduled) {
  101. // We found an available, but not scheduled, predecessor. If it's the
  102. // only one we have found, keep track of it... otherwise give up.
  103. if (OnlyAvailablePred && OnlyAvailablePred != &Pred)
  104. return 0;
  105. OnlyAvailablePred = &Pred;
  106. }
  107. }
  108. return OnlyAvailablePred;
  109. }
  110. void LatencyPriorityQueue::push_impl(SUnit *SU) {
  111. // Look at all of the successors of this node. Count the number of nodes that
  112. // this node is the sole unscheduled node for.
  113. unsigned NumNodesBlocking = 0;
  114. for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
  115. I != E; ++I)
  116. if (getSingleUnscheduledPred(I->getSUnit()) == SU)
  117. ++NumNodesBlocking;
  118. NumNodesSolelyBlocking[SU->NodeNum] = NumNodesBlocking;
  119. Queue.push(SU);
  120. }
  121. // ScheduledNode - As nodes are scheduled, we look to see if there are any
  122. // successor nodes that have a single unscheduled predecessor. If so, that
  123. // single predecessor has a higher priority, since scheduling it will make
  124. // the node available.
  125. void LatencyPriorityQueue::ScheduledNode(SUnit *SU) {
  126. for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
  127. I != E; ++I)
  128. AdjustPriorityOfUnscheduledPreds(I->getSUnit());
  129. }
  130. /// AdjustPriorityOfUnscheduledPreds - One of the predecessors of SU was just
  131. /// scheduled. If SU is not itself available, then there is at least one
  132. /// predecessor node that has not been scheduled yet. If SU has exactly ONE
  133. /// unscheduled predecessor, we want to increase its priority: it getting
  134. /// scheduled will make this node available, so it is better than some other
  135. /// node of the same priority that will not make a node available.
  136. void LatencyPriorityQueue::AdjustPriorityOfUnscheduledPreds(SUnit *SU) {
  137. if (SU->isAvailable) return; // All preds scheduled.
  138. SUnit *OnlyAvailablePred = getSingleUnscheduledPred(SU);
  139. if (OnlyAvailablePred == 0 || !OnlyAvailablePred->isAvailable) return;
  140. // Okay, we found a single predecessor that is available, but not scheduled.
  141. // Since it is available, it must be in the priority queue. First remove it.
  142. remove(OnlyAvailablePred);
  143. // Reinsert the node into the priority queue, which recomputes its
  144. // NumNodesSolelyBlocking value.
  145. push(OnlyAvailablePred);
  146. }