1cc3bb855SJames Nagurne //===- VLIWMachineScheduler.cpp - VLIW-Focused Scheduling Pass ------------===//
2cc3bb855SJames Nagurne //
3cc3bb855SJames Nagurne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4cc3bb855SJames Nagurne // See https://llvm.org/LICENSE.txt for license information.
5cc3bb855SJames Nagurne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cc3bb855SJames Nagurne //
7cc3bb855SJames Nagurne //===----------------------------------------------------------------------===//
8cc3bb855SJames Nagurne //
9cc3bb855SJames Nagurne // MachineScheduler schedules machine instructions after phi elimination. It
10cc3bb855SJames Nagurne // preserves LiveIntervals so it can be invoked before register allocation.
11cc3bb855SJames Nagurne //
12cc3bb855SJames Nagurne //===----------------------------------------------------------------------===//
13cc3bb855SJames Nagurne
14cc3bb855SJames Nagurne #include "llvm/CodeGen/VLIWMachineScheduler.h"
15cc3bb855SJames Nagurne #include "llvm/ADT/SmallVector.h"
16cc3bb855SJames Nagurne #include "llvm/CodeGen/DFAPacketizer.h"
17cc3bb855SJames Nagurne #include "llvm/CodeGen/MachineBasicBlock.h"
18cc3bb855SJames Nagurne #include "llvm/CodeGen/MachineFunction.h"
19cc3bb855SJames Nagurne #include "llvm/CodeGen/MachineInstr.h"
20cc3bb855SJames Nagurne #include "llvm/CodeGen/MachineLoopInfo.h"
21cc3bb855SJames Nagurne #include "llvm/CodeGen/RegisterClassInfo.h"
22cc3bb855SJames Nagurne #include "llvm/CodeGen/RegisterPressure.h"
23cc3bb855SJames Nagurne #include "llvm/CodeGen/ScheduleDAG.h"
24cc3bb855SJames Nagurne #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
25cc3bb855SJames Nagurne #include "llvm/CodeGen/TargetInstrInfo.h"
26cc3bb855SJames Nagurne #include "llvm/CodeGen/TargetOpcodes.h"
27cc3bb855SJames Nagurne #include "llvm/CodeGen/TargetRegisterInfo.h"
28cc3bb855SJames Nagurne #include "llvm/CodeGen/TargetSchedule.h"
29cc3bb855SJames Nagurne #include "llvm/CodeGen/TargetSubtargetInfo.h"
30cc3bb855SJames Nagurne #include "llvm/Support/CommandLine.h"
31cc3bb855SJames Nagurne #include "llvm/Support/Debug.h"
32cc3bb855SJames Nagurne #include "llvm/Support/raw_ostream.h"
33cc3bb855SJames Nagurne #include <algorithm>
34cc3bb855SJames Nagurne #include <cassert>
35cc3bb855SJames Nagurne #include <iomanip>
36cc3bb855SJames Nagurne #include <limits>
37cc3bb855SJames Nagurne #include <memory>
38cc3bb855SJames Nagurne #include <sstream>
39cc3bb855SJames Nagurne
40cc3bb855SJames Nagurne using namespace llvm;
41cc3bb855SJames Nagurne
42cc3bb855SJames Nagurne #define DEBUG_TYPE "machine-scheduler"
43cc3bb855SJames Nagurne
44cc3bb855SJames Nagurne static cl::opt<bool> IgnoreBBRegPressure("ignore-bb-reg-pressure", cl::Hidden,
45d86a206fSFangrui Song cl::init(false));
46cc3bb855SJames Nagurne
47cc3bb855SJames Nagurne static cl::opt<bool> UseNewerCandidate("use-newer-candidate", cl::Hidden,
4895a13425SFangrui Song cl::init(true));
49cc3bb855SJames Nagurne
50cc3bb855SJames Nagurne static cl::opt<unsigned> SchedDebugVerboseLevel("misched-verbose-level",
51557efc9aSFangrui Song cl::Hidden, cl::init(1));
52cc3bb855SJames Nagurne
53cc3bb855SJames Nagurne // Check if the scheduler should penalize instructions that are available to
54cc3bb855SJames Nagurne // early due to a zero-latency dependence.
55cc3bb855SJames Nagurne static cl::opt<bool> CheckEarlyAvail("check-early-avail", cl::Hidden,
56d86a206fSFangrui Song cl::init(true));
57cc3bb855SJames Nagurne
58cc3bb855SJames Nagurne // This value is used to determine if a register class is a high pressure set.
59cc3bb855SJames Nagurne // We compute the maximum number of registers needed and divided by the total
60cc3bb855SJames Nagurne // available. Then, we compare the result to this value.
61cc3bb855SJames Nagurne static cl::opt<float> RPThreshold("vliw-misched-reg-pressure", cl::Hidden,
62cc3bb855SJames Nagurne cl::init(0.75f),
63cc3bb855SJames Nagurne cl::desc("High register pressure threhold."));
64cc3bb855SJames Nagurne
VLIWResourceModel(const TargetSubtargetInfo & STI,const TargetSchedModel * SM)65cc3bb855SJames Nagurne VLIWResourceModel::VLIWResourceModel(const TargetSubtargetInfo &STI,
66cc3bb855SJames Nagurne const TargetSchedModel *SM)
67cc3bb855SJames Nagurne : TII(STI.getInstrInfo()), SchedModel(SM) {
68cc3bb855SJames Nagurne ResourcesModel = createPacketizer(STI);
69cc3bb855SJames Nagurne
70cc3bb855SJames Nagurne // This hard requirement could be relaxed,
71cc3bb855SJames Nagurne // but for now do not let it proceed.
72cc3bb855SJames Nagurne assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
73cc3bb855SJames Nagurne
74cc3bb855SJames Nagurne Packet.reserve(SchedModel->getIssueWidth());
75cc3bb855SJames Nagurne Packet.clear();
76cc3bb855SJames Nagurne ResourcesModel->clearResources();
77cc3bb855SJames Nagurne }
78cc3bb855SJames Nagurne
reset()79cc3bb855SJames Nagurne void VLIWResourceModel::reset() {
80cc3bb855SJames Nagurne Packet.clear();
81cc3bb855SJames Nagurne ResourcesModel->clearResources();
82cc3bb855SJames Nagurne }
83cc3bb855SJames Nagurne
~VLIWResourceModel()84cc3bb855SJames Nagurne VLIWResourceModel::~VLIWResourceModel() { delete ResourcesModel; }
85cc3bb855SJames Nagurne
86cc3bb855SJames Nagurne /// Return true if there is a dependence between SUd and SUu.
hasDependence(const SUnit * SUd,const SUnit * SUu)87cc3bb855SJames Nagurne bool VLIWResourceModel::hasDependence(const SUnit *SUd, const SUnit *SUu) {
88cc3bb855SJames Nagurne if (SUd->Succs.size() == 0)
89cc3bb855SJames Nagurne return false;
90cc3bb855SJames Nagurne
91cc3bb855SJames Nagurne for (const auto &S : SUd->Succs) {
92cc3bb855SJames Nagurne // Since we do not add pseudos to packets, might as well
93cc3bb855SJames Nagurne // ignore order dependencies.
94cc3bb855SJames Nagurne if (S.isCtrl())
95cc3bb855SJames Nagurne continue;
96cc3bb855SJames Nagurne
97cc3bb855SJames Nagurne if (S.getSUnit() == SUu && S.getLatency() > 0)
98cc3bb855SJames Nagurne return true;
99cc3bb855SJames Nagurne }
100cc3bb855SJames Nagurne return false;
101cc3bb855SJames Nagurne }
102cc3bb855SJames Nagurne
103cc3bb855SJames Nagurne /// Check if scheduling of this SU is possible
104cc3bb855SJames Nagurne /// in the current packet.
105cc3bb855SJames Nagurne /// It is _not_ precise (statefull), it is more like
106cc3bb855SJames Nagurne /// another heuristic. Many corner cases are figured
107cc3bb855SJames Nagurne /// empirically.
isResourceAvailable(SUnit * SU,bool IsTop)108cc3bb855SJames Nagurne bool VLIWResourceModel::isResourceAvailable(SUnit *SU, bool IsTop) {
109cc3bb855SJames Nagurne if (!SU || !SU->getInstr())
110cc3bb855SJames Nagurne return false;
111cc3bb855SJames Nagurne
112cc3bb855SJames Nagurne // First see if the pipeline could receive this instruction
113cc3bb855SJames Nagurne // in the current cycle.
114cc3bb855SJames Nagurne switch (SU->getInstr()->getOpcode()) {
115cc3bb855SJames Nagurne default:
116cc3bb855SJames Nagurne if (!ResourcesModel->canReserveResources(*SU->getInstr()))
117cc3bb855SJames Nagurne return false;
118cc3bb855SJames Nagurne break;
119cc3bb855SJames Nagurne case TargetOpcode::EXTRACT_SUBREG:
120cc3bb855SJames Nagurne case TargetOpcode::INSERT_SUBREG:
121cc3bb855SJames Nagurne case TargetOpcode::SUBREG_TO_REG:
122cc3bb855SJames Nagurne case TargetOpcode::REG_SEQUENCE:
123cc3bb855SJames Nagurne case TargetOpcode::IMPLICIT_DEF:
124cc3bb855SJames Nagurne case TargetOpcode::COPY:
125cc3bb855SJames Nagurne case TargetOpcode::INLINEASM:
126cc3bb855SJames Nagurne case TargetOpcode::INLINEASM_BR:
127cc3bb855SJames Nagurne break;
128cc3bb855SJames Nagurne }
129cc3bb855SJames Nagurne
130cc3bb855SJames Nagurne // Now see if there are no other dependencies to instructions already
131cc3bb855SJames Nagurne // in the packet.
132cc3bb855SJames Nagurne if (IsTop) {
133cc3bb855SJames Nagurne for (unsigned i = 0, e = Packet.size(); i != e; ++i)
134cc3bb855SJames Nagurne if (hasDependence(Packet[i], SU))
135cc3bb855SJames Nagurne return false;
136cc3bb855SJames Nagurne } else {
137cc3bb855SJames Nagurne for (unsigned i = 0, e = Packet.size(); i != e; ++i)
138cc3bb855SJames Nagurne if (hasDependence(SU, Packet[i]))
139cc3bb855SJames Nagurne return false;
140cc3bb855SJames Nagurne }
141cc3bb855SJames Nagurne return true;
142cc3bb855SJames Nagurne }
143cc3bb855SJames Nagurne
144cc3bb855SJames Nagurne /// Keep track of available resources.
reserveResources(SUnit * SU,bool IsTop)145cc3bb855SJames Nagurne bool VLIWResourceModel::reserveResources(SUnit *SU, bool IsTop) {
146cc3bb855SJames Nagurne bool startNewCycle = false;
147cc3bb855SJames Nagurne // Artificially reset state.
148cc3bb855SJames Nagurne if (!SU) {
149cc3bb855SJames Nagurne reset();
150cc3bb855SJames Nagurne TotalPackets++;
151cc3bb855SJames Nagurne return false;
152cc3bb855SJames Nagurne }
153cc3bb855SJames Nagurne // If this SU does not fit in the packet or the packet is now full
154cc3bb855SJames Nagurne // start a new one.
155cc3bb855SJames Nagurne if (!isResourceAvailable(SU, IsTop) ||
156cc3bb855SJames Nagurne Packet.size() >= SchedModel->getIssueWidth()) {
157cc3bb855SJames Nagurne reset();
158cc3bb855SJames Nagurne TotalPackets++;
159cc3bb855SJames Nagurne startNewCycle = true;
160cc3bb855SJames Nagurne }
161cc3bb855SJames Nagurne
162cc3bb855SJames Nagurne switch (SU->getInstr()->getOpcode()) {
163cc3bb855SJames Nagurne default:
164cc3bb855SJames Nagurne ResourcesModel->reserveResources(*SU->getInstr());
165cc3bb855SJames Nagurne break;
166cc3bb855SJames Nagurne case TargetOpcode::EXTRACT_SUBREG:
167cc3bb855SJames Nagurne case TargetOpcode::INSERT_SUBREG:
168cc3bb855SJames Nagurne case TargetOpcode::SUBREG_TO_REG:
169cc3bb855SJames Nagurne case TargetOpcode::REG_SEQUENCE:
170cc3bb855SJames Nagurne case TargetOpcode::IMPLICIT_DEF:
171cc3bb855SJames Nagurne case TargetOpcode::KILL:
172cc3bb855SJames Nagurne case TargetOpcode::CFI_INSTRUCTION:
173cc3bb855SJames Nagurne case TargetOpcode::EH_LABEL:
174cc3bb855SJames Nagurne case TargetOpcode::COPY:
175cc3bb855SJames Nagurne case TargetOpcode::INLINEASM:
176cc3bb855SJames Nagurne case TargetOpcode::INLINEASM_BR:
177cc3bb855SJames Nagurne break;
178cc3bb855SJames Nagurne }
179cc3bb855SJames Nagurne Packet.push_back(SU);
180cc3bb855SJames Nagurne
181cc3bb855SJames Nagurne #ifndef NDEBUG
182cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "Packet[" << TotalPackets << "]:\n");
183cc3bb855SJames Nagurne for (unsigned i = 0, e = Packet.size(); i != e; ++i) {
184cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "\t[" << i << "] SU(");
185cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << Packet[i]->NodeNum << ")\t");
186cc3bb855SJames Nagurne LLVM_DEBUG(Packet[i]->getInstr()->dump());
187cc3bb855SJames Nagurne }
188cc3bb855SJames Nagurne #endif
189cc3bb855SJames Nagurne
190cc3bb855SJames Nagurne return startNewCycle;
191cc3bb855SJames Nagurne }
192cc3bb855SJames Nagurne
193cc3bb855SJames Nagurne DFAPacketizer *
createPacketizer(const TargetSubtargetInfo & STI) const194cc3bb855SJames Nagurne VLIWResourceModel::createPacketizer(const TargetSubtargetInfo &STI) const {
195cc3bb855SJames Nagurne return STI.getInstrInfo()->CreateTargetScheduleState(STI);
196cc3bb855SJames Nagurne }
197cc3bb855SJames Nagurne
198cc3bb855SJames Nagurne /// schedule - Called back from MachineScheduler::runOnMachineFunction
199cc3bb855SJames Nagurne /// after setting up the current scheduling region. [RegionBegin, RegionEnd)
200cc3bb855SJames Nagurne /// only includes instructions that have DAG nodes, not scheduling boundaries.
schedule()201cc3bb855SJames Nagurne void VLIWMachineScheduler::schedule() {
202cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "********** MI Converging Scheduling VLIW "
203cc3bb855SJames Nagurne << printMBBReference(*BB) << " " << BB->getName()
204cc3bb855SJames Nagurne << " in_func " << BB->getParent()->getName()
205cc3bb855SJames Nagurne << " at loop depth " << MLI->getLoopDepth(BB) << " \n");
206cc3bb855SJames Nagurne
207cc3bb855SJames Nagurne buildDAGWithRegPressure();
208cc3bb855SJames Nagurne
209cc3bb855SJames Nagurne Topo.InitDAGTopologicalSorting();
210cc3bb855SJames Nagurne
211cc3bb855SJames Nagurne // Postprocess the DAG to add platform-specific artificial dependencies.
212cc3bb855SJames Nagurne postprocessDAG();
213cc3bb855SJames Nagurne
214cc3bb855SJames Nagurne SmallVector<SUnit *, 8> TopRoots, BotRoots;
215cc3bb855SJames Nagurne findRootsAndBiasEdges(TopRoots, BotRoots);
216cc3bb855SJames Nagurne
217cc3bb855SJames Nagurne // Initialize the strategy before modifying the DAG.
218cc3bb855SJames Nagurne SchedImpl->initialize(this);
219cc3bb855SJames Nagurne
22067aeae01SKazu Hirata LLVM_DEBUG({
22167aeae01SKazu Hirata unsigned maxH = 0;
22267aeae01SKazu Hirata for (const SUnit &SU : SUnits)
22367aeae01SKazu Hirata if (SU.getHeight() > maxH)
22467aeae01SKazu Hirata maxH = SU.getHeight();
22567aeae01SKazu Hirata dbgs() << "Max Height " << maxH << "\n";
22667aeae01SKazu Hirata });
22767aeae01SKazu Hirata LLVM_DEBUG({
22867aeae01SKazu Hirata unsigned maxD = 0;
22967aeae01SKazu Hirata for (const SUnit &SU : SUnits)
23067aeae01SKazu Hirata if (SU.getDepth() > maxD)
23167aeae01SKazu Hirata maxD = SU.getDepth();
23267aeae01SKazu Hirata dbgs() << "Max Depth " << maxD << "\n";
23367aeae01SKazu Hirata });
234cc3bb855SJames Nagurne LLVM_DEBUG(dump());
235cc3bb855SJames Nagurne if (ViewMISchedDAGs)
236cc3bb855SJames Nagurne viewGraph();
237cc3bb855SJames Nagurne
238cc3bb855SJames Nagurne initQueues(TopRoots, BotRoots);
239cc3bb855SJames Nagurne
240cc3bb855SJames Nagurne bool IsTopNode = false;
241cc3bb855SJames Nagurne while (true) {
242cc3bb855SJames Nagurne LLVM_DEBUG(
243cc3bb855SJames Nagurne dbgs() << "** VLIWMachineScheduler::schedule picking next node\n");
244cc3bb855SJames Nagurne SUnit *SU = SchedImpl->pickNode(IsTopNode);
245cc3bb855SJames Nagurne if (!SU)
246cc3bb855SJames Nagurne break;
247cc3bb855SJames Nagurne
248cc3bb855SJames Nagurne if (!checkSchedLimit())
249cc3bb855SJames Nagurne break;
250cc3bb855SJames Nagurne
251cc3bb855SJames Nagurne scheduleMI(SU, IsTopNode);
252cc3bb855SJames Nagurne
253cc3bb855SJames Nagurne // Notify the scheduling strategy after updating the DAG.
254cc3bb855SJames Nagurne SchedImpl->schedNode(SU, IsTopNode);
255cc3bb855SJames Nagurne
256cc3bb855SJames Nagurne updateQueues(SU, IsTopNode);
257cc3bb855SJames Nagurne }
258cc3bb855SJames Nagurne assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
259cc3bb855SJames Nagurne
260cc3bb855SJames Nagurne placeDebugValues();
261cc3bb855SJames Nagurne
262cc3bb855SJames Nagurne LLVM_DEBUG({
263cc3bb855SJames Nagurne dbgs() << "*** Final schedule for "
264cc3bb855SJames Nagurne << printMBBReference(*begin()->getParent()) << " ***\n";
265cc3bb855SJames Nagurne dumpSchedule();
266cc3bb855SJames Nagurne dbgs() << '\n';
267cc3bb855SJames Nagurne });
268cc3bb855SJames Nagurne }
269cc3bb855SJames Nagurne
initialize(ScheduleDAGMI * dag)270cc3bb855SJames Nagurne void ConvergingVLIWScheduler::initialize(ScheduleDAGMI *dag) {
271cc3bb855SJames Nagurne DAG = static_cast<VLIWMachineScheduler *>(dag);
272cc3bb855SJames Nagurne SchedModel = DAG->getSchedModel();
273cc3bb855SJames Nagurne
274cc3bb855SJames Nagurne Top.init(DAG, SchedModel);
275cc3bb855SJames Nagurne Bot.init(DAG, SchedModel);
276cc3bb855SJames Nagurne
277cc3bb855SJames Nagurne // Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
278cc3bb855SJames Nagurne // are disabled, then these HazardRecs will be disabled.
279cc3bb855SJames Nagurne const InstrItineraryData *Itin = DAG->getSchedModel()->getInstrItineraries();
280cc3bb855SJames Nagurne const TargetSubtargetInfo &STI = DAG->MF.getSubtarget();
281cc3bb855SJames Nagurne const TargetInstrInfo *TII = STI.getInstrInfo();
282cc3bb855SJames Nagurne delete Top.HazardRec;
283cc3bb855SJames Nagurne delete Bot.HazardRec;
284cc3bb855SJames Nagurne Top.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG);
285cc3bb855SJames Nagurne Bot.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG);
286cc3bb855SJames Nagurne
287cc3bb855SJames Nagurne delete Top.ResourceModel;
288cc3bb855SJames Nagurne delete Bot.ResourceModel;
289cc3bb855SJames Nagurne Top.ResourceModel = createVLIWResourceModel(STI, DAG->getSchedModel());
290cc3bb855SJames Nagurne Bot.ResourceModel = createVLIWResourceModel(STI, DAG->getSchedModel());
291cc3bb855SJames Nagurne
292cc3bb855SJames Nagurne const std::vector<unsigned> &MaxPressure =
293cc3bb855SJames Nagurne DAG->getRegPressure().MaxSetPressure;
2942aed0813SKazu Hirata HighPressureSets.assign(MaxPressure.size(), false);
295cc3bb855SJames Nagurne for (unsigned i = 0, e = MaxPressure.size(); i < e; ++i) {
296cc3bb855SJames Nagurne unsigned Limit = DAG->getRegClassInfo()->getRegPressureSetLimit(i);
297cc3bb855SJames Nagurne HighPressureSets[i] =
298cc3bb855SJames Nagurne ((float)MaxPressure[i] > ((float)Limit * RPThreshold));
299cc3bb855SJames Nagurne }
300cc3bb855SJames Nagurne
301cc3bb855SJames Nagurne assert((!ForceTopDown || !ForceBottomUp) &&
302cc3bb855SJames Nagurne "-misched-topdown incompatible with -misched-bottomup");
303cc3bb855SJames Nagurne }
304cc3bb855SJames Nagurne
createVLIWResourceModel(const TargetSubtargetInfo & STI,const TargetSchedModel * SchedModel) const305cc3bb855SJames Nagurne VLIWResourceModel *ConvergingVLIWScheduler::createVLIWResourceModel(
306cc3bb855SJames Nagurne const TargetSubtargetInfo &STI, const TargetSchedModel *SchedModel) const {
307cc3bb855SJames Nagurne return new VLIWResourceModel(STI, SchedModel);
308cc3bb855SJames Nagurne }
309cc3bb855SJames Nagurne
releaseTopNode(SUnit * SU)310cc3bb855SJames Nagurne void ConvergingVLIWScheduler::releaseTopNode(SUnit *SU) {
311cc3bb855SJames Nagurne for (const SDep &PI : SU->Preds) {
312cc3bb855SJames Nagurne unsigned PredReadyCycle = PI.getSUnit()->TopReadyCycle;
313cc3bb855SJames Nagurne unsigned MinLatency = PI.getLatency();
314cc3bb855SJames Nagurne #ifndef NDEBUG
315cc3bb855SJames Nagurne Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency);
316cc3bb855SJames Nagurne #endif
317cc3bb855SJames Nagurne if (SU->TopReadyCycle < PredReadyCycle + MinLatency)
318cc3bb855SJames Nagurne SU->TopReadyCycle = PredReadyCycle + MinLatency;
319cc3bb855SJames Nagurne }
320cc3bb855SJames Nagurne
321cc3bb855SJames Nagurne if (!SU->isScheduled)
322cc3bb855SJames Nagurne Top.releaseNode(SU, SU->TopReadyCycle);
323cc3bb855SJames Nagurne }
324cc3bb855SJames Nagurne
releaseBottomNode(SUnit * SU)325cc3bb855SJames Nagurne void ConvergingVLIWScheduler::releaseBottomNode(SUnit *SU) {
326cc3bb855SJames Nagurne assert(SU->getInstr() && "Scheduled SUnit must have instr");
327cc3bb855SJames Nagurne
328cc3bb855SJames Nagurne for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); I != E;
329cc3bb855SJames Nagurne ++I) {
330cc3bb855SJames Nagurne unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle;
331cc3bb855SJames Nagurne unsigned MinLatency = I->getLatency();
332cc3bb855SJames Nagurne #ifndef NDEBUG
333cc3bb855SJames Nagurne Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency);
334cc3bb855SJames Nagurne #endif
335cc3bb855SJames Nagurne if (SU->BotReadyCycle < SuccReadyCycle + MinLatency)
336cc3bb855SJames Nagurne SU->BotReadyCycle = SuccReadyCycle + MinLatency;
337cc3bb855SJames Nagurne }
338cc3bb855SJames Nagurne
339cc3bb855SJames Nagurne if (!SU->isScheduled)
340cc3bb855SJames Nagurne Bot.releaseNode(SU, SU->BotReadyCycle);
341cc3bb855SJames Nagurne }
342cc3bb855SJames Nagurne
~VLIWSchedBoundary()343cc3bb855SJames Nagurne ConvergingVLIWScheduler::VLIWSchedBoundary::~VLIWSchedBoundary() {
344cc3bb855SJames Nagurne delete ResourceModel;
345cc3bb855SJames Nagurne delete HazardRec;
346cc3bb855SJames Nagurne }
347cc3bb855SJames Nagurne
348cc3bb855SJames Nagurne /// Does this SU have a hazard within the current instruction group.
349cc3bb855SJames Nagurne ///
350cc3bb855SJames Nagurne /// The scheduler supports two modes of hazard recognition. The first is the
351cc3bb855SJames Nagurne /// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that
352cc3bb855SJames Nagurne /// supports highly complicated in-order reservation tables
353cc3bb855SJames Nagurne /// (ScoreboardHazardRecognizer) and arbitrary target-specific logic.
354cc3bb855SJames Nagurne ///
355cc3bb855SJames Nagurne /// The second is a streamlined mechanism that checks for hazards based on
356cc3bb855SJames Nagurne /// simple counters that the scheduler itself maintains. It explicitly checks
357cc3bb855SJames Nagurne /// for instruction dispatch limitations, including the number of micro-ops that
358cc3bb855SJames Nagurne /// can dispatch per cycle.
359cc3bb855SJames Nagurne ///
360cc3bb855SJames Nagurne /// TODO: Also check whether the SU must start a new group.
checkHazard(SUnit * SU)361cc3bb855SJames Nagurne bool ConvergingVLIWScheduler::VLIWSchedBoundary::checkHazard(SUnit *SU) {
362cc3bb855SJames Nagurne if (HazardRec->isEnabled())
363cc3bb855SJames Nagurne return HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard;
364cc3bb855SJames Nagurne
365cc3bb855SJames Nagurne unsigned uops = SchedModel->getNumMicroOps(SU->getInstr());
366cc3bb855SJames Nagurne if (IssueCount + uops > SchedModel->getIssueWidth())
367cc3bb855SJames Nagurne return true;
368cc3bb855SJames Nagurne
369cc3bb855SJames Nagurne return false;
370cc3bb855SJames Nagurne }
371cc3bb855SJames Nagurne
releaseNode(SUnit * SU,unsigned ReadyCycle)372cc3bb855SJames Nagurne void ConvergingVLIWScheduler::VLIWSchedBoundary::releaseNode(
373cc3bb855SJames Nagurne SUnit *SU, unsigned ReadyCycle) {
374cc3bb855SJames Nagurne if (ReadyCycle < MinReadyCycle)
375cc3bb855SJames Nagurne MinReadyCycle = ReadyCycle;
376cc3bb855SJames Nagurne
377cc3bb855SJames Nagurne // Check for interlocks first. For the purpose of other heuristics, an
378cc3bb855SJames Nagurne // instruction that cannot issue appears as if it's not in the ReadyQueue.
379cc3bb855SJames Nagurne if (ReadyCycle > CurrCycle || checkHazard(SU))
380cc3bb855SJames Nagurne
381cc3bb855SJames Nagurne Pending.push(SU);
382cc3bb855SJames Nagurne else
383cc3bb855SJames Nagurne Available.push(SU);
384cc3bb855SJames Nagurne }
385cc3bb855SJames Nagurne
386cc3bb855SJames Nagurne /// Move the boundary of scheduled code by one cycle.
bumpCycle()387cc3bb855SJames Nagurne void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpCycle() {
388cc3bb855SJames Nagurne unsigned Width = SchedModel->getIssueWidth();
389cc3bb855SJames Nagurne IssueCount = (IssueCount <= Width) ? 0 : IssueCount - Width;
390cc3bb855SJames Nagurne
391cc3bb855SJames Nagurne assert(MinReadyCycle < std::numeric_limits<unsigned>::max() &&
392cc3bb855SJames Nagurne "MinReadyCycle uninitialized");
393cc3bb855SJames Nagurne unsigned NextCycle = std::max(CurrCycle + 1, MinReadyCycle);
394cc3bb855SJames Nagurne
395cc3bb855SJames Nagurne if (!HazardRec->isEnabled()) {
396cc3bb855SJames Nagurne // Bypass HazardRec virtual calls.
397cc3bb855SJames Nagurne CurrCycle = NextCycle;
398cc3bb855SJames Nagurne } else {
399cc3bb855SJames Nagurne // Bypass getHazardType calls in case of long latency.
400cc3bb855SJames Nagurne for (; CurrCycle != NextCycle; ++CurrCycle) {
401cc3bb855SJames Nagurne if (isTop())
402cc3bb855SJames Nagurne HazardRec->AdvanceCycle();
403cc3bb855SJames Nagurne else
404cc3bb855SJames Nagurne HazardRec->RecedeCycle();
405cc3bb855SJames Nagurne }
406cc3bb855SJames Nagurne }
407cc3bb855SJames Nagurne CheckPending = true;
408cc3bb855SJames Nagurne
409cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "*** Next cycle " << Available.getName() << " cycle "
410cc3bb855SJames Nagurne << CurrCycle << '\n');
411cc3bb855SJames Nagurne }
412cc3bb855SJames Nagurne
413cc3bb855SJames Nagurne /// Move the boundary of scheduled code by one SUnit.
bumpNode(SUnit * SU)414cc3bb855SJames Nagurne void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpNode(SUnit *SU) {
415cc3bb855SJames Nagurne bool startNewCycle = false;
416cc3bb855SJames Nagurne
417cc3bb855SJames Nagurne // Update the reservation table.
418cc3bb855SJames Nagurne if (HazardRec->isEnabled()) {
419cc3bb855SJames Nagurne if (!isTop() && SU->isCall) {
420cc3bb855SJames Nagurne // Calls are scheduled with their preceding instructions. For bottom-up
421cc3bb855SJames Nagurne // scheduling, clear the pipeline state before emitting.
422cc3bb855SJames Nagurne HazardRec->Reset();
423cc3bb855SJames Nagurne }
424cc3bb855SJames Nagurne HazardRec->EmitInstruction(SU);
425cc3bb855SJames Nagurne }
426cc3bb855SJames Nagurne
427cc3bb855SJames Nagurne // Update DFA model.
428cc3bb855SJames Nagurne startNewCycle = ResourceModel->reserveResources(SU, isTop());
429cc3bb855SJames Nagurne
430cc3bb855SJames Nagurne // Check the instruction group dispatch limit.
431cc3bb855SJames Nagurne // TODO: Check if this SU must end a dispatch group.
432cc3bb855SJames Nagurne IssueCount += SchedModel->getNumMicroOps(SU->getInstr());
433cc3bb855SJames Nagurne if (startNewCycle) {
434cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "*** Max instrs at cycle " << CurrCycle << '\n');
435cc3bb855SJames Nagurne bumpCycle();
436cc3bb855SJames Nagurne } else
437cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "*** IssueCount " << IssueCount << " at cycle "
438cc3bb855SJames Nagurne << CurrCycle << '\n');
439cc3bb855SJames Nagurne }
440cc3bb855SJames Nagurne
441cc3bb855SJames Nagurne /// Release pending ready nodes in to the available queue. This makes them
442cc3bb855SJames Nagurne /// visible to heuristics.
releasePending()443cc3bb855SJames Nagurne void ConvergingVLIWScheduler::VLIWSchedBoundary::releasePending() {
444cc3bb855SJames Nagurne // If the available queue is empty, it is safe to reset MinReadyCycle.
445cc3bb855SJames Nagurne if (Available.empty())
446cc3bb855SJames Nagurne MinReadyCycle = std::numeric_limits<unsigned>::max();
447cc3bb855SJames Nagurne
448cc3bb855SJames Nagurne // Check to see if any of the pending instructions are ready to issue. If
449cc3bb855SJames Nagurne // so, add them to the available queue.
450cc3bb855SJames Nagurne for (unsigned i = 0, e = Pending.size(); i != e; ++i) {
451cc3bb855SJames Nagurne SUnit *SU = *(Pending.begin() + i);
452cc3bb855SJames Nagurne unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle;
453cc3bb855SJames Nagurne
454cc3bb855SJames Nagurne if (ReadyCycle < MinReadyCycle)
455cc3bb855SJames Nagurne MinReadyCycle = ReadyCycle;
456cc3bb855SJames Nagurne
457cc3bb855SJames Nagurne if (ReadyCycle > CurrCycle)
458cc3bb855SJames Nagurne continue;
459cc3bb855SJames Nagurne
460cc3bb855SJames Nagurne if (checkHazard(SU))
461cc3bb855SJames Nagurne continue;
462cc3bb855SJames Nagurne
463cc3bb855SJames Nagurne Available.push(SU);
464cc3bb855SJames Nagurne Pending.remove(Pending.begin() + i);
465cc3bb855SJames Nagurne --i;
466cc3bb855SJames Nagurne --e;
467cc3bb855SJames Nagurne }
468cc3bb855SJames Nagurne CheckPending = false;
469cc3bb855SJames Nagurne }
470cc3bb855SJames Nagurne
471cc3bb855SJames Nagurne /// Remove SU from the ready set for this boundary.
removeReady(SUnit * SU)472cc3bb855SJames Nagurne void ConvergingVLIWScheduler::VLIWSchedBoundary::removeReady(SUnit *SU) {
473cc3bb855SJames Nagurne if (Available.isInQueue(SU))
474cc3bb855SJames Nagurne Available.remove(Available.find(SU));
475cc3bb855SJames Nagurne else {
476cc3bb855SJames Nagurne assert(Pending.isInQueue(SU) && "bad ready count");
477cc3bb855SJames Nagurne Pending.remove(Pending.find(SU));
478cc3bb855SJames Nagurne }
479cc3bb855SJames Nagurne }
480cc3bb855SJames Nagurne
481cc3bb855SJames Nagurne /// If this queue only has one ready candidate, return it. As a side effect,
482cc3bb855SJames Nagurne /// advance the cycle until at least one node is ready. If multiple instructions
483cc3bb855SJames Nagurne /// are ready, return NULL.
pickOnlyChoice()484cc3bb855SJames Nagurne SUnit *ConvergingVLIWScheduler::VLIWSchedBoundary::pickOnlyChoice() {
485cc3bb855SJames Nagurne if (CheckPending)
486cc3bb855SJames Nagurne releasePending();
487cc3bb855SJames Nagurne
488cc3bb855SJames Nagurne auto AdvanceCycle = [this]() {
489cc3bb855SJames Nagurne if (Available.empty())
490cc3bb855SJames Nagurne return true;
491cc3bb855SJames Nagurne if (Available.size() == 1 && Pending.size() > 0)
492cc3bb855SJames Nagurne return !ResourceModel->isResourceAvailable(*Available.begin(), isTop()) ||
493cc3bb855SJames Nagurne getWeakLeft(*Available.begin(), isTop()) != 0;
494cc3bb855SJames Nagurne return false;
495cc3bb855SJames Nagurne };
496cc3bb855SJames Nagurne for (unsigned i = 0; AdvanceCycle(); ++i) {
497cc3bb855SJames Nagurne assert(i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) &&
498cc3bb855SJames Nagurne "permanent hazard");
499cc3bb855SJames Nagurne (void)i;
500cc3bb855SJames Nagurne ResourceModel->reserveResources(nullptr, isTop());
501cc3bb855SJames Nagurne bumpCycle();
502cc3bb855SJames Nagurne releasePending();
503cc3bb855SJames Nagurne }
504cc3bb855SJames Nagurne if (Available.size() == 1)
505cc3bb855SJames Nagurne return *Available.begin();
506cc3bb855SJames Nagurne return nullptr;
507cc3bb855SJames Nagurne }
508cc3bb855SJames Nagurne
509cc3bb855SJames Nagurne #ifndef NDEBUG
traceCandidate(const char * Label,const ReadyQueue & Q,SUnit * SU,int Cost,PressureChange P)510cc3bb855SJames Nagurne void ConvergingVLIWScheduler::traceCandidate(const char *Label,
511cc3bb855SJames Nagurne const ReadyQueue &Q, SUnit *SU,
512cc3bb855SJames Nagurne int Cost, PressureChange P) {
513cc3bb855SJames Nagurne dbgs() << Label << " " << Q.getName() << " ";
514cc3bb855SJames Nagurne if (P.isValid())
515cc3bb855SJames Nagurne dbgs() << DAG->TRI->getRegPressureSetName(P.getPSet()) << ":"
516cc3bb855SJames Nagurne << P.getUnitInc() << " ";
517cc3bb855SJames Nagurne else
518cc3bb855SJames Nagurne dbgs() << " ";
519cc3bb855SJames Nagurne dbgs() << "cost(" << Cost << ")\t";
520cc3bb855SJames Nagurne DAG->dumpNode(*SU);
521cc3bb855SJames Nagurne }
522cc3bb855SJames Nagurne
523cc3bb855SJames Nagurne // Very detailed queue dump, to be used with higher verbosity levels.
readyQueueVerboseDump(const RegPressureTracker & RPTracker,SchedCandidate & Candidate,ReadyQueue & Q)524cc3bb855SJames Nagurne void ConvergingVLIWScheduler::readyQueueVerboseDump(
525cc3bb855SJames Nagurne const RegPressureTracker &RPTracker, SchedCandidate &Candidate,
526cc3bb855SJames Nagurne ReadyQueue &Q) {
527cc3bb855SJames Nagurne RegPressureTracker &TempTracker = const_cast<RegPressureTracker &>(RPTracker);
528cc3bb855SJames Nagurne
529cc3bb855SJames Nagurne dbgs() << ">>> " << Q.getName() << "\n";
530cc3bb855SJames Nagurne for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) {
531cc3bb855SJames Nagurne RegPressureDelta RPDelta;
532cc3bb855SJames Nagurne TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
533cc3bb855SJames Nagurne DAG->getRegionCriticalPSets(),
534cc3bb855SJames Nagurne DAG->getRegPressure().MaxSetPressure);
535cc3bb855SJames Nagurne std::stringstream dbgstr;
536cc3bb855SJames Nagurne dbgstr << "SU(" << std::setw(3) << (*I)->NodeNum << ")";
537cc3bb855SJames Nagurne dbgs() << dbgstr.str();
538cc3bb855SJames Nagurne SchedulingCost(Q, *I, Candidate, RPDelta, true);
539cc3bb855SJames Nagurne dbgs() << "\t";
540cc3bb855SJames Nagurne (*I)->getInstr()->dump();
541cc3bb855SJames Nagurne }
542cc3bb855SJames Nagurne dbgs() << "\n";
543cc3bb855SJames Nagurne }
544cc3bb855SJames Nagurne #endif
545cc3bb855SJames Nagurne
546cc3bb855SJames Nagurne /// isSingleUnscheduledPred - If SU2 is the only unscheduled predecessor
547cc3bb855SJames Nagurne /// of SU, return true (we may have duplicates)
isSingleUnscheduledPred(SUnit * SU,SUnit * SU2)548cc3bb855SJames Nagurne static inline bool isSingleUnscheduledPred(SUnit *SU, SUnit *SU2) {
549cc3bb855SJames Nagurne if (SU->NumPredsLeft == 0)
550cc3bb855SJames Nagurne return false;
551cc3bb855SJames Nagurne
552cc3bb855SJames Nagurne for (auto &Pred : SU->Preds) {
553cc3bb855SJames Nagurne // We found an available, but not scheduled, predecessor.
554cc3bb855SJames Nagurne if (!Pred.getSUnit()->isScheduled && (Pred.getSUnit() != SU2))
555cc3bb855SJames Nagurne return false;
556cc3bb855SJames Nagurne }
557cc3bb855SJames Nagurne
558cc3bb855SJames Nagurne return true;
559cc3bb855SJames Nagurne }
560cc3bb855SJames Nagurne
561cc3bb855SJames Nagurne /// isSingleUnscheduledSucc - If SU2 is the only unscheduled successor
562cc3bb855SJames Nagurne /// of SU, return true (we may have duplicates)
isSingleUnscheduledSucc(SUnit * SU,SUnit * SU2)563cc3bb855SJames Nagurne static inline bool isSingleUnscheduledSucc(SUnit *SU, SUnit *SU2) {
564cc3bb855SJames Nagurne if (SU->NumSuccsLeft == 0)
565cc3bb855SJames Nagurne return false;
566cc3bb855SJames Nagurne
567cc3bb855SJames Nagurne for (auto &Succ : SU->Succs) {
568cc3bb855SJames Nagurne // We found an available, but not scheduled, successor.
569cc3bb855SJames Nagurne if (!Succ.getSUnit()->isScheduled && (Succ.getSUnit() != SU2))
570cc3bb855SJames Nagurne return false;
571cc3bb855SJames Nagurne }
572cc3bb855SJames Nagurne return true;
573cc3bb855SJames Nagurne }
574cc3bb855SJames Nagurne
575cc3bb855SJames Nagurne /// Check if the instruction changes the register pressure of a register in the
576cc3bb855SJames Nagurne /// high pressure set. The function returns a negative value if the pressure
577cc3bb855SJames Nagurne /// decreases and a positive value is the pressure increases. If the instruction
578cc3bb855SJames Nagurne /// doesn't use a high pressure register or doesn't change the register
579cc3bb855SJames Nagurne /// pressure, then return 0.
pressureChange(const SUnit * SU,bool isBotUp)580cc3bb855SJames Nagurne int ConvergingVLIWScheduler::pressureChange(const SUnit *SU, bool isBotUp) {
581cc3bb855SJames Nagurne PressureDiff &PD = DAG->getPressureDiff(SU);
582*9e6d1f4bSKazu Hirata for (const auto &P : PD) {
583cc3bb855SJames Nagurne if (!P.isValid())
584cc3bb855SJames Nagurne continue;
585cc3bb855SJames Nagurne // The pressure differences are computed bottom-up, so the comparision for
586cc3bb855SJames Nagurne // an increase is positive in the bottom direction, but negative in the
587cc3bb855SJames Nagurne // top-down direction.
588cc3bb855SJames Nagurne if (HighPressureSets[P.getPSet()])
589cc3bb855SJames Nagurne return (isBotUp ? P.getUnitInc() : -P.getUnitInc());
590cc3bb855SJames Nagurne }
591cc3bb855SJames Nagurne return 0;
592cc3bb855SJames Nagurne }
593cc3bb855SJames Nagurne
594cc3bb855SJames Nagurne /// Single point to compute overall scheduling cost.
595cc3bb855SJames Nagurne /// TODO: More heuristics will be used soon.
SchedulingCost(ReadyQueue & Q,SUnit * SU,SchedCandidate & Candidate,RegPressureDelta & Delta,bool verbose)596cc3bb855SJames Nagurne int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
597cc3bb855SJames Nagurne SchedCandidate &Candidate,
598cc3bb855SJames Nagurne RegPressureDelta &Delta,
599cc3bb855SJames Nagurne bool verbose) {
600cc3bb855SJames Nagurne // Initial trivial priority.
601cc3bb855SJames Nagurne int ResCount = 1;
602cc3bb855SJames Nagurne
603cc3bb855SJames Nagurne // Do not waste time on a node that is already scheduled.
604cc3bb855SJames Nagurne if (!SU || SU->isScheduled)
605cc3bb855SJames Nagurne return ResCount;
606cc3bb855SJames Nagurne
607cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs()
608cc3bb855SJames Nagurne << ((Q.getID() == TopQID) ? "(top|" : "(bot|"));
609cc3bb855SJames Nagurne // Forced priority is high.
610cc3bb855SJames Nagurne if (SU->isScheduleHigh) {
611cc3bb855SJames Nagurne ResCount += PriorityOne;
612cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "H|");
613cc3bb855SJames Nagurne }
614cc3bb855SJames Nagurne
615cc3bb855SJames Nagurne unsigned IsAvailableAmt = 0;
616cc3bb855SJames Nagurne // Critical path first.
617cc3bb855SJames Nagurne if (Q.getID() == TopQID) {
618cc3bb855SJames Nagurne if (Top.isLatencyBound(SU)) {
619cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << "LB|");
620cc3bb855SJames Nagurne ResCount += (SU->getHeight() * ScaleTwo);
621cc3bb855SJames Nagurne }
622cc3bb855SJames Nagurne
623cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) {
624cc3bb855SJames Nagurne std::stringstream dbgstr;
625cc3bb855SJames Nagurne dbgstr << "h" << std::setw(3) << SU->getHeight() << "|";
626cc3bb855SJames Nagurne dbgs() << dbgstr.str();
627cc3bb855SJames Nagurne });
628cc3bb855SJames Nagurne
629cc3bb855SJames Nagurne // If resources are available for it, multiply the
630cc3bb855SJames Nagurne // chance of scheduling.
631cc3bb855SJames Nagurne if (Top.ResourceModel->isResourceAvailable(SU, true)) {
632cc3bb855SJames Nagurne IsAvailableAmt = (PriorityTwo + PriorityThree);
633cc3bb855SJames Nagurne ResCount += IsAvailableAmt;
634cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << "A|");
635cc3bb855SJames Nagurne } else
636cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << " |");
637cc3bb855SJames Nagurne } else {
638cc3bb855SJames Nagurne if (Bot.isLatencyBound(SU)) {
639cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << "LB|");
640cc3bb855SJames Nagurne ResCount += (SU->getDepth() * ScaleTwo);
641cc3bb855SJames Nagurne }
642cc3bb855SJames Nagurne
643cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) {
644cc3bb855SJames Nagurne std::stringstream dbgstr;
645cc3bb855SJames Nagurne dbgstr << "d" << std::setw(3) << SU->getDepth() << "|";
646cc3bb855SJames Nagurne dbgs() << dbgstr.str();
647cc3bb855SJames Nagurne });
648cc3bb855SJames Nagurne
649cc3bb855SJames Nagurne // If resources are available for it, multiply the
650cc3bb855SJames Nagurne // chance of scheduling.
651cc3bb855SJames Nagurne if (Bot.ResourceModel->isResourceAvailable(SU, false)) {
652cc3bb855SJames Nagurne IsAvailableAmt = (PriorityTwo + PriorityThree);
653cc3bb855SJames Nagurne ResCount += IsAvailableAmt;
654cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << "A|");
655cc3bb855SJames Nagurne } else
656cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << " |");
657cc3bb855SJames Nagurne }
658cc3bb855SJames Nagurne
659cc3bb855SJames Nagurne unsigned NumNodesBlocking = 0;
660cc3bb855SJames Nagurne if (Q.getID() == TopQID) {
661cc3bb855SJames Nagurne // How many SUs does it block from scheduling?
662cc3bb855SJames Nagurne // Look at all of the successors of this node.
663cc3bb855SJames Nagurne // Count the number of nodes that
664cc3bb855SJames Nagurne // this node is the sole unscheduled node for.
665cc3bb855SJames Nagurne if (Top.isLatencyBound(SU))
666cc3bb855SJames Nagurne for (const SDep &SI : SU->Succs)
667cc3bb855SJames Nagurne if (isSingleUnscheduledPred(SI.getSUnit(), SU))
668cc3bb855SJames Nagurne ++NumNodesBlocking;
669cc3bb855SJames Nagurne } else {
670cc3bb855SJames Nagurne // How many unscheduled predecessors block this node?
671cc3bb855SJames Nagurne if (Bot.isLatencyBound(SU))
672cc3bb855SJames Nagurne for (const SDep &PI : SU->Preds)
673cc3bb855SJames Nagurne if (isSingleUnscheduledSucc(PI.getSUnit(), SU))
674cc3bb855SJames Nagurne ++NumNodesBlocking;
675cc3bb855SJames Nagurne }
676cc3bb855SJames Nagurne ResCount += (NumNodesBlocking * ScaleTwo);
677cc3bb855SJames Nagurne
678cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) {
679cc3bb855SJames Nagurne std::stringstream dbgstr;
680cc3bb855SJames Nagurne dbgstr << "blk " << std::setw(2) << NumNodesBlocking << ")|";
681cc3bb855SJames Nagurne dbgs() << dbgstr.str();
682cc3bb855SJames Nagurne });
683cc3bb855SJames Nagurne
684cc3bb855SJames Nagurne // Factor in reg pressure as a heuristic.
685cc3bb855SJames Nagurne if (!IgnoreBBRegPressure) {
686cc3bb855SJames Nagurne // Decrease priority by the amount that register pressure exceeds the limit.
687cc3bb855SJames Nagurne ResCount -= (Delta.Excess.getUnitInc() * PriorityOne);
688cc3bb855SJames Nagurne // Decrease priority if register pressure exceeds the limit.
689cc3bb855SJames Nagurne ResCount -= (Delta.CriticalMax.getUnitInc() * PriorityOne);
690cc3bb855SJames Nagurne // Decrease priority slightly if register pressure would increase over the
691cc3bb855SJames Nagurne // current maximum.
692cc3bb855SJames Nagurne ResCount -= (Delta.CurrentMax.getUnitInc() * PriorityTwo);
693cc3bb855SJames Nagurne // If there are register pressure issues, then we remove the value added for
694cc3bb855SJames Nagurne // the instruction being available. The rationale is that we really don't
695cc3bb855SJames Nagurne // want to schedule an instruction that causes a spill.
696cc3bb855SJames Nagurne if (IsAvailableAmt && pressureChange(SU, Q.getID() != TopQID) > 0 &&
697cc3bb855SJames Nagurne (Delta.Excess.getUnitInc() || Delta.CriticalMax.getUnitInc() ||
698cc3bb855SJames Nagurne Delta.CurrentMax.getUnitInc()))
699cc3bb855SJames Nagurne ResCount -= IsAvailableAmt;
700cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) {
701cc3bb855SJames Nagurne dbgs() << "RP " << Delta.Excess.getUnitInc() << "/"
702cc3bb855SJames Nagurne << Delta.CriticalMax.getUnitInc() << "/"
703cc3bb855SJames Nagurne << Delta.CurrentMax.getUnitInc() << ")|";
704cc3bb855SJames Nagurne });
705cc3bb855SJames Nagurne }
706cc3bb855SJames Nagurne
707cc3bb855SJames Nagurne // Give preference to a zero latency instruction if the dependent
708cc3bb855SJames Nagurne // instruction is in the current packet.
709cc3bb855SJames Nagurne if (Q.getID() == TopQID && getWeakLeft(SU, true) == 0) {
710cc3bb855SJames Nagurne for (const SDep &PI : SU->Preds) {
711cc3bb855SJames Nagurne if (!PI.getSUnit()->getInstr()->isPseudo() && PI.isAssignedRegDep() &&
712cc3bb855SJames Nagurne PI.getLatency() == 0 &&
713cc3bb855SJames Nagurne Top.ResourceModel->isInPacket(PI.getSUnit())) {
714cc3bb855SJames Nagurne ResCount += PriorityThree;
715cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << "Z|");
716cc3bb855SJames Nagurne }
717cc3bb855SJames Nagurne }
718cc3bb855SJames Nagurne } else if (Q.getID() == BotQID && getWeakLeft(SU, false) == 0) {
719cc3bb855SJames Nagurne for (const SDep &SI : SU->Succs) {
720cc3bb855SJames Nagurne if (!SI.getSUnit()->getInstr()->isPseudo() && SI.isAssignedRegDep() &&
721cc3bb855SJames Nagurne SI.getLatency() == 0 &&
722cc3bb855SJames Nagurne Bot.ResourceModel->isInPacket(SI.getSUnit())) {
723cc3bb855SJames Nagurne ResCount += PriorityThree;
724cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << "Z|");
725cc3bb855SJames Nagurne }
726cc3bb855SJames Nagurne }
727cc3bb855SJames Nagurne }
728cc3bb855SJames Nagurne
729cc3bb855SJames Nagurne // If the instruction has a non-zero latency dependence with an instruction in
730cc3bb855SJames Nagurne // the current packet, then it should not be scheduled yet. The case occurs
731cc3bb855SJames Nagurne // when the dependent instruction is scheduled in a new packet, so the
732cc3bb855SJames Nagurne // scheduler updates the current cycle and pending instructions become
733cc3bb855SJames Nagurne // available.
734cc3bb855SJames Nagurne if (CheckEarlyAvail) {
735cc3bb855SJames Nagurne if (Q.getID() == TopQID) {
736cc3bb855SJames Nagurne for (const auto &PI : SU->Preds) {
737cc3bb855SJames Nagurne if (PI.getLatency() > 0 &&
738cc3bb855SJames Nagurne Top.ResourceModel->isInPacket(PI.getSUnit())) {
739cc3bb855SJames Nagurne ResCount -= PriorityOne;
740cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << "D|");
741cc3bb855SJames Nagurne }
742cc3bb855SJames Nagurne }
743cc3bb855SJames Nagurne } else {
744cc3bb855SJames Nagurne for (const auto &SI : SU->Succs) {
745cc3bb855SJames Nagurne if (SI.getLatency() > 0 &&
746cc3bb855SJames Nagurne Bot.ResourceModel->isInPacket(SI.getSUnit())) {
747cc3bb855SJames Nagurne ResCount -= PriorityOne;
748cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) dbgs() << "D|");
749cc3bb855SJames Nagurne }
750cc3bb855SJames Nagurne }
751cc3bb855SJames Nagurne }
752cc3bb855SJames Nagurne }
753cc3bb855SJames Nagurne
754cc3bb855SJames Nagurne LLVM_DEBUG(if (verbose) {
755cc3bb855SJames Nagurne std::stringstream dbgstr;
756cc3bb855SJames Nagurne dbgstr << "Total " << std::setw(4) << ResCount << ")";
757cc3bb855SJames Nagurne dbgs() << dbgstr.str();
758cc3bb855SJames Nagurne });
759cc3bb855SJames Nagurne
760cc3bb855SJames Nagurne return ResCount;
761cc3bb855SJames Nagurne }
762cc3bb855SJames Nagurne
763cc3bb855SJames Nagurne /// Pick the best candidate from the top queue.
764cc3bb855SJames Nagurne ///
765cc3bb855SJames Nagurne /// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during
766cc3bb855SJames Nagurne /// DAG building. To adjust for the current scheduling location we need to
767cc3bb855SJames Nagurne /// maintain the number of vreg uses remaining to be top-scheduled.
768cc3bb855SJames Nagurne ConvergingVLIWScheduler::CandResult
pickNodeFromQueue(VLIWSchedBoundary & Zone,const RegPressureTracker & RPTracker,SchedCandidate & Candidate)769cc3bb855SJames Nagurne ConvergingVLIWScheduler::pickNodeFromQueue(VLIWSchedBoundary &Zone,
770cc3bb855SJames Nagurne const RegPressureTracker &RPTracker,
771cc3bb855SJames Nagurne SchedCandidate &Candidate) {
772cc3bb855SJames Nagurne ReadyQueue &Q = Zone.Available;
773cc3bb855SJames Nagurne LLVM_DEBUG(if (SchedDebugVerboseLevel > 1)
774cc3bb855SJames Nagurne readyQueueVerboseDump(RPTracker, Candidate, Q);
775cc3bb855SJames Nagurne else Q.dump(););
776cc3bb855SJames Nagurne
777cc3bb855SJames Nagurne // getMaxPressureDelta temporarily modifies the tracker.
778cc3bb855SJames Nagurne RegPressureTracker &TempTracker = const_cast<RegPressureTracker &>(RPTracker);
779cc3bb855SJames Nagurne
780cc3bb855SJames Nagurne // BestSU remains NULL if no top candidates beat the best existing candidate.
781cc3bb855SJames Nagurne CandResult FoundCandidate = NoCand;
782cc3bb855SJames Nagurne for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) {
783cc3bb855SJames Nagurne RegPressureDelta RPDelta;
784cc3bb855SJames Nagurne TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
785cc3bb855SJames Nagurne DAG->getRegionCriticalPSets(),
786cc3bb855SJames Nagurne DAG->getRegPressure().MaxSetPressure);
787cc3bb855SJames Nagurne
788cc3bb855SJames Nagurne int CurrentCost = SchedulingCost(Q, *I, Candidate, RPDelta, false);
789cc3bb855SJames Nagurne
790cc3bb855SJames Nagurne // Initialize the candidate if needed.
791cc3bb855SJames Nagurne if (!Candidate.SU) {
792cc3bb855SJames Nagurne LLVM_DEBUG(traceCandidate("DCAND", Q, *I, CurrentCost));
793cc3bb855SJames Nagurne Candidate.SU = *I;
794cc3bb855SJames Nagurne Candidate.RPDelta = RPDelta;
795cc3bb855SJames Nagurne Candidate.SCost = CurrentCost;
796cc3bb855SJames Nagurne FoundCandidate = NodeOrder;
797cc3bb855SJames Nagurne continue;
798cc3bb855SJames Nagurne }
799cc3bb855SJames Nagurne
800cc3bb855SJames Nagurne // Choose node order for negative cost candidates. There is no good
801cc3bb855SJames Nagurne // candidate in this case.
802cc3bb855SJames Nagurne if (CurrentCost < 0 && Candidate.SCost < 0) {
803cc3bb855SJames Nagurne if ((Q.getID() == TopQID && (*I)->NodeNum < Candidate.SU->NodeNum) ||
804cc3bb855SJames Nagurne (Q.getID() == BotQID && (*I)->NodeNum > Candidate.SU->NodeNum)) {
805cc3bb855SJames Nagurne LLVM_DEBUG(traceCandidate("NCAND", Q, *I, CurrentCost));
806cc3bb855SJames Nagurne Candidate.SU = *I;
807cc3bb855SJames Nagurne Candidate.RPDelta = RPDelta;
808cc3bb855SJames Nagurne Candidate.SCost = CurrentCost;
809cc3bb855SJames Nagurne FoundCandidate = NodeOrder;
810cc3bb855SJames Nagurne }
811cc3bb855SJames Nagurne continue;
812cc3bb855SJames Nagurne }
813cc3bb855SJames Nagurne
814cc3bb855SJames Nagurne // Best cost.
815cc3bb855SJames Nagurne if (CurrentCost > Candidate.SCost) {
816cc3bb855SJames Nagurne LLVM_DEBUG(traceCandidate("CCAND", Q, *I, CurrentCost));
817cc3bb855SJames Nagurne Candidate.SU = *I;
818cc3bb855SJames Nagurne Candidate.RPDelta = RPDelta;
819cc3bb855SJames Nagurne Candidate.SCost = CurrentCost;
820cc3bb855SJames Nagurne FoundCandidate = BestCost;
821cc3bb855SJames Nagurne continue;
822cc3bb855SJames Nagurne }
823cc3bb855SJames Nagurne
824cc3bb855SJames Nagurne // Choose an instruction that does not depend on an artificial edge.
825cc3bb855SJames Nagurne unsigned CurrWeak = getWeakLeft(*I, (Q.getID() == TopQID));
826cc3bb855SJames Nagurne unsigned CandWeak = getWeakLeft(Candidate.SU, (Q.getID() == TopQID));
827cc3bb855SJames Nagurne if (CurrWeak != CandWeak) {
828cc3bb855SJames Nagurne if (CurrWeak < CandWeak) {
829cc3bb855SJames Nagurne LLVM_DEBUG(traceCandidate("WCAND", Q, *I, CurrentCost));
830cc3bb855SJames Nagurne Candidate.SU = *I;
831cc3bb855SJames Nagurne Candidate.RPDelta = RPDelta;
832cc3bb855SJames Nagurne Candidate.SCost = CurrentCost;
833cc3bb855SJames Nagurne FoundCandidate = Weak;
834cc3bb855SJames Nagurne }
835cc3bb855SJames Nagurne continue;
836cc3bb855SJames Nagurne }
837cc3bb855SJames Nagurne
838cc3bb855SJames Nagurne if (CurrentCost == Candidate.SCost && Zone.isLatencyBound(*I)) {
839cc3bb855SJames Nagurne unsigned CurrSize, CandSize;
840cc3bb855SJames Nagurne if (Q.getID() == TopQID) {
841cc3bb855SJames Nagurne CurrSize = (*I)->Succs.size();
842cc3bb855SJames Nagurne CandSize = Candidate.SU->Succs.size();
843cc3bb855SJames Nagurne } else {
844cc3bb855SJames Nagurne CurrSize = (*I)->Preds.size();
845cc3bb855SJames Nagurne CandSize = Candidate.SU->Preds.size();
846cc3bb855SJames Nagurne }
847cc3bb855SJames Nagurne if (CurrSize > CandSize) {
848cc3bb855SJames Nagurne LLVM_DEBUG(traceCandidate("SPCAND", Q, *I, CurrentCost));
849cc3bb855SJames Nagurne Candidate.SU = *I;
850cc3bb855SJames Nagurne Candidate.RPDelta = RPDelta;
851cc3bb855SJames Nagurne Candidate.SCost = CurrentCost;
852cc3bb855SJames Nagurne FoundCandidate = BestCost;
853cc3bb855SJames Nagurne }
854cc3bb855SJames Nagurne // Keep the old candidate if it's a better candidate. That is, don't use
855cc3bb855SJames Nagurne // the subsequent tie breaker.
856cc3bb855SJames Nagurne if (CurrSize != CandSize)
857cc3bb855SJames Nagurne continue;
858cc3bb855SJames Nagurne }
859cc3bb855SJames Nagurne
860cc3bb855SJames Nagurne // Tie breaker.
861cc3bb855SJames Nagurne // To avoid scheduling indeterminism, we need a tie breaker
862cc3bb855SJames Nagurne // for the case when cost is identical for two nodes.
863cc3bb855SJames Nagurne if (UseNewerCandidate && CurrentCost == Candidate.SCost) {
864cc3bb855SJames Nagurne if ((Q.getID() == TopQID && (*I)->NodeNum < Candidate.SU->NodeNum) ||
865cc3bb855SJames Nagurne (Q.getID() == BotQID && (*I)->NodeNum > Candidate.SU->NodeNum)) {
866cc3bb855SJames Nagurne LLVM_DEBUG(traceCandidate("TCAND", Q, *I, CurrentCost));
867cc3bb855SJames Nagurne Candidate.SU = *I;
868cc3bb855SJames Nagurne Candidate.RPDelta = RPDelta;
869cc3bb855SJames Nagurne Candidate.SCost = CurrentCost;
870cc3bb855SJames Nagurne FoundCandidate = NodeOrder;
871cc3bb855SJames Nagurne continue;
872cc3bb855SJames Nagurne }
873cc3bb855SJames Nagurne }
874cc3bb855SJames Nagurne
875cc3bb855SJames Nagurne // Fall through to original instruction order.
876cc3bb855SJames Nagurne // Only consider node order if Candidate was chosen from this Q.
877cc3bb855SJames Nagurne if (FoundCandidate == NoCand)
878cc3bb855SJames Nagurne continue;
879cc3bb855SJames Nagurne }
880cc3bb855SJames Nagurne return FoundCandidate;
881cc3bb855SJames Nagurne }
882cc3bb855SJames Nagurne
883cc3bb855SJames Nagurne /// Pick the best candidate node from either the top or bottom queue.
pickNodeBidrectional(bool & IsTopNode)884cc3bb855SJames Nagurne SUnit *ConvergingVLIWScheduler::pickNodeBidrectional(bool &IsTopNode) {
885cc3bb855SJames Nagurne // Schedule as far as possible in the direction of no choice. This is most
886cc3bb855SJames Nagurne // efficient, but also provides the best heuristics for CriticalPSets.
887cc3bb855SJames Nagurne if (SUnit *SU = Bot.pickOnlyChoice()) {
888cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "Picked only Bottom\n");
889cc3bb855SJames Nagurne IsTopNode = false;
890cc3bb855SJames Nagurne return SU;
891cc3bb855SJames Nagurne }
892cc3bb855SJames Nagurne if (SUnit *SU = Top.pickOnlyChoice()) {
893cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "Picked only Top\n");
894cc3bb855SJames Nagurne IsTopNode = true;
895cc3bb855SJames Nagurne return SU;
896cc3bb855SJames Nagurne }
897cc3bb855SJames Nagurne SchedCandidate BotCand;
898cc3bb855SJames Nagurne // Prefer bottom scheduling when heuristics are silent.
899cc3bb855SJames Nagurne CandResult BotResult =
900cc3bb855SJames Nagurne pickNodeFromQueue(Bot, DAG->getBotRPTracker(), BotCand);
901cc3bb855SJames Nagurne assert(BotResult != NoCand && "failed to find the first candidate");
902cc3bb855SJames Nagurne
903cc3bb855SJames Nagurne // If either Q has a single candidate that provides the least increase in
904cc3bb855SJames Nagurne // Excess pressure, we can immediately schedule from that Q.
905cc3bb855SJames Nagurne //
906cc3bb855SJames Nagurne // RegionCriticalPSets summarizes the pressure within the scheduled region and
907cc3bb855SJames Nagurne // affects picking from either Q. If scheduling in one direction must
908cc3bb855SJames Nagurne // increase pressure for one of the excess PSets, then schedule in that
909cc3bb855SJames Nagurne // direction first to provide more freedom in the other direction.
910cc3bb855SJames Nagurne if (BotResult == SingleExcess || BotResult == SingleCritical) {
911cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "Prefered Bottom Node\n");
912cc3bb855SJames Nagurne IsTopNode = false;
913cc3bb855SJames Nagurne return BotCand.SU;
914cc3bb855SJames Nagurne }
915cc3bb855SJames Nagurne // Check if the top Q has a better candidate.
916cc3bb855SJames Nagurne SchedCandidate TopCand;
917cc3bb855SJames Nagurne CandResult TopResult =
918cc3bb855SJames Nagurne pickNodeFromQueue(Top, DAG->getTopRPTracker(), TopCand);
919cc3bb855SJames Nagurne assert(TopResult != NoCand && "failed to find the first candidate");
920cc3bb855SJames Nagurne
921cc3bb855SJames Nagurne if (TopResult == SingleExcess || TopResult == SingleCritical) {
922cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "Prefered Top Node\n");
923cc3bb855SJames Nagurne IsTopNode = true;
924cc3bb855SJames Nagurne return TopCand.SU;
925cc3bb855SJames Nagurne }
926cc3bb855SJames Nagurne // If either Q has a single candidate that minimizes pressure above the
927cc3bb855SJames Nagurne // original region's pressure pick it.
928cc3bb855SJames Nagurne if (BotResult == SingleMax) {
929cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "Prefered Bottom Node SingleMax\n");
930cc3bb855SJames Nagurne IsTopNode = false;
931cc3bb855SJames Nagurne return BotCand.SU;
932cc3bb855SJames Nagurne }
933cc3bb855SJames Nagurne if (TopResult == SingleMax) {
934cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "Prefered Top Node SingleMax\n");
935cc3bb855SJames Nagurne IsTopNode = true;
936cc3bb855SJames Nagurne return TopCand.SU;
937cc3bb855SJames Nagurne }
938cc3bb855SJames Nagurne if (TopCand.SCost > BotCand.SCost) {
939cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "Prefered Top Node Cost\n");
940cc3bb855SJames Nagurne IsTopNode = true;
941cc3bb855SJames Nagurne return TopCand.SU;
942cc3bb855SJames Nagurne }
943cc3bb855SJames Nagurne // Otherwise prefer the bottom candidate in node order.
944cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "Prefered Bottom in Node order\n");
945cc3bb855SJames Nagurne IsTopNode = false;
946cc3bb855SJames Nagurne return BotCand.SU;
947cc3bb855SJames Nagurne }
948cc3bb855SJames Nagurne
949cc3bb855SJames Nagurne /// Pick the best node to balance the schedule. Implements MachineSchedStrategy.
pickNode(bool & IsTopNode)950cc3bb855SJames Nagurne SUnit *ConvergingVLIWScheduler::pickNode(bool &IsTopNode) {
951cc3bb855SJames Nagurne if (DAG->top() == DAG->bottom()) {
952cc3bb855SJames Nagurne assert(Top.Available.empty() && Top.Pending.empty() &&
953cc3bb855SJames Nagurne Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
954cc3bb855SJames Nagurne return nullptr;
955cc3bb855SJames Nagurne }
956cc3bb855SJames Nagurne SUnit *SU;
957cc3bb855SJames Nagurne if (ForceTopDown) {
958cc3bb855SJames Nagurne SU = Top.pickOnlyChoice();
959cc3bb855SJames Nagurne if (!SU) {
960cc3bb855SJames Nagurne SchedCandidate TopCand;
961cc3bb855SJames Nagurne CandResult TopResult =
962cc3bb855SJames Nagurne pickNodeFromQueue(Top, DAG->getTopRPTracker(), TopCand);
963cc3bb855SJames Nagurne assert(TopResult != NoCand && "failed to find the first candidate");
964cc3bb855SJames Nagurne (void)TopResult;
965cc3bb855SJames Nagurne SU = TopCand.SU;
966cc3bb855SJames Nagurne }
967cc3bb855SJames Nagurne IsTopNode = true;
968cc3bb855SJames Nagurne } else if (ForceBottomUp) {
969cc3bb855SJames Nagurne SU = Bot.pickOnlyChoice();
970cc3bb855SJames Nagurne if (!SU) {
971cc3bb855SJames Nagurne SchedCandidate BotCand;
972cc3bb855SJames Nagurne CandResult BotResult =
973cc3bb855SJames Nagurne pickNodeFromQueue(Bot, DAG->getBotRPTracker(), BotCand);
974cc3bb855SJames Nagurne assert(BotResult != NoCand && "failed to find the first candidate");
975cc3bb855SJames Nagurne (void)BotResult;
976cc3bb855SJames Nagurne SU = BotCand.SU;
977cc3bb855SJames Nagurne }
978cc3bb855SJames Nagurne IsTopNode = false;
979cc3bb855SJames Nagurne } else {
980cc3bb855SJames Nagurne SU = pickNodeBidrectional(IsTopNode);
981cc3bb855SJames Nagurne }
982cc3bb855SJames Nagurne if (SU->isTopReady())
983cc3bb855SJames Nagurne Top.removeReady(SU);
984cc3bb855SJames Nagurne if (SU->isBottomReady())
985cc3bb855SJames Nagurne Bot.removeReady(SU);
986cc3bb855SJames Nagurne
987cc3bb855SJames Nagurne LLVM_DEBUG(dbgs() << "*** " << (IsTopNode ? "Top" : "Bottom")
988cc3bb855SJames Nagurne << " Scheduling instruction in cycle "
989cc3bb855SJames Nagurne << (IsTopNode ? Top.CurrCycle : Bot.CurrCycle) << " ("
990cc3bb855SJames Nagurne << reportPackets() << ")\n";
991cc3bb855SJames Nagurne DAG->dumpNode(*SU));
992cc3bb855SJames Nagurne return SU;
993cc3bb855SJames Nagurne }
994cc3bb855SJames Nagurne
995cc3bb855SJames Nagurne /// Update the scheduler's state after scheduling a node. This is the same node
996cc3bb855SJames Nagurne /// that was just returned by pickNode(). However, VLIWMachineScheduler needs
997cc3bb855SJames Nagurne /// to update it's state based on the current cycle before MachineSchedStrategy
998cc3bb855SJames Nagurne /// does.
schedNode(SUnit * SU,bool IsTopNode)999cc3bb855SJames Nagurne void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) {
1000cc3bb855SJames Nagurne if (IsTopNode) {
1001cc3bb855SJames Nagurne Top.bumpNode(SU);
1002cc3bb855SJames Nagurne SU->TopReadyCycle = Top.CurrCycle;
1003cc3bb855SJames Nagurne } else {
1004cc3bb855SJames Nagurne Bot.bumpNode(SU);
1005cc3bb855SJames Nagurne SU->BotReadyCycle = Bot.CurrCycle;
1006cc3bb855SJames Nagurne }
1007cc3bb855SJames Nagurne }
1008