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