blob: 3c88eeeb8a47bc1841545c041d6ed6cea202b722 [file] [log] [blame]
Sergei Larin4d8986a2012-09-04 14:49:56 +00001//===- HexagonMachineScheduler.cpp - MI Scheduler for Hexagon -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// MachineScheduler schedules machine instructions after phi elimination. It
11// preserves LiveIntervals so it can be invoked before register allocation.
12//
13//===----------------------------------------------------------------------===//
14
Sergei Larin4d8986a2012-09-04 14:49:56 +000015#include "HexagonMachineScheduler.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000016#include "HexagonInstrInfo.h"
Krzysztof Parzyszek9be66732016-07-15 17:48:09 +000017#include "HexagonSubtarget.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000018#include "llvm/ADT/SmallVector.h"
19#include "llvm/CodeGen/DFAPacketizer.h"
20#include "llvm/CodeGen/MachineBasicBlock.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstr.h"
Jakub Staszakdf17ddd2013-03-10 13:11:23 +000023#include "llvm/CodeGen/MachineLoopInfo.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000024#include "llvm/CodeGen/RegisterPressure.h"
25#include "llvm/CodeGen/ScheduleDAG.h"
26#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000027#include "llvm/CodeGen/TargetInstrInfo.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000028#include "llvm/CodeGen/TargetSchedule.h"
Jakub Staszakdf17ddd2013-03-10 13:11:23 +000029#include "llvm/IR/Function.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000030#include "llvm/Support/CommandLine.h"
31#include "llvm/Support/Debug.h"
32#include "llvm/Support/raw_ostream.h"
Eugene Zelenko3b873362017-09-28 22:27:31 +000033#include "llvm/Target/TargetOpcodes.h"
34#include "llvm/Target/TargetRegisterInfo.h"
35#include "llvm/Target/TargetSubtargetInfo.h"
36#include <algorithm>
37#include <cassert>
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +000038#include <iomanip>
Eugene Zelenko3b873362017-09-28 22:27:31 +000039#include <limits>
40#include <memory>
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +000041#include <sstream>
42
Eugene Zelenko3b873362017-09-28 22:27:31 +000043using namespace llvm;
44
45#define DEBUG_TYPE "machine-scheduler"
46
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +000047static cl::opt<bool> IgnoreBBRegPressure("ignore-bb-reg-pressure",
48 cl::Hidden, cl::ZeroOrMore, cl::init(false));
49
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +000050static cl::opt<unsigned> SchedDebugVerboseLevel("misched-verbose-level",
51 cl::Hidden, cl::ZeroOrMore, cl::init(1));
52
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +000053static cl::opt<bool> TopUseShorterTie("top-use-shorter-tie",
54 cl::Hidden, cl::ZeroOrMore, cl::init(false));
55
56static cl::opt<bool> BotUseShorterTie("bot-use-shorter-tie",
57 cl::Hidden, cl::ZeroOrMore, cl::init(false));
58
59static cl::opt<bool> DisableTCTie("disable-tc-tie",
60 cl::Hidden, cl::ZeroOrMore, cl::init(false));
61
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +000062// Check if the scheduler should penalize instructions that are available to
63// early due to a zero-latency dependence.
64static cl::opt<bool> CheckEarlyAvail("check-early-avail", cl::Hidden,
65 cl::ZeroOrMore, cl::init(true));
66
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +000067/// Save the last formed packet
68void VLIWResourceModel::savePacket() {
69 OldPacket = Packet;
70}
71
Sergei Larin4d8986a2012-09-04 14:49:56 +000072/// Check if scheduling of this SU is possible
73/// in the current packet.
74/// It is _not_ precise (statefull), it is more like
75/// another heuristic. Many corner cases are figured
76/// empirically.
77bool VLIWResourceModel::isResourceAvailable(SUnit *SU) {
78 if (!SU || !SU->getInstr())
79 return false;
80
81 // First see if the pipeline could receive this instruction
82 // in the current cycle.
83 switch (SU->getInstr()->getOpcode()) {
84 default:
Duncan P. N. Exon Smith57022872016-02-27 19:09:00 +000085 if (!ResourcesModel->canReserveResources(*SU->getInstr()))
Sergei Larin4d8986a2012-09-04 14:49:56 +000086 return false;
87 case TargetOpcode::EXTRACT_SUBREG:
88 case TargetOpcode::INSERT_SUBREG:
89 case TargetOpcode::SUBREG_TO_REG:
90 case TargetOpcode::REG_SEQUENCE:
91 case TargetOpcode::IMPLICIT_DEF:
92 case TargetOpcode::COPY:
93 case TargetOpcode::INLINEASM:
94 break;
95 }
96
Krzysztof Parzyszek786333f2016-07-18 16:05:27 +000097 MachineFunction &MF = *SU->getInstr()->getParent()->getParent();
98 auto &QII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
99
Sergei Larin4d8986a2012-09-04 14:49:56 +0000100 // Now see if there are no other dependencies to instructions already
101 // in the packet.
102 for (unsigned i = 0, e = Packet.size(); i != e; ++i) {
103 if (Packet[i]->Succs.size() == 0)
104 continue;
Krzysztof Parzyszek786333f2016-07-18 16:05:27 +0000105
106 // Enable .cur formation.
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000107 if (QII.mayBeCurLoad(*Packet[i]->getInstr()))
Krzysztof Parzyszek786333f2016-07-18 16:05:27 +0000108 continue;
109
Sergei Larin4d8986a2012-09-04 14:49:56 +0000110 for (SUnit::const_succ_iterator I = Packet[i]->Succs.begin(),
111 E = Packet[i]->Succs.end(); I != E; ++I) {
112 // Since we do not add pseudos to packets, might as well
113 // ignore order dependencies.
114 if (I->isCtrl())
115 continue;
116
117 if (I->getSUnit() == SU)
118 return false;
119 }
120 }
121 return true;
122}
123
124/// Keep track of available resources.
Sergei Larinef4cc112012-09-10 17:31:34 +0000125bool VLIWResourceModel::reserveResources(SUnit *SU) {
126 bool startNewCycle = false;
Sergei Larin2db64a72012-09-14 15:07:59 +0000127 // Artificially reset state.
128 if (!SU) {
129 ResourcesModel->clearResources();
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000130 savePacket();
Sergei Larin2db64a72012-09-14 15:07:59 +0000131 Packet.clear();
132 TotalPackets++;
133 return false;
134 }
Sergei Larin4d8986a2012-09-04 14:49:56 +0000135 // If this SU does not fit in the packet
136 // start a new one.
137 if (!isResourceAvailable(SU)) {
138 ResourcesModel->clearResources();
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000139 savePacket();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000140 Packet.clear();
141 TotalPackets++;
Sergei Larinef4cc112012-09-10 17:31:34 +0000142 startNewCycle = true;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000143 }
144
145 switch (SU->getInstr()->getOpcode()) {
146 default:
Duncan P. N. Exon Smith57022872016-02-27 19:09:00 +0000147 ResourcesModel->reserveResources(*SU->getInstr());
Sergei Larin4d8986a2012-09-04 14:49:56 +0000148 break;
149 case TargetOpcode::EXTRACT_SUBREG:
150 case TargetOpcode::INSERT_SUBREG:
151 case TargetOpcode::SUBREG_TO_REG:
152 case TargetOpcode::REG_SEQUENCE:
153 case TargetOpcode::IMPLICIT_DEF:
154 case TargetOpcode::KILL:
Rafael Espindolab1f25f12014-03-07 06:08:31 +0000155 case TargetOpcode::CFI_INSTRUCTION:
Sergei Larin4d8986a2012-09-04 14:49:56 +0000156 case TargetOpcode::EH_LABEL:
157 case TargetOpcode::COPY:
158 case TargetOpcode::INLINEASM:
159 break;
160 }
161 Packet.push_back(SU);
162
163#ifndef NDEBUG
164 DEBUG(dbgs() << "Packet[" << TotalPackets << "]:\n");
165 for (unsigned i = 0, e = Packet.size(); i != e; ++i) {
166 DEBUG(dbgs() << "\t[" << i << "] SU(");
Sergei Larinef4cc112012-09-10 17:31:34 +0000167 DEBUG(dbgs() << Packet[i]->NodeNum << ")\t");
168 DEBUG(Packet[i]->getInstr()->dump());
Sergei Larin4d8986a2012-09-04 14:49:56 +0000169 }
170#endif
171
172 // If packet is now full, reset the state so in the next cycle
173 // we start fresh.
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000174 if (Packet.size() >= SchedModel->getIssueWidth()) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000175 ResourcesModel->clearResources();
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000176 savePacket();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000177 Packet.clear();
178 TotalPackets++;
Sergei Larinef4cc112012-09-10 17:31:34 +0000179 startNewCycle = true;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000180 }
Sergei Larinef4cc112012-09-10 17:31:34 +0000181
182 return startNewCycle;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000183}
184
Sergei Larin4d8986a2012-09-04 14:49:56 +0000185/// schedule - Called back from MachineScheduler::runOnMachineFunction
186/// after setting up the current scheduling region. [RegionBegin, RegionEnd)
187/// only includes instructions that have DAG nodes, not scheduling boundaries.
188void VLIWMachineScheduler::schedule() {
189 DEBUG(dbgs()
190 << "********** MI Converging Scheduling VLIW BB#" << BB->getNumber()
191 << " " << BB->getName()
192 << " in_func " << BB->getParent()->getFunction()->getName()
Alexey Samsonov8968e6d2014-08-20 19:36:05 +0000193 << " at loop depth " << MLI->getLoopDepth(BB)
Sergei Larin4d8986a2012-09-04 14:49:56 +0000194 << " \n");
195
Andrew Trick7a8e1002012-09-11 00:39:15 +0000196 buildDAGWithRegPressure();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000197
Andrew Tricke2c3f5c2013-01-25 06:33:57 +0000198 SmallVector<SUnit*, 8> TopRoots, BotRoots;
199 findRootsAndBiasEdges(TopRoots, BotRoots);
200
201 // Initialize the strategy before modifying the DAG.
202 SchedImpl->initialize(this);
203
Sergei Larinef4cc112012-09-10 17:31:34 +0000204 DEBUG(unsigned maxH = 0;
205 for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
206 if (SUnits[su].getHeight() > maxH)
207 maxH = SUnits[su].getHeight();
208 dbgs() << "Max Height " << maxH << "\n";);
209 DEBUG(unsigned maxD = 0;
210 for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
211 if (SUnits[su].getDepth() > maxD)
212 maxD = SUnits[su].getDepth();
213 dbgs() << "Max Depth " << maxD << "\n";);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000214 DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
215 SUnits[su].dumpAll(this));
216
Andrew Tricke2c3f5c2013-01-25 06:33:57 +0000217 initQueues(TopRoots, BotRoots);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000218
Sergei Larin4d8986a2012-09-04 14:49:56 +0000219 bool IsTopNode = false;
James Y Knighte72b0db2015-09-18 18:52:20 +0000220 while (true) {
221 DEBUG(dbgs() << "** VLIWMachineScheduler::schedule picking next node\n");
222 SUnit *SU = SchedImpl->pickNode(IsTopNode);
223 if (!SU) break;
224
Sergei Larin4d8986a2012-09-04 14:49:56 +0000225 if (!checkSchedLimit())
226 break;
227
Andrew Trick7a8e1002012-09-11 00:39:15 +0000228 scheduleMI(SU, IsTopNode);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000229
Andrew Trick7a8e1002012-09-11 00:39:15 +0000230 updateQueues(SU, IsTopNode);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000231
232 // Notify the scheduling strategy after updating the DAG.
233 SchedImpl->schedNode(SU, IsTopNode);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000234 }
235 assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
236
Sergei Larin4d8986a2012-09-04 14:49:56 +0000237 placeDebugValues();
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000238
239 DEBUG({
240 unsigned BBNum = begin()->getParent()->getNumber();
241 dbgs() << "*** Final schedule for BB#" << BBNum << " ***\n";
242 dumpSchedule();
243 dbgs() << '\n';
244 });
Sergei Larin4d8986a2012-09-04 14:49:56 +0000245}
246
Andrew Trick7a8e1002012-09-11 00:39:15 +0000247void ConvergingVLIWScheduler::initialize(ScheduleDAGMI *dag) {
248 DAG = static_cast<VLIWMachineScheduler*>(dag);
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000249 SchedModel = DAG->getSchedModel();
Andrew Trick553e0fe2013-02-13 19:22:27 +0000250
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000251 Top.init(DAG, SchedModel);
252 Bot.init(DAG, SchedModel);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000253
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000254 // Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
255 // are disabled, then these HazardRecs will be disabled.
256 const InstrItineraryData *Itin = DAG->getSchedModel()->getInstrItineraries();
Eric Christopherf8b8e4a2015-02-02 22:11:40 +0000257 const TargetSubtargetInfo &STI = DAG->MF.getSubtarget();
258 const TargetInstrInfo *TII = STI.getInstrInfo();
Andrew Trick553e0fe2013-02-13 19:22:27 +0000259 delete Top.HazardRec;
260 delete Bot.HazardRec;
Eric Christopherf8b8e4a2015-02-02 22:11:40 +0000261 Top.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG);
262 Bot.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000263
Chandler Carruthc18e39c2013-07-27 10:48:45 +0000264 delete Top.ResourceModel;
265 delete Bot.ResourceModel;
Eric Christopherf8b8e4a2015-02-02 22:11:40 +0000266 Top.ResourceModel = new VLIWResourceModel(STI, DAG->getSchedModel());
267 Bot.ResourceModel = new VLIWResourceModel(STI, DAG->getSchedModel());
Sergei Larinef4cc112012-09-10 17:31:34 +0000268
Eugene Zelenko3b873362017-09-28 22:27:31 +0000269 assert((!ForceTopDown || !ForceBottomUp) &&
Sergei Larin4d8986a2012-09-04 14:49:56 +0000270 "-misched-topdown incompatible with -misched-bottomup");
271}
272
273void ConvergingVLIWScheduler::releaseTopNode(SUnit *SU) {
274 if (SU->isScheduled)
275 return;
276
Krzysztof Parzyszek2be7ead2016-07-18 16:15:15 +0000277 for (const SDep &PI : SU->Preds) {
278 unsigned PredReadyCycle = PI.getSUnit()->TopReadyCycle;
279 unsigned MinLatency = PI.getLatency();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000280#ifndef NDEBUG
281 Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency);
282#endif
283 if (SU->TopReadyCycle < PredReadyCycle + MinLatency)
284 SU->TopReadyCycle = PredReadyCycle + MinLatency;
285 }
286 Top.releaseNode(SU, SU->TopReadyCycle);
287}
288
289void ConvergingVLIWScheduler::releaseBottomNode(SUnit *SU) {
290 if (SU->isScheduled)
291 return;
292
293 assert(SU->getInstr() && "Scheduled SUnit must have instr");
294
295 for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
296 I != E; ++I) {
297 unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle;
Andrew Trickde2109e2013-06-15 04:49:57 +0000298 unsigned MinLatency = I->getLatency();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000299#ifndef NDEBUG
300 Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency);
301#endif
302 if (SU->BotReadyCycle < SuccReadyCycle + MinLatency)
303 SU->BotReadyCycle = SuccReadyCycle + MinLatency;
304 }
305 Bot.releaseNode(SU, SU->BotReadyCycle);
306}
307
308/// Does this SU have a hazard within the current instruction group.
309///
310/// The scheduler supports two modes of hazard recognition. The first is the
311/// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that
312/// supports highly complicated in-order reservation tables
313/// (ScoreboardHazardRecognizer) and arbitrary target-specific logic.
314///
315/// The second is a streamlined mechanism that checks for hazards based on
316/// simple counters that the scheduler itself maintains. It explicitly checks
317/// for instruction dispatch limitations, including the number of micro-ops that
318/// can dispatch per cycle.
319///
320/// TODO: Also check whether the SU must start a new group.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000321bool ConvergingVLIWScheduler::VLIWSchedBoundary::checkHazard(SUnit *SU) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000322 if (HazardRec->isEnabled())
323 return HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard;
324
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000325 unsigned uops = SchedModel->getNumMicroOps(SU->getInstr());
326 if (IssueCount + uops > SchedModel->getIssueWidth())
Sergei Larin4d8986a2012-09-04 14:49:56 +0000327 return true;
328
329 return false;
330}
331
Andrew Trickd7f890e2013-12-28 21:56:47 +0000332void ConvergingVLIWScheduler::VLIWSchedBoundary::releaseNode(SUnit *SU,
Sergei Larin4d8986a2012-09-04 14:49:56 +0000333 unsigned ReadyCycle) {
334 if (ReadyCycle < MinReadyCycle)
335 MinReadyCycle = ReadyCycle;
336
337 // Check for interlocks first. For the purpose of other heuristics, an
338 // instruction that cannot issue appears as if it's not in the ReadyQueue.
339 if (ReadyCycle > CurrCycle || checkHazard(SU))
340
341 Pending.push(SU);
342 else
343 Available.push(SU);
344}
345
346/// Move the boundary of scheduled code by one cycle.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000347void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpCycle() {
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000348 unsigned Width = SchedModel->getIssueWidth();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000349 IssueCount = (IssueCount <= Width) ? 0 : IssueCount - Width;
350
Eugene Zelenko3b873362017-09-28 22:27:31 +0000351 assert(MinReadyCycle < std::numeric_limits<unsigned>::max() &&
352 "MinReadyCycle uninitialized");
Sergei Larin4d8986a2012-09-04 14:49:56 +0000353 unsigned NextCycle = std::max(CurrCycle + 1, MinReadyCycle);
354
355 if (!HazardRec->isEnabled()) {
356 // Bypass HazardRec virtual calls.
357 CurrCycle = NextCycle;
Sergei Larinef4cc112012-09-10 17:31:34 +0000358 } else {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000359 // Bypass getHazardType calls in case of long latency.
360 for (; CurrCycle != NextCycle; ++CurrCycle) {
361 if (isTop())
362 HazardRec->AdvanceCycle();
363 else
364 HazardRec->RecedeCycle();
365 }
366 }
367 CheckPending = true;
368
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000369 DEBUG(dbgs() << "*** Next cycle " << Available.getName() << " cycle "
370 << CurrCycle << '\n');
Sergei Larin4d8986a2012-09-04 14:49:56 +0000371}
372
373/// Move the boundary of scheduled code by one SUnit.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000374void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpNode(SUnit *SU) {
Sergei Larinef4cc112012-09-10 17:31:34 +0000375 bool startNewCycle = false;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000376
377 // Update the reservation table.
378 if (HazardRec->isEnabled()) {
379 if (!isTop() && SU->isCall) {
380 // Calls are scheduled with their preceding instructions. For bottom-up
381 // scheduling, clear the pipeline state before emitting.
382 HazardRec->Reset();
383 }
384 HazardRec->EmitInstruction(SU);
385 }
Sergei Larinef4cc112012-09-10 17:31:34 +0000386
387 // Update DFA model.
388 startNewCycle = ResourceModel->reserveResources(SU);
389
Sergei Larin4d8986a2012-09-04 14:49:56 +0000390 // Check the instruction group dispatch limit.
391 // TODO: Check if this SU must end a dispatch group.
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000392 IssueCount += SchedModel->getNumMicroOps(SU->getInstr());
Sergei Larinef4cc112012-09-10 17:31:34 +0000393 if (startNewCycle) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000394 DEBUG(dbgs() << "*** Max instrs at cycle " << CurrCycle << '\n');
395 bumpCycle();
396 }
Sergei Larinef4cc112012-09-10 17:31:34 +0000397 else
398 DEBUG(dbgs() << "*** IssueCount " << IssueCount
399 << " at cycle " << CurrCycle << '\n');
Sergei Larin4d8986a2012-09-04 14:49:56 +0000400}
401
402/// Release pending ready nodes in to the available queue. This makes them
403/// visible to heuristics.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000404void ConvergingVLIWScheduler::VLIWSchedBoundary::releasePending() {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000405 // If the available queue is empty, it is safe to reset MinReadyCycle.
406 if (Available.empty())
Eugene Zelenko3b873362017-09-28 22:27:31 +0000407 MinReadyCycle = std::numeric_limits<unsigned>::max();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000408
409 // Check to see if any of the pending instructions are ready to issue. If
410 // so, add them to the available queue.
411 for (unsigned i = 0, e = Pending.size(); i != e; ++i) {
412 SUnit *SU = *(Pending.begin()+i);
413 unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle;
414
415 if (ReadyCycle < MinReadyCycle)
416 MinReadyCycle = ReadyCycle;
417
418 if (ReadyCycle > CurrCycle)
419 continue;
420
421 if (checkHazard(SU))
422 continue;
423
424 Available.push(SU);
425 Pending.remove(Pending.begin()+i);
426 --i; --e;
427 }
428 CheckPending = false;
429}
430
431/// Remove SU from the ready set for this boundary.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000432void ConvergingVLIWScheduler::VLIWSchedBoundary::removeReady(SUnit *SU) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000433 if (Available.isInQueue(SU))
434 Available.remove(Available.find(SU));
435 else {
436 assert(Pending.isInQueue(SU) && "bad ready count");
437 Pending.remove(Pending.find(SU));
438 }
439}
440
441/// If this queue only has one ready candidate, return it. As a side effect,
442/// advance the cycle until at least one node is ready. If multiple instructions
443/// are ready, return NULL.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000444SUnit *ConvergingVLIWScheduler::VLIWSchedBoundary::pickOnlyChoice() {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000445 if (CheckPending)
446 releasePending();
447
448 for (unsigned i = 0; Available.empty(); ++i) {
449 assert(i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) &&
450 "permanent hazard"); (void)i;
Craig Topper062a2ba2014-04-25 05:30:21 +0000451 ResourceModel->reserveResources(nullptr);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000452 bumpCycle();
453 releasePending();
454 }
455 if (Available.size() == 1)
456 return *Available.begin();
Craig Topper062a2ba2014-04-25 05:30:21 +0000457 return nullptr;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000458}
459
460#ifndef NDEBUG
Sergei Larinef4cc112012-09-10 17:31:34 +0000461void ConvergingVLIWScheduler::traceCandidate(const char *Label,
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000462 const ReadyQueue &Q, SUnit *SU, int Cost, PressureChange P) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000463 dbgs() << Label << " " << Q.getName() << " ";
464 if (P.isValid())
Andrew Trick1a831342013-08-30 03:49:48 +0000465 dbgs() << DAG->TRI->getRegPressureSetName(P.getPSet()) << ":"
466 << P.getUnitInc() << " ";
Sergei Larin4d8986a2012-09-04 14:49:56 +0000467 else
468 dbgs() << " ";
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000469 dbgs() << "cost(" << Cost << ")\t";
Sergei Larin4d8986a2012-09-04 14:49:56 +0000470 SU->dump(DAG);
471}
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000472
473// Very detailed queue dump, to be used with higher verbosity levels.
474void ConvergingVLIWScheduler::readyQueueVerboseDump(
475 const RegPressureTracker &RPTracker, SchedCandidate &Candidate,
476 ReadyQueue &Q) {
477 RegPressureTracker &TempTracker = const_cast<RegPressureTracker &>(RPTracker);
478
479 dbgs() << ">>> " << Q.getName() << "\n";
480 for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) {
481 RegPressureDelta RPDelta;
482 TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
483 DAG->getRegionCriticalPSets(),
484 DAG->getRegPressure().MaxSetPressure);
485 std::stringstream dbgstr;
486 dbgstr << "SU(" << std::setw(3) << (*I)->NodeNum << ")";
487 dbgs() << dbgstr.str();
488 SchedulingCost(Q, *I, Candidate, RPDelta, true);
489 dbgs() << "\t";
490 (*I)->getInstr()->dump();
491 }
492 dbgs() << "\n";
493}
Sergei Larin4d8986a2012-09-04 14:49:56 +0000494#endif
495
Nirav Dave6a38cc62017-06-08 18:49:25 +0000496/// isSingleUnscheduledPred - If SU2 is the only unscheduled predecessor
497/// of SU, return true (we may have duplicates)
498static inline bool isSingleUnscheduledPred(SUnit *SU, SUnit *SU2) {
499 if (SU->NumPredsLeft == 0)
500 return false;
501
502 for (auto &Pred : SU->Preds) {
503 // We found an available, but not scheduled, predecessor.
504 if (!Pred.getSUnit()->isScheduled && (Pred.getSUnit() != SU2))
505 return false;
Sergei Larinef4cc112012-09-10 17:31:34 +0000506 }
Nirav Dave6a38cc62017-06-08 18:49:25 +0000507
508 return true;
Sergei Larinef4cc112012-09-10 17:31:34 +0000509}
510
Nirav Dave6a38cc62017-06-08 18:49:25 +0000511/// isSingleUnscheduledSucc - If SU2 is the only unscheduled successor
512/// of SU, return true (we may have duplicates)
513static inline bool isSingleUnscheduledSucc(SUnit *SU, SUnit *SU2) {
514 if (SU->NumSuccsLeft == 0)
515 return false;
516
517 for (auto &Succ : SU->Succs) {
518 // We found an available, but not scheduled, successor.
519 if (!Succ.getSUnit()->isScheduled && (Succ.getSUnit() != SU2))
520 return false;
Sergei Larinef4cc112012-09-10 17:31:34 +0000521 }
Nirav Dave6a38cc62017-06-08 18:49:25 +0000522 return true;
Sergei Larinef4cc112012-09-10 17:31:34 +0000523}
524
Sergei Larin4d8986a2012-09-04 14:49:56 +0000525// Constants used to denote relative importance of
526// heuristic components for cost computation.
527static const unsigned PriorityOne = 200;
Eli Friedman8f06d552013-09-11 00:41:02 +0000528static const unsigned PriorityTwo = 50;
Krzysztof Parzyszek748d3ef2016-07-18 14:23:10 +0000529static const unsigned PriorityThree = 75;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000530static const unsigned ScaleTwo = 10;
531static const unsigned FactorOne = 2;
532
533/// Single point to compute overall scheduling cost.
534/// TODO: More heuristics will be used soon.
535int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
536 SchedCandidate &Candidate,
537 RegPressureDelta &Delta,
538 bool verbose) {
539 // Initial trivial priority.
540 int ResCount = 1;
541
542 // Do not waste time on a node that is already scheduled.
543 if (!SU || SU->isScheduled)
544 return ResCount;
545
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000546 MachineInstr &Instr = *SU->getInstr();
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000547
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000548 DEBUG(if (verbose) dbgs() << ((Q.getID() == TopQID) ? "(top|" : "(bot|"));
Sergei Larin4d8986a2012-09-04 14:49:56 +0000549 // Forced priority is high.
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000550 if (SU->isScheduleHigh) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000551 ResCount += PriorityOne;
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000552 DEBUG(dbgs() << "H|");
553 }
Sergei Larin4d8986a2012-09-04 14:49:56 +0000554
555 // Critical path first.
Sergei Larinef4cc112012-09-10 17:31:34 +0000556 if (Q.getID() == TopQID) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000557 ResCount += (SU->getHeight() * ScaleTwo);
Sergei Larinef4cc112012-09-10 17:31:34 +0000558
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000559 DEBUG(if (verbose) {
560 std::stringstream dbgstr;
561 dbgstr << "h" << std::setw(3) << SU->getHeight() << "|";
562 dbgs() << dbgstr.str();
563 });
564
Sergei Larinef4cc112012-09-10 17:31:34 +0000565 // If resources are available for it, multiply the
566 // chance of scheduling.
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +0000567 if (Top.ResourceModel->isResourceAvailable(SU)) {
Sergei Larinef4cc112012-09-10 17:31:34 +0000568 ResCount <<= FactorOne;
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +0000569 ResCount += PriorityThree;
570 DEBUG(if (verbose) dbgs() << "A|");
571 } else
572 DEBUG(if (verbose) dbgs() << " |");
Sergei Larinef4cc112012-09-10 17:31:34 +0000573 } else {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000574 ResCount += (SU->getDepth() * ScaleTwo);
575
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000576 DEBUG(if (verbose) {
577 std::stringstream dbgstr;
578 dbgstr << "d" << std::setw(3) << SU->getDepth() << "|";
579 dbgs() << dbgstr.str();
580 });
581
Sergei Larinef4cc112012-09-10 17:31:34 +0000582 // If resources are available for it, multiply the
583 // chance of scheduling.
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +0000584 if (Bot.ResourceModel->isResourceAvailable(SU)) {
Sergei Larinef4cc112012-09-10 17:31:34 +0000585 ResCount <<= FactorOne;
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +0000586 ResCount += PriorityThree;
587 DEBUG(if (verbose) dbgs() << "A|");
588 } else
589 DEBUG(if (verbose) dbgs() << " |");
Sergei Larinef4cc112012-09-10 17:31:34 +0000590 }
591
592 unsigned NumNodesBlocking = 0;
593 if (Q.getID() == TopQID) {
594 // How many SUs does it block from scheduling?
595 // Look at all of the successors of this node.
596 // Count the number of nodes that
597 // this node is the sole unscheduled node for.
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +0000598 for (const SDep &SI : SU->Succs)
Nirav Dave6a38cc62017-06-08 18:49:25 +0000599 if (isSingleUnscheduledPred(SI.getSUnit(), SU))
Sergei Larinef4cc112012-09-10 17:31:34 +0000600 ++NumNodesBlocking;
601 } else {
602 // How many unscheduled predecessors block this node?
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +0000603 for (const SDep &PI : SU->Preds)
Nirav Dave6a38cc62017-06-08 18:49:25 +0000604 if (isSingleUnscheduledSucc(PI.getSUnit(), SU))
Sergei Larinef4cc112012-09-10 17:31:34 +0000605 ++NumNodesBlocking;
606 }
607 ResCount += (NumNodesBlocking * ScaleTwo);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000608
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000609 DEBUG(if (verbose) {
610 std::stringstream dbgstr;
611 dbgstr << "blk " << std::setw(2) << NumNodesBlocking << ")|";
612 dbgs() << dbgstr.str();
613 });
614
Sergei Larin4d8986a2012-09-04 14:49:56 +0000615 // Factor in reg pressure as a heuristic.
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +0000616 if (!IgnoreBBRegPressure) {
617 // Decrease priority by the amount that register pressure exceeds the limit.
618 ResCount -= (Delta.Excess.getUnitInc()*PriorityOne);
619 // Decrease priority if register pressure exceeds the limit.
620 ResCount -= (Delta.CriticalMax.getUnitInc()*PriorityOne);
621 // Decrease priority slightly if register pressure would increase over the
622 // current maximum.
623 ResCount -= (Delta.CurrentMax.getUnitInc()*PriorityTwo);
624 DEBUG(if (verbose) {
625 dbgs() << "RP " << Delta.Excess.getUnitInc() << "/"
626 << Delta.CriticalMax.getUnitInc() <<"/"
627 << Delta.CurrentMax.getUnitInc() << ")|";
628 });
629 }
Sergei Larin4d8986a2012-09-04 14:49:56 +0000630
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +0000631 // Give a little extra priority to a .cur instruction if there is a resource
632 // available for it.
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000633 auto &QST = DAG->MF.getSubtarget<HexagonSubtarget>();
634 auto &QII = *QST.getInstrInfo();
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000635 if (SU->isInstr() && QII.mayBeCurLoad(*SU->getInstr())) {
Krzysztof Parzyszek748d3ef2016-07-18 14:23:10 +0000636 if (Q.getID() == TopQID && Top.ResourceModel->isResourceAvailable(SU)) {
637 ResCount += PriorityTwo;
638 DEBUG(if (verbose) dbgs() << "C|");
639 } else if (Q.getID() == BotQID &&
640 Bot.ResourceModel->isResourceAvailable(SU)) {
641 ResCount += PriorityTwo;
642 DEBUG(if (verbose) dbgs() << "C|");
643 }
644 }
645
Krzysztof Parzyszek408e3002016-07-15 21:34:02 +0000646 // Give preference to a zero latency instruction if the dependent
647 // instruction is in the current packet.
648 if (Q.getID() == TopQID) {
649 for (const SDep &PI : SU->Preds) {
650 if (!PI.getSUnit()->getInstr()->isPseudo() && PI.isAssignedRegDep() &&
651 PI.getLatency() == 0 &&
652 Top.ResourceModel->isInPacket(PI.getSUnit())) {
Krzysztof Parzyszek748d3ef2016-07-18 14:23:10 +0000653 ResCount += PriorityThree;
Krzysztof Parzyszek408e3002016-07-15 21:34:02 +0000654 DEBUG(if (verbose) dbgs() << "Z|");
655 }
656 }
657 } else {
658 for (const SDep &SI : SU->Succs) {
659 if (!SI.getSUnit()->getInstr()->isPseudo() && SI.isAssignedRegDep() &&
660 SI.getLatency() == 0 &&
661 Bot.ResourceModel->isInPacket(SI.getSUnit())) {
Krzysztof Parzyszek748d3ef2016-07-18 14:23:10 +0000662 ResCount += PriorityThree;
Krzysztof Parzyszek408e3002016-07-15 21:34:02 +0000663 DEBUG(if (verbose) dbgs() << "Z|");
664 }
665 }
666 }
667
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000668 // Give less preference to an instruction that will cause a stall with
669 // an instruction in the previous packet.
Krzysztof Parzyszek2af50372017-05-03 20:10:36 +0000670 if (QII.isHVXVec(Instr)) {
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000671 // Check for stalls in the previous packet.
672 if (Q.getID() == TopQID) {
673 for (auto J : Top.ResourceModel->OldPacket)
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000674 if (QII.producesStall(*J->getInstr(), Instr))
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000675 ResCount -= PriorityOne;
676 } else {
677 for (auto J : Bot.ResourceModel->OldPacket)
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000678 if (QII.producesStall(Instr, *J->getInstr()))
Krzysztof Parzyszek6c715e12016-07-15 20:16:03 +0000679 ResCount -= PriorityOne;
680 }
681 }
682
Krzysztof Parzyszek3467e9d2016-07-18 14:52:13 +0000683 // If the instruction has a non-zero latency dependence with an instruction in
684 // the current packet, then it should not be scheduled yet. The case occurs
685 // when the dependent instruction is scheduled in a new packet, so the
686 // scheduler updates the current cycle and pending instructions become
687 // available.
688 if (CheckEarlyAvail) {
689 if (Q.getID() == TopQID) {
690 for (const auto &PI : SU->Preds) {
691 if (PI.getLatency() > 0 &&
692 Top.ResourceModel->isInPacket(PI.getSUnit())) {
693 ResCount -= PriorityOne;
694 DEBUG(if (verbose) dbgs() << "D|");
695 }
696 }
697 } else {
698 for (const auto &SI : SU->Succs) {
699 if (SI.getLatency() > 0 &&
700 Bot.ResourceModel->isInPacket(SI.getSUnit())) {
701 ResCount -= PriorityOne;
702 DEBUG(if (verbose) dbgs() << "D|");
703 }
704 }
705 }
706 }
707
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000708 DEBUG(if (verbose) {
709 std::stringstream dbgstr;
710 dbgstr << "Total " << std::setw(4) << ResCount << ")";
711 dbgs() << dbgstr.str();
712 });
Sergei Larin4d8986a2012-09-04 14:49:56 +0000713
714 return ResCount;
715}
716
717/// Pick the best candidate from the top queue.
718///
719/// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during
720/// DAG building. To adjust for the current scheduling location we need to
721/// maintain the number of vreg uses remaining to be top-scheduled.
722ConvergingVLIWScheduler::CandResult ConvergingVLIWScheduler::
723pickNodeFromQueue(ReadyQueue &Q, const RegPressureTracker &RPTracker,
724 SchedCandidate &Candidate) {
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000725 DEBUG(if (SchedDebugVerboseLevel > 1)
726 readyQueueVerboseDump(RPTracker, Candidate, Q);
727 else Q.dump(););
Sergei Larin4d8986a2012-09-04 14:49:56 +0000728
729 // getMaxPressureDelta temporarily modifies the tracker.
730 RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker);
731
732 // BestSU remains NULL if no top candidates beat the best existing candidate.
733 CandResult FoundCandidate = NoCand;
734 for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) {
735 RegPressureDelta RPDelta;
736 TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
737 DAG->getRegionCriticalPSets(),
738 DAG->getRegPressure().MaxSetPressure);
739
740 int CurrentCost = SchedulingCost(Q, *I, Candidate, RPDelta, false);
741
742 // Initialize the candidate if needed.
743 if (!Candidate.SU) {
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000744 DEBUG(traceCandidate("DCAND", Q, *I, CurrentCost));
Sergei Larin4d8986a2012-09-04 14:49:56 +0000745 Candidate.SU = *I;
746 Candidate.RPDelta = RPDelta;
747 Candidate.SCost = CurrentCost;
748 FoundCandidate = NodeOrder;
749 continue;
750 }
751
Sergei Larin4d8986a2012-09-04 14:49:56 +0000752 // Best cost.
753 if (CurrentCost > Candidate.SCost) {
Krzysztof Parzyszekf05dc4d2016-07-18 15:47:25 +0000754 DEBUG(traceCandidate("CCAND", Q, *I, CurrentCost));
Sergei Larin4d8986a2012-09-04 14:49:56 +0000755 Candidate.SU = *I;
756 Candidate.RPDelta = RPDelta;
757 Candidate.SCost = CurrentCost;
758 FoundCandidate = BestCost;
759 continue;
760 }
761
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000762 // Tie breaker using Timing Class.
763 if (!DisableTCTie) {
764 auto &QST = DAG->MF.getSubtarget<HexagonSubtarget>();
765 auto &QII = *QST.getInstrInfo();
766
767 const MachineInstr *MI = (*I)->getInstr();
768 const MachineInstr *CandI = Candidate.SU->getInstr();
769 const InstrItineraryData *InstrItins = QST.getInstrItineraryData();
770
Krzysztof Parzyszekf0b34a52016-07-29 21:49:42 +0000771 unsigned InstrLatency = QII.getInstrTimingClassLatency(InstrItins, *MI);
772 unsigned CandLatency = QII.getInstrTimingClassLatency(InstrItins, *CandI);
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000773 DEBUG(dbgs() << "TC Tie Breaker Cand: "
774 << CandLatency << " Instr:" << InstrLatency << "\n"
775 << *MI << *CandI << "\n");
776 if (Q.getID() == TopQID && CurrentCost == Candidate.SCost) {
777 if (InstrLatency < CandLatency && TopUseShorterTie) {
778 Candidate.SU = *I;
779 Candidate.RPDelta = RPDelta;
780 Candidate.SCost = CurrentCost;
781 FoundCandidate = BestCost;
782 DEBUG(dbgs() << "Used top shorter tie breaker\n");
783 continue;
784 } else if (InstrLatency > CandLatency && !TopUseShorterTie) {
785 Candidate.SU = *I;
786 Candidate.RPDelta = RPDelta;
787 Candidate.SCost = CurrentCost;
788 FoundCandidate = BestCost;
789 DEBUG(dbgs() << "Used top longer tie breaker\n");
790 continue;
791 }
792 } else if (Q.getID() == BotQID && CurrentCost == Candidate.SCost) {
793 if (InstrLatency < CandLatency && BotUseShorterTie) {
794 Candidate.SU = *I;
795 Candidate.RPDelta = RPDelta;
796 Candidate.SCost = CurrentCost;
797 FoundCandidate = BestCost;
798 DEBUG(dbgs() << "Used Bot shorter tie breaker\n");
799 continue;
800 } else if (InstrLatency > CandLatency && !BotUseShorterTie) {
801 Candidate.SU = *I;
802 Candidate.RPDelta = RPDelta;
803 Candidate.SCost = CurrentCost;
804 FoundCandidate = BestCost;
805 DEBUG(dbgs() << "Used Bot longer tie breaker\n");
806 continue;
807 }
808 }
809 }
810
Krzysztof Parzyszek748d3ef2016-07-18 14:23:10 +0000811 if (CurrentCost == Candidate.SCost) {
812 if ((Q.getID() == TopQID &&
813 (*I)->Succs.size() > Candidate.SU->Succs.size()) ||
814 (Q.getID() == BotQID &&
815 (*I)->Preds.size() < Candidate.SU->Preds.size())) {
816 DEBUG(traceCandidate("SPCAND", Q, *I, CurrentCost));
817 Candidate.SU = *I;
818 Candidate.RPDelta = RPDelta;
819 Candidate.SCost = CurrentCost;
820 FoundCandidate = BestCost;
821 continue;
822 }
823 }
824
Sergei Larin4d8986a2012-09-04 14:49:56 +0000825 // Fall through to original instruction order.
826 // Only consider node order if Candidate was chosen from this Q.
827 if (FoundCandidate == NoCand)
828 continue;
829 }
830 return FoundCandidate;
831}
832
833/// Pick the best candidate node from either the top or bottom queue.
834SUnit *ConvergingVLIWScheduler::pickNodeBidrectional(bool &IsTopNode) {
835 // Schedule as far as possible in the direction of no choice. This is most
836 // efficient, but also provides the best heuristics for CriticalPSets.
837 if (SUnit *SU = Bot.pickOnlyChoice()) {
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000838 DEBUG(dbgs() << "Picked only Bottom\n");
Sergei Larin4d8986a2012-09-04 14:49:56 +0000839 IsTopNode = false;
840 return SU;
841 }
842 if (SUnit *SU = Top.pickOnlyChoice()) {
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000843 DEBUG(dbgs() << "Picked only Top\n");
Sergei Larin4d8986a2012-09-04 14:49:56 +0000844 IsTopNode = true;
845 return SU;
846 }
847 SchedCandidate BotCand;
848 // Prefer bottom scheduling when heuristics are silent.
849 CandResult BotResult = pickNodeFromQueue(Bot.Available,
850 DAG->getBotRPTracker(), BotCand);
851 assert(BotResult != NoCand && "failed to find the first candidate");
852
853 // If either Q has a single candidate that provides the least increase in
854 // Excess pressure, we can immediately schedule from that Q.
855 //
856 // RegionCriticalPSets summarizes the pressure within the scheduled region and
857 // affects picking from either Q. If scheduling in one direction must
858 // increase pressure for one of the excess PSets, then schedule in that
859 // direction first to provide more freedom in the other direction.
860 if (BotResult == SingleExcess || BotResult == SingleCritical) {
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000861 DEBUG(dbgs() << "Prefered Bottom Node\n");
Sergei Larin4d8986a2012-09-04 14:49:56 +0000862 IsTopNode = false;
863 return BotCand.SU;
864 }
865 // Check if the top Q has a better candidate.
866 SchedCandidate TopCand;
867 CandResult TopResult = pickNodeFromQueue(Top.Available,
868 DAG->getTopRPTracker(), TopCand);
869 assert(TopResult != NoCand && "failed to find the first candidate");
870
871 if (TopResult == SingleExcess || TopResult == SingleCritical) {
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000872 DEBUG(dbgs() << "Prefered Top Node\n");
Sergei Larin4d8986a2012-09-04 14:49:56 +0000873 IsTopNode = true;
874 return TopCand.SU;
875 }
876 // If either Q has a single candidate that minimizes pressure above the
877 // original region's pressure pick it.
878 if (BotResult == SingleMax) {
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000879 DEBUG(dbgs() << "Prefered Bottom Node SingleMax\n");
Sergei Larin4d8986a2012-09-04 14:49:56 +0000880 IsTopNode = false;
881 return BotCand.SU;
882 }
883 if (TopResult == SingleMax) {
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000884 DEBUG(dbgs() << "Prefered Top Node SingleMax\n");
Sergei Larin4d8986a2012-09-04 14:49:56 +0000885 IsTopNode = true;
886 return TopCand.SU;
887 }
888 if (TopCand.SCost > BotCand.SCost) {
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000889 DEBUG(dbgs() << "Prefered Top Node Cost\n");
Sergei Larin4d8986a2012-09-04 14:49:56 +0000890 IsTopNode = true;
891 return TopCand.SU;
892 }
893 // Otherwise prefer the bottom candidate in node order.
Krzysztof Parzyszek393b3792016-07-18 15:17:10 +0000894 DEBUG(dbgs() << "Prefered Bottom in Node order\n");
Sergei Larin4d8986a2012-09-04 14:49:56 +0000895 IsTopNode = false;
896 return BotCand.SU;
897}
898
899/// Pick the best node to balance the schedule. Implements MachineSchedStrategy.
900SUnit *ConvergingVLIWScheduler::pickNode(bool &IsTopNode) {
901 if (DAG->top() == DAG->bottom()) {
902 assert(Top.Available.empty() && Top.Pending.empty() &&
903 Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
Craig Topper062a2ba2014-04-25 05:30:21 +0000904 return nullptr;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000905 }
906 SUnit *SU;
Eugene Zelenko3b873362017-09-28 22:27:31 +0000907 if (ForceTopDown) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000908 SU = Top.pickOnlyChoice();
909 if (!SU) {
910 SchedCandidate TopCand;
911 CandResult TopResult =
912 pickNodeFromQueue(Top.Available, DAG->getTopRPTracker(), TopCand);
913 assert(TopResult != NoCand && "failed to find the first candidate");
914 (void)TopResult;
915 SU = TopCand.SU;
916 }
917 IsTopNode = true;
Eugene Zelenko3b873362017-09-28 22:27:31 +0000918 } else if (ForceBottomUp) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000919 SU = Bot.pickOnlyChoice();
920 if (!SU) {
921 SchedCandidate BotCand;
922 CandResult BotResult =
923 pickNodeFromQueue(Bot.Available, DAG->getBotRPTracker(), BotCand);
924 assert(BotResult != NoCand && "failed to find the first candidate");
925 (void)BotResult;
926 SU = BotCand.SU;
927 }
928 IsTopNode = false;
929 } else {
930 SU = pickNodeBidrectional(IsTopNode);
931 }
932 if (SU->isTopReady())
933 Top.removeReady(SU);
934 if (SU->isBottomReady())
935 Bot.removeReady(SU);
936
937 DEBUG(dbgs() << "*** " << (IsTopNode ? "Top" : "Bottom")
938 << " Scheduling Instruction in cycle "
939 << (IsTopNode ? Top.CurrCycle : Bot.CurrCycle) << '\n';
940 SU->dump(DAG));
941 return SU;
942}
943
944/// Update the scheduler's state after scheduling a node. This is the same node
Sergei Larinef4cc112012-09-10 17:31:34 +0000945/// that was just returned by pickNode(). However, VLIWMachineScheduler needs
946/// to update it's state based on the current cycle before MachineSchedStrategy
947/// does.
Sergei Larin4d8986a2012-09-04 14:49:56 +0000948void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) {
949 if (IsTopNode) {
950 SU->TopReadyCycle = Top.CurrCycle;
951 Top.bumpNode(SU);
Sergei Larinef4cc112012-09-10 17:31:34 +0000952 } else {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000953 SU->BotReadyCycle = Bot.CurrCycle;
954 Bot.bumpNode(SU);
955 }
956}