1f2fe9725SValery Pykhtin //===---------------------------- GCNILPSched.cpp - -----------------------===//
2f2fe9725SValery Pykhtin //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f2fe9725SValery Pykhtin //
7f2fe9725SValery Pykhtin //===----------------------------------------------------------------------===//
8f2fe9725SValery Pykhtin //
9f2fe9725SValery Pykhtin /// \file
10f2fe9725SValery Pykhtin //
11f2fe9725SValery Pykhtin //===----------------------------------------------------------------------===//
12f2fe9725SValery Pykhtin 
13f2fe9725SValery Pykhtin #include "llvm/CodeGen/ScheduleDAG.h"
14f2fe9725SValery Pykhtin 
15f2fe9725SValery Pykhtin using namespace llvm;
16f2fe9725SValery Pykhtin 
17f2fe9725SValery Pykhtin #define DEBUG_TYPE "machine-scheduler"
18f2fe9725SValery Pykhtin 
19f2fe9725SValery Pykhtin namespace {
20f2fe9725SValery Pykhtin 
21f2fe9725SValery Pykhtin class GCNILPScheduler {
22f2fe9725SValery Pykhtin   struct Candidate : ilist_node<Candidate> {
23f2fe9725SValery Pykhtin     SUnit *SU;
24f2fe9725SValery Pykhtin 
Candidate__anoned9f76670111::GCNILPScheduler::Candidate25f2fe9725SValery Pykhtin     Candidate(SUnit *SU_)
26f2fe9725SValery Pykhtin       : SU(SU_) {}
27f2fe9725SValery Pykhtin   };
28f2fe9725SValery Pykhtin 
29f2fe9725SValery Pykhtin   SpecificBumpPtrAllocator<Candidate> Alloc;
30f2fe9725SValery Pykhtin   typedef simple_ilist<Candidate> Queue;
31f2fe9725SValery Pykhtin   Queue PendingQueue;
32f2fe9725SValery Pykhtin   Queue AvailQueue;
33f2fe9725SValery Pykhtin   unsigned CurQueueId = 0;
34f2fe9725SValery Pykhtin 
35f2fe9725SValery Pykhtin   std::vector<unsigned> SUNumbers;
36f2fe9725SValery Pykhtin 
37f2fe9725SValery Pykhtin   /// CurCycle - The current scheduler state corresponds to this cycle.
38f2fe9725SValery Pykhtin   unsigned CurCycle = 0;
39f2fe9725SValery Pykhtin 
40f2fe9725SValery Pykhtin   unsigned getNodePriority(const SUnit *SU) const;
41f2fe9725SValery Pykhtin 
42f2fe9725SValery Pykhtin   const SUnit *pickBest(const SUnit *left, const SUnit *right);
43f2fe9725SValery Pykhtin   Candidate* pickCandidate();
44f2fe9725SValery Pykhtin 
45f2fe9725SValery Pykhtin   void releasePending();
46f2fe9725SValery Pykhtin   void advanceToCycle(unsigned NextCycle);
47f2fe9725SValery Pykhtin   void releasePredecessors(const SUnit* SU);
48f2fe9725SValery Pykhtin 
49f2fe9725SValery Pykhtin public:
50f2fe9725SValery Pykhtin   std::vector<const SUnit*> schedule(ArrayRef<const SUnit*> TopRoots,
51f2fe9725SValery Pykhtin                                      const ScheduleDAG &DAG);
52f2fe9725SValery Pykhtin };
53f2fe9725SValery Pykhtin } // namespace
54f2fe9725SValery Pykhtin 
55f2fe9725SValery Pykhtin /// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number.
56f2fe9725SValery Pykhtin /// Smaller number is the higher priority.
57f2fe9725SValery Pykhtin static unsigned
CalcNodeSethiUllmanNumber(const SUnit * SU,std::vector<unsigned> & SUNumbers)58f2fe9725SValery Pykhtin CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector<unsigned> &SUNumbers) {
59f2fe9725SValery Pykhtin   unsigned &SethiUllmanNumber = SUNumbers[SU->NodeNum];
60f2fe9725SValery Pykhtin   if (SethiUllmanNumber != 0)
61f2fe9725SValery Pykhtin     return SethiUllmanNumber;
62f2fe9725SValery Pykhtin 
63f2fe9725SValery Pykhtin   unsigned Extra = 0;
64f2fe9725SValery Pykhtin   for (const SDep &Pred : SU->Preds) {
65f2fe9725SValery Pykhtin     if (Pred.isCtrl()) continue;  // ignore chain preds
66f2fe9725SValery Pykhtin     SUnit *PredSU = Pred.getSUnit();
67f2fe9725SValery Pykhtin     unsigned PredSethiUllman = CalcNodeSethiUllmanNumber(PredSU, SUNumbers);
68f2fe9725SValery Pykhtin     if (PredSethiUllman > SethiUllmanNumber) {
69f2fe9725SValery Pykhtin       SethiUllmanNumber = PredSethiUllman;
70f2fe9725SValery Pykhtin       Extra = 0;
71f2fe9725SValery Pykhtin     }
72f2fe9725SValery Pykhtin     else if (PredSethiUllman == SethiUllmanNumber)
73f2fe9725SValery Pykhtin       ++Extra;
74f2fe9725SValery Pykhtin   }
75f2fe9725SValery Pykhtin 
76f2fe9725SValery Pykhtin   SethiUllmanNumber += Extra;
77f2fe9725SValery Pykhtin 
78f2fe9725SValery Pykhtin   if (SethiUllmanNumber == 0)
79f2fe9725SValery Pykhtin     SethiUllmanNumber = 1;
80f2fe9725SValery Pykhtin 
81f2fe9725SValery Pykhtin   return SethiUllmanNumber;
82f2fe9725SValery Pykhtin }
83f2fe9725SValery Pykhtin 
84f2fe9725SValery Pykhtin // Lower priority means schedule further down. For bottom-up scheduling, lower
85f2fe9725SValery Pykhtin // priority SUs are scheduled before higher priority SUs.
getNodePriority(const SUnit * SU) const86f2fe9725SValery Pykhtin unsigned GCNILPScheduler::getNodePriority(const SUnit *SU) const {
87f2fe9725SValery Pykhtin   assert(SU->NodeNum < SUNumbers.size());
88f2fe9725SValery Pykhtin   if (SU->NumSuccs == 0 && SU->NumPreds != 0)
89f2fe9725SValery Pykhtin     // If SU does not have a register use, i.e. it doesn't produce a value
90f2fe9725SValery Pykhtin     // that would be consumed (e.g. store), then it terminates a chain of
91f2fe9725SValery Pykhtin     // computation.  Give it a large SethiUllman number so it will be
92f2fe9725SValery Pykhtin     // scheduled right before its predecessors that it doesn't lengthen
93f2fe9725SValery Pykhtin     // their live ranges.
94f2fe9725SValery Pykhtin     return 0xffff;
95f2fe9725SValery Pykhtin 
96f2fe9725SValery Pykhtin   if (SU->NumPreds == 0 && SU->NumSuccs != 0)
97f2fe9725SValery Pykhtin     // If SU does not have a register def, schedule it close to its uses
98f2fe9725SValery Pykhtin     // because it does not lengthen any live ranges.
99f2fe9725SValery Pykhtin     return 0;
100f2fe9725SValery Pykhtin 
101f2fe9725SValery Pykhtin   return SUNumbers[SU->NodeNum];
102f2fe9725SValery Pykhtin }
103f2fe9725SValery Pykhtin 
104f2fe9725SValery Pykhtin /// closestSucc - Returns the scheduled cycle of the successor which is
105f2fe9725SValery Pykhtin /// closest to the current cycle.
closestSucc(const SUnit * SU)106f2fe9725SValery Pykhtin static unsigned closestSucc(const SUnit *SU) {
107f2fe9725SValery Pykhtin   unsigned MaxHeight = 0;
108f2fe9725SValery Pykhtin   for (const SDep &Succ : SU->Succs) {
109f2fe9725SValery Pykhtin     if (Succ.isCtrl()) continue;  // ignore chain succs
110f2fe9725SValery Pykhtin     unsigned Height = Succ.getSUnit()->getHeight();
111f2fe9725SValery Pykhtin     // If there are bunch of CopyToRegs stacked up, they should be considered
112f2fe9725SValery Pykhtin     // to be at the same position.
113f2fe9725SValery Pykhtin     if (Height > MaxHeight)
114f2fe9725SValery Pykhtin       MaxHeight = Height;
115f2fe9725SValery Pykhtin   }
116f2fe9725SValery Pykhtin   return MaxHeight;
117f2fe9725SValery Pykhtin }
118f2fe9725SValery Pykhtin 
119f2fe9725SValery Pykhtin /// calcMaxScratches - Returns an cost estimate of the worse case requirement
120f2fe9725SValery Pykhtin /// for scratch registers, i.e. number of data dependencies.
calcMaxScratches(const SUnit * SU)121f2fe9725SValery Pykhtin static unsigned calcMaxScratches(const SUnit *SU) {
122f2fe9725SValery Pykhtin   unsigned Scratches = 0;
123f2fe9725SValery Pykhtin   for (const SDep &Pred : SU->Preds) {
124f2fe9725SValery Pykhtin     if (Pred.isCtrl()) continue;  // ignore chain preds
125f2fe9725SValery Pykhtin     Scratches++;
126f2fe9725SValery Pykhtin   }
127f2fe9725SValery Pykhtin   return Scratches;
128f2fe9725SValery Pykhtin }
129f2fe9725SValery Pykhtin 
130f2fe9725SValery Pykhtin // Return -1 if left has higher priority, 1 if right has higher priority.
131f2fe9725SValery Pykhtin // Return 0 if latency-based priority is equivalent.
BUCompareLatency(const SUnit * left,const SUnit * right)132f2fe9725SValery Pykhtin static int BUCompareLatency(const SUnit *left, const SUnit *right) {
133f2fe9725SValery Pykhtin   // Scheduling an instruction that uses a VReg whose postincrement has not yet
134f2fe9725SValery Pykhtin   // been scheduled will induce a copy. Model this as an extra cycle of latency.
135f2fe9725SValery Pykhtin   int LHeight = (int)left->getHeight();
136f2fe9725SValery Pykhtin   int RHeight = (int)right->getHeight();
137f2fe9725SValery Pykhtin 
138f2fe9725SValery Pykhtin   // If either node is scheduling for latency, sort them by height/depth
139f2fe9725SValery Pykhtin   // and latency.
140f2fe9725SValery Pykhtin 
141f2fe9725SValery Pykhtin   // If neither instruction stalls (!LStall && !RStall) and HazardRecognizer
142f2fe9725SValery Pykhtin   // is enabled, grouping instructions by cycle, then its height is already
143f2fe9725SValery Pykhtin   // covered so only its depth matters. We also reach this point if both stall
144f2fe9725SValery Pykhtin   // but have the same height.
145f2fe9725SValery Pykhtin   if (LHeight != RHeight)
146f2fe9725SValery Pykhtin     return LHeight > RHeight ? 1 : -1;
147f2fe9725SValery Pykhtin 
148f2fe9725SValery Pykhtin   int LDepth = left->getDepth();
149f2fe9725SValery Pykhtin   int RDepth = right->getDepth();
150f2fe9725SValery Pykhtin   if (LDepth != RDepth) {
151d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "  Comparing latency of SU (" << left->NodeNum
152f2fe9725SValery Pykhtin                       << ") depth " << LDepth << " vs SU (" << right->NodeNum
153f2fe9725SValery Pykhtin                       << ") depth " << RDepth << "\n");
154f2fe9725SValery Pykhtin     return LDepth < RDepth ? 1 : -1;
155f2fe9725SValery Pykhtin   }
156f2fe9725SValery Pykhtin   if (left->Latency != right->Latency)
157f2fe9725SValery Pykhtin     return left->Latency > right->Latency ? 1 : -1;
158f2fe9725SValery Pykhtin 
159f2fe9725SValery Pykhtin   return 0;
160f2fe9725SValery Pykhtin }
161f2fe9725SValery Pykhtin 
pickBest(const SUnit * left,const SUnit * right)162f2fe9725SValery Pykhtin const SUnit *GCNILPScheduler::pickBest(const SUnit *left, const SUnit *right)
163f2fe9725SValery Pykhtin {
164f2fe9725SValery Pykhtin   // TODO: add register pressure lowering checks
165f2fe9725SValery Pykhtin 
166f2fe9725SValery Pykhtin   bool const DisableSchedCriticalPath = false;
167f2fe9725SValery Pykhtin   int MaxReorderWindow = 6;
168f2fe9725SValery Pykhtin   if (!DisableSchedCriticalPath) {
169f2fe9725SValery Pykhtin     int spread = (int)left->getDepth() - (int)right->getDepth();
170f2fe9725SValery Pykhtin     if (std::abs(spread) > MaxReorderWindow) {
171d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "Depth of SU(" << left->NodeNum << "): "
172d34e60caSNicola Zaghen                         << left->getDepth() << " != SU(" << right->NodeNum
173d34e60caSNicola Zaghen                         << "): " << right->getDepth() << "\n");
174f2fe9725SValery Pykhtin       return left->getDepth() < right->getDepth() ? right : left;
175f2fe9725SValery Pykhtin     }
176f2fe9725SValery Pykhtin   }
177f2fe9725SValery Pykhtin 
178f2fe9725SValery Pykhtin   bool const DisableSchedHeight = false;
179f2fe9725SValery Pykhtin   if (!DisableSchedHeight && left->getHeight() != right->getHeight()) {
180f2fe9725SValery Pykhtin     int spread = (int)left->getHeight() - (int)right->getHeight();
181f2fe9725SValery Pykhtin     if (std::abs(spread) > MaxReorderWindow)
182f2fe9725SValery Pykhtin       return left->getHeight() > right->getHeight() ? right : left;
183f2fe9725SValery Pykhtin   }
184f2fe9725SValery Pykhtin 
185f2fe9725SValery Pykhtin   // Prioritize by Sethi-Ulmann number and push CopyToReg nodes down.
186f2fe9725SValery Pykhtin   unsigned LPriority = getNodePriority(left);
187f2fe9725SValery Pykhtin   unsigned RPriority = getNodePriority(right);
188f2fe9725SValery Pykhtin 
189f2fe9725SValery Pykhtin   if (LPriority != RPriority)
190f2fe9725SValery Pykhtin     return LPriority > RPriority ? right : left;
191f2fe9725SValery Pykhtin 
192f2fe9725SValery Pykhtin   // Try schedule def + use closer when Sethi-Ullman numbers are the same.
193f2fe9725SValery Pykhtin   // e.g.
194f2fe9725SValery Pykhtin   // t1 = op t2, c1
195f2fe9725SValery Pykhtin   // t3 = op t4, c2
196f2fe9725SValery Pykhtin   //
197f2fe9725SValery Pykhtin   // and the following instructions are both ready.
198f2fe9725SValery Pykhtin   // t2 = op c3
199f2fe9725SValery Pykhtin   // t4 = op c4
200f2fe9725SValery Pykhtin   //
201f2fe9725SValery Pykhtin   // Then schedule t2 = op first.
202f2fe9725SValery Pykhtin   // i.e.
203f2fe9725SValery Pykhtin   // t4 = op c4
204f2fe9725SValery Pykhtin   // t2 = op c3
205f2fe9725SValery Pykhtin   // t1 = op t2, c1
206f2fe9725SValery Pykhtin   // t3 = op t4, c2
207f2fe9725SValery Pykhtin   //
208f2fe9725SValery Pykhtin   // This creates more short live intervals.
209f2fe9725SValery Pykhtin   unsigned LDist = closestSucc(left);
210f2fe9725SValery Pykhtin   unsigned RDist = closestSucc(right);
211f2fe9725SValery Pykhtin   if (LDist != RDist)
212f2fe9725SValery Pykhtin     return LDist < RDist ? right : left;
213f2fe9725SValery Pykhtin 
214f2fe9725SValery Pykhtin   // How many registers becomes live when the node is scheduled.
215f2fe9725SValery Pykhtin   unsigned LScratch = calcMaxScratches(left);
216f2fe9725SValery Pykhtin   unsigned RScratch = calcMaxScratches(right);
217f2fe9725SValery Pykhtin   if (LScratch != RScratch)
218f2fe9725SValery Pykhtin     return LScratch > RScratch ? right : left;
219f2fe9725SValery Pykhtin 
220f2fe9725SValery Pykhtin   bool const DisableSchedCycles = false;
221f2fe9725SValery Pykhtin   if (!DisableSchedCycles) {
222f2fe9725SValery Pykhtin     int result = BUCompareLatency(left, right);
223f2fe9725SValery Pykhtin     if (result != 0)
224f2fe9725SValery Pykhtin       return result > 0 ? right : left;
225f2fe9725SValery Pykhtin     return left;
226f2fe9725SValery Pykhtin   }
227f2fe9725SValery Pykhtin   else {
228f2fe9725SValery Pykhtin     if (left->getHeight() != right->getHeight())
229f2fe9725SValery Pykhtin       return (left->getHeight() > right->getHeight()) ? right : left;
230f2fe9725SValery Pykhtin 
231f2fe9725SValery Pykhtin     if (left->getDepth() != right->getDepth())
232f2fe9725SValery Pykhtin       return (left->getDepth() < right->getDepth()) ? right : left;
233f2fe9725SValery Pykhtin   }
234f2fe9725SValery Pykhtin 
235f2fe9725SValery Pykhtin   assert(left->NodeQueueId && right->NodeQueueId &&
236f2fe9725SValery Pykhtin         "NodeQueueId cannot be zero");
237f2fe9725SValery Pykhtin   return (left->NodeQueueId > right->NodeQueueId) ? right : left;
238f2fe9725SValery Pykhtin }
239f2fe9725SValery Pykhtin 
pickCandidate()240f2fe9725SValery Pykhtin GCNILPScheduler::Candidate* GCNILPScheduler::pickCandidate() {
241f2fe9725SValery Pykhtin   if (AvailQueue.empty())
242f2fe9725SValery Pykhtin     return nullptr;
243f2fe9725SValery Pykhtin   auto Best = AvailQueue.begin();
244f2fe9725SValery Pykhtin   for (auto I = std::next(AvailQueue.begin()), E = AvailQueue.end(); I != E; ++I) {
245f2fe9725SValery Pykhtin     auto NewBestSU = pickBest(Best->SU, I->SU);
246f2fe9725SValery Pykhtin     if (NewBestSU != Best->SU) {
247f2fe9725SValery Pykhtin       assert(NewBestSU == I->SU);
248f2fe9725SValery Pykhtin       Best = I;
249f2fe9725SValery Pykhtin     }
250f2fe9725SValery Pykhtin   }
251f2fe9725SValery Pykhtin   return &*Best;
252f2fe9725SValery Pykhtin }
253f2fe9725SValery Pykhtin 
releasePending()254f2fe9725SValery Pykhtin void GCNILPScheduler::releasePending() {
255f2fe9725SValery Pykhtin   // Check to see if any of the pending instructions are ready to issue.  If
256f2fe9725SValery Pykhtin   // so, add them to the available queue.
257f2fe9725SValery Pykhtin   for(auto I = PendingQueue.begin(), E = PendingQueue.end(); I != E;) {
258f2fe9725SValery Pykhtin     auto &C = *I++;
259f2fe9725SValery Pykhtin     if (C.SU->getHeight() <= CurCycle) {
260f2fe9725SValery Pykhtin       PendingQueue.remove(C);
261f2fe9725SValery Pykhtin       AvailQueue.push_back(C);
262f2fe9725SValery Pykhtin       C.SU->NodeQueueId = CurQueueId++;
263f2fe9725SValery Pykhtin     }
264f2fe9725SValery Pykhtin   }
265f2fe9725SValery Pykhtin }
266f2fe9725SValery Pykhtin 
267f2fe9725SValery Pykhtin /// Move the scheduler state forward by the specified number of Cycles.
advanceToCycle(unsigned NextCycle)268f2fe9725SValery Pykhtin void GCNILPScheduler::advanceToCycle(unsigned NextCycle) {
269f2fe9725SValery Pykhtin   if (NextCycle <= CurCycle)
270f2fe9725SValery Pykhtin     return;
271f2fe9725SValery Pykhtin   CurCycle = NextCycle;
272f2fe9725SValery Pykhtin   releasePending();
273f2fe9725SValery Pykhtin }
274f2fe9725SValery Pykhtin 
releasePredecessors(const SUnit * SU)275f2fe9725SValery Pykhtin void GCNILPScheduler::releasePredecessors(const SUnit* SU) {
276f2fe9725SValery Pykhtin   for (const auto &PredEdge : SU->Preds) {
277f2fe9725SValery Pykhtin     auto PredSU = PredEdge.getSUnit();
278f2fe9725SValery Pykhtin     if (PredEdge.isWeak())
279f2fe9725SValery Pykhtin       continue;
280f2fe9725SValery Pykhtin     assert(PredSU->isBoundaryNode() || PredSU->NumSuccsLeft > 0);
281f2fe9725SValery Pykhtin 
282f2fe9725SValery Pykhtin     PredSU->setHeightToAtLeast(SU->getHeight() + PredEdge.getLatency());
283f2fe9725SValery Pykhtin 
284f2fe9725SValery Pykhtin     if (!PredSU->isBoundaryNode() && --PredSU->NumSuccsLeft == 0)
285f2fe9725SValery Pykhtin       PendingQueue.push_front(*new (Alloc.Allocate()) Candidate(PredSU));
286f2fe9725SValery Pykhtin   }
287f2fe9725SValery Pykhtin }
288f2fe9725SValery Pykhtin 
289f2fe9725SValery Pykhtin std::vector<const SUnit*>
schedule(ArrayRef<const SUnit * > BotRoots,const ScheduleDAG & DAG)290f2fe9725SValery Pykhtin GCNILPScheduler::schedule(ArrayRef<const SUnit*> BotRoots,
291f2fe9725SValery Pykhtin                           const ScheduleDAG &DAG) {
292f2fe9725SValery Pykhtin   auto &SUnits = const_cast<ScheduleDAG&>(DAG).SUnits;
293f2fe9725SValery Pykhtin 
294f2fe9725SValery Pykhtin   std::vector<SUnit> SUSavedCopy;
295f2fe9725SValery Pykhtin   SUSavedCopy.resize(SUnits.size());
296f2fe9725SValery Pykhtin 
297f2fe9725SValery Pykhtin   // we cannot save only those fields we touch: some of them are private
298f2fe9725SValery Pykhtin   // so save units verbatim: this assumes SUnit should have value semantics
299f2fe9725SValery Pykhtin   for (const SUnit &SU : SUnits)
300f2fe9725SValery Pykhtin     SUSavedCopy[SU.NodeNum] = SU;
301f2fe9725SValery Pykhtin 
302f2fe9725SValery Pykhtin   SUNumbers.assign(SUnits.size(), 0);
303f2fe9725SValery Pykhtin   for (const SUnit &SU : SUnits)
304f2fe9725SValery Pykhtin     CalcNodeSethiUllmanNumber(&SU, SUNumbers);
305f2fe9725SValery Pykhtin 
306f2fe9725SValery Pykhtin   for (auto SU : BotRoots) {
307f2fe9725SValery Pykhtin     AvailQueue.push_back(
308f2fe9725SValery Pykhtin       *new (Alloc.Allocate()) Candidate(const_cast<SUnit*>(SU)));
309f2fe9725SValery Pykhtin   }
310f2fe9725SValery Pykhtin   releasePredecessors(&DAG.ExitSU);
311f2fe9725SValery Pykhtin 
312f2fe9725SValery Pykhtin   std::vector<const SUnit*> Schedule;
313f2fe9725SValery Pykhtin   Schedule.reserve(SUnits.size());
314f2fe9725SValery Pykhtin   while (true) {
315f2fe9725SValery Pykhtin     if (AvailQueue.empty() && !PendingQueue.empty()) {
316f2fe9725SValery Pykhtin       auto EarliestSU = std::min_element(
317f2fe9725SValery Pykhtin         PendingQueue.begin(), PendingQueue.end(),
318f2fe9725SValery Pykhtin         [=](const Candidate& C1, const Candidate& C2) {
319f2fe9725SValery Pykhtin         return C1.SU->getHeight() < C2.SU->getHeight();
320f2fe9725SValery Pykhtin       })->SU;
321f2fe9725SValery Pykhtin       advanceToCycle(std::max(CurCycle + 1, EarliestSU->getHeight()));
322f2fe9725SValery Pykhtin     }
323f2fe9725SValery Pykhtin     if (AvailQueue.empty())
324f2fe9725SValery Pykhtin       break;
325f2fe9725SValery Pykhtin 
326d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "\n=== Picking candidate\n"
327f2fe9725SValery Pykhtin                          "Ready queue:";
328d34e60caSNicola Zaghen                for (auto &C
329d34e60caSNicola Zaghen                     : AvailQueue) dbgs()
330d34e60caSNicola Zaghen                << ' ' << C.SU->NodeNum;
331d34e60caSNicola Zaghen                dbgs() << '\n';);
332f2fe9725SValery Pykhtin 
333f2fe9725SValery Pykhtin     auto C = pickCandidate();
334f2fe9725SValery Pykhtin     assert(C);
335f2fe9725SValery Pykhtin     AvailQueue.remove(*C);
336f2fe9725SValery Pykhtin     auto SU = C->SU;
337726e12cfSMatthias Braun     LLVM_DEBUG(dbgs() << "Selected "; DAG.dumpNode(*SU));
338f2fe9725SValery Pykhtin 
339f2fe9725SValery Pykhtin     advanceToCycle(SU->getHeight());
340f2fe9725SValery Pykhtin 
341f2fe9725SValery Pykhtin     releasePredecessors(SU);
342f2fe9725SValery Pykhtin     Schedule.push_back(SU);
343f2fe9725SValery Pykhtin     SU->isScheduled = true;
344f2fe9725SValery Pykhtin   }
345f2fe9725SValery Pykhtin   assert(SUnits.size() == Schedule.size());
346f2fe9725SValery Pykhtin 
347f2fe9725SValery Pykhtin   std::reverse(Schedule.begin(), Schedule.end());
348f2fe9725SValery Pykhtin 
349f2fe9725SValery Pykhtin   // restore units
350f2fe9725SValery Pykhtin   for (auto &SU : SUnits)
351f2fe9725SValery Pykhtin     SU = SUSavedCopy[SU.NodeNum];
352f2fe9725SValery Pykhtin 
353f2fe9725SValery Pykhtin   return Schedule;
354f2fe9725SValery Pykhtin }
355f2fe9725SValery Pykhtin 
356f2fe9725SValery Pykhtin namespace llvm {
makeGCNILPScheduler(ArrayRef<const SUnit * > BotRoots,const ScheduleDAG & DAG)357f2fe9725SValery Pykhtin std::vector<const SUnit*> makeGCNILPScheduler(ArrayRef<const SUnit*> BotRoots,
358f2fe9725SValery Pykhtin                                               const ScheduleDAG &DAG) {
359f2fe9725SValery Pykhtin   GCNILPScheduler S;
360f2fe9725SValery Pykhtin   return S.schedule(BotRoots, DAG);
361f2fe9725SValery Pykhtin }
362f2fe9725SValery Pykhtin }
363