blob: 0cc02930fa17c18d53a129945663ca6d66a577a3 [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"
Krzysztof Parzyszek9be66732016-07-15 17:48:09 +000016#include "HexagonSubtarget.h"
Jakub Staszakdf17ddd2013-03-10 13:11:23 +000017#include "llvm/CodeGen/MachineLoopInfo.h"
Krzysztof Parzyszek9be66732016-07-15 17:48:09 +000018#include "llvm/CodeGen/ScheduleDAGMutation.h"
Jakub Staszakdf17ddd2013-03-10 13:11:23 +000019#include "llvm/IR/Function.h"
Sergei Larin4d8986a2012-09-04 14:49:56 +000020
Krzysztof Parzyszek36b0f932016-07-15 19:09:37 +000021static cl::opt<bool> SchedPredsCloser("sched-preds-closer",
22 cl::Hidden, cl::ZeroOrMore, cl::init(true));
23
24static cl::opt<bool> SchedRetvalOptimization("sched-retval-optimization",
25 cl::Hidden, cl::ZeroOrMore, cl::init(true));
26
Sergei Larin4d8986a2012-09-04 14:49:56 +000027using namespace llvm;
28
Chandler Carruth84e68b22014-04-22 02:41:26 +000029#define DEBUG_TYPE "misched"
30
Krzysztof Parzyszek36b0f932016-07-15 19:09:37 +000031class HexagonCallMutation : public ScheduleDAGMutation {
32public:
33 void apply(ScheduleDAGInstrs *DAG) override;
34private:
35 bool shouldTFRICallBind(const HexagonInstrInfo &HII,
36 const SUnit &Inst1, const SUnit &Inst2) const;
37};
38
39// Check if a call and subsequent A2_tfrpi instructions should maintain
40// scheduling affinity. We are looking for the TFRI to be consumed in
41// the next instruction. This should help reduce the instances of
42// double register pairs being allocated and scheduled before a call
43// when not used until after the call. This situation is exacerbated
44// by the fact that we allocate the pair from the callee saves list,
45// leading to excess spills and restores.
46bool HexagonCallMutation::shouldTFRICallBind(const HexagonInstrInfo &HII,
47 const SUnit &Inst1, const SUnit &Inst2) const {
48 if (Inst1.getInstr()->getOpcode() != Hexagon::A2_tfrpi)
49 return false;
50
51 // TypeXTYPE are 64 bit operations.
52 if (HII.getType(Inst2.getInstr()) == HexagonII::TypeXTYPE)
53 return true;
54 return false;
55}
56
57void HexagonCallMutation::apply(ScheduleDAGInstrs *DAG) {
Craig Topper062a2ba2014-04-25 05:30:21 +000058 SUnit* LastSequentialCall = nullptr;
Krzysztof Parzyszek36b0f932016-07-15 19:09:37 +000059 unsigned VRegHoldingRet = 0;
60 unsigned RetRegister;
61 SUnit* LastUseOfRet = nullptr;
62 auto &TRI = *DAG->MF.getSubtarget().getRegisterInfo();
63 auto &HII = *DAG->MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
64
Sergei Larin2db64a72012-09-14 15:07:59 +000065 // Currently we only catch the situation when compare gets scheduled
66 // before preceding call.
Krzysztof Parzyszek36b0f932016-07-15 19:09:37 +000067 for (unsigned su = 0, e = DAG->SUnits.size(); su != e; ++su) {
Sergei Larin2db64a72012-09-14 15:07:59 +000068 // Remember the call.
Krzysztof Parzyszek36b0f932016-07-15 19:09:37 +000069 if (DAG->SUnits[su].getInstr()->isCall())
70 LastSequentialCall = &DAG->SUnits[su];
Sergei Larin2db64a72012-09-14 15:07:59 +000071 // Look for a compare that defines a predicate.
Krzysztof Parzyszek36b0f932016-07-15 19:09:37 +000072 else if (DAG->SUnits[su].getInstr()->isCompare() && LastSequentialCall)
73 DAG->SUnits[su].addPred(SDep(LastSequentialCall, SDep::Barrier));
74 // Look for call and tfri* instructions.
75 else if (SchedPredsCloser && LastSequentialCall && su > 1 && su < e-1 &&
76 shouldTFRICallBind(HII, DAG->SUnits[su], DAG->SUnits[su+1]))
77 DAG->SUnits[su].addPred(SDep(&DAG->SUnits[su-1], SDep::Barrier));
78 // Prevent redundant register copies between two calls, which are caused by
79 // both the return value and the argument for the next call being in %R0.
80 // Example:
81 // 1: <call1>
82 // 2: %VregX = COPY %R0
83 // 3: <use of %VregX>
84 // 4: %R0 = ...
85 // 5: <call2>
86 // The scheduler would often swap 3 and 4, so an additional register is
87 // needed. This code inserts a Barrier dependence between 3 & 4 to prevent
88 // this. The same applies for %D0 and %V0/%W0, which are also handled.
89 else if (SchedRetvalOptimization) {
90 const MachineInstr *MI = DAG->SUnits[su].getInstr();
91 if (MI->isCopy() && (MI->readsRegister(Hexagon::R0, &TRI) ||
92 MI->readsRegister(Hexagon::V0, &TRI))) {
93 // %vregX = COPY %R0
94 VRegHoldingRet = MI->getOperand(0).getReg();
95 RetRegister = MI->getOperand(1).getReg();
96 LastUseOfRet = nullptr;
97 } else if (VRegHoldingRet && MI->readsVirtualRegister(VRegHoldingRet))
98 // <use of %vregX>
99 LastUseOfRet = &DAG->SUnits[su];
100 else if (LastUseOfRet && MI->definesRegister(RetRegister, &TRI))
101 // %R0 = ...
102 DAG->SUnits[su].addPred(SDep(LastUseOfRet, SDep::Barrier));
103 }
Sergei Larin2db64a72012-09-14 15:07:59 +0000104 }
105}
106
Krzysztof Parzyszek36b0f932016-07-15 19:09:37 +0000107
Sergei Larin4d8986a2012-09-04 14:49:56 +0000108/// Check if scheduling of this SU is possible
109/// in the current packet.
110/// It is _not_ precise (statefull), it is more like
111/// another heuristic. Many corner cases are figured
112/// empirically.
113bool VLIWResourceModel::isResourceAvailable(SUnit *SU) {
114 if (!SU || !SU->getInstr())
115 return false;
116
117 // First see if the pipeline could receive this instruction
118 // in the current cycle.
119 switch (SU->getInstr()->getOpcode()) {
120 default:
Duncan P. N. Exon Smith57022872016-02-27 19:09:00 +0000121 if (!ResourcesModel->canReserveResources(*SU->getInstr()))
Sergei Larin4d8986a2012-09-04 14:49:56 +0000122 return false;
123 case TargetOpcode::EXTRACT_SUBREG:
124 case TargetOpcode::INSERT_SUBREG:
125 case TargetOpcode::SUBREG_TO_REG:
126 case TargetOpcode::REG_SEQUENCE:
127 case TargetOpcode::IMPLICIT_DEF:
128 case TargetOpcode::COPY:
129 case TargetOpcode::INLINEASM:
130 break;
131 }
132
133 // Now see if there are no other dependencies to instructions already
134 // in the packet.
135 for (unsigned i = 0, e = Packet.size(); i != e; ++i) {
136 if (Packet[i]->Succs.size() == 0)
137 continue;
138 for (SUnit::const_succ_iterator I = Packet[i]->Succs.begin(),
139 E = Packet[i]->Succs.end(); I != E; ++I) {
140 // Since we do not add pseudos to packets, might as well
141 // ignore order dependencies.
142 if (I->isCtrl())
143 continue;
144
145 if (I->getSUnit() == SU)
146 return false;
147 }
148 }
149 return true;
150}
151
152/// Keep track of available resources.
Sergei Larinef4cc112012-09-10 17:31:34 +0000153bool VLIWResourceModel::reserveResources(SUnit *SU) {
154 bool startNewCycle = false;
Sergei Larin2db64a72012-09-14 15:07:59 +0000155 // Artificially reset state.
156 if (!SU) {
157 ResourcesModel->clearResources();
158 Packet.clear();
159 TotalPackets++;
160 return false;
161 }
Sergei Larin4d8986a2012-09-04 14:49:56 +0000162 // If this SU does not fit in the packet
163 // start a new one.
164 if (!isResourceAvailable(SU)) {
165 ResourcesModel->clearResources();
166 Packet.clear();
167 TotalPackets++;
Sergei Larinef4cc112012-09-10 17:31:34 +0000168 startNewCycle = true;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000169 }
170
171 switch (SU->getInstr()->getOpcode()) {
172 default:
Duncan P. N. Exon Smith57022872016-02-27 19:09:00 +0000173 ResourcesModel->reserveResources(*SU->getInstr());
Sergei Larin4d8986a2012-09-04 14:49:56 +0000174 break;
175 case TargetOpcode::EXTRACT_SUBREG:
176 case TargetOpcode::INSERT_SUBREG:
177 case TargetOpcode::SUBREG_TO_REG:
178 case TargetOpcode::REG_SEQUENCE:
179 case TargetOpcode::IMPLICIT_DEF:
180 case TargetOpcode::KILL:
Rafael Espindolab1f25f12014-03-07 06:08:31 +0000181 case TargetOpcode::CFI_INSTRUCTION:
Sergei Larin4d8986a2012-09-04 14:49:56 +0000182 case TargetOpcode::EH_LABEL:
183 case TargetOpcode::COPY:
184 case TargetOpcode::INLINEASM:
185 break;
186 }
187 Packet.push_back(SU);
188
189#ifndef NDEBUG
190 DEBUG(dbgs() << "Packet[" << TotalPackets << "]:\n");
191 for (unsigned i = 0, e = Packet.size(); i != e; ++i) {
192 DEBUG(dbgs() << "\t[" << i << "] SU(");
Sergei Larinef4cc112012-09-10 17:31:34 +0000193 DEBUG(dbgs() << Packet[i]->NodeNum << ")\t");
194 DEBUG(Packet[i]->getInstr()->dump());
Sergei Larin4d8986a2012-09-04 14:49:56 +0000195 }
196#endif
197
198 // If packet is now full, reset the state so in the next cycle
199 // we start fresh.
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000200 if (Packet.size() >= SchedModel->getIssueWidth()) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000201 ResourcesModel->clearResources();
202 Packet.clear();
203 TotalPackets++;
Sergei Larinef4cc112012-09-10 17:31:34 +0000204 startNewCycle = true;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000205 }
Sergei Larinef4cc112012-09-10 17:31:34 +0000206
207 return startNewCycle;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000208}
209
Sergei Larin4d8986a2012-09-04 14:49:56 +0000210/// schedule - Called back from MachineScheduler::runOnMachineFunction
211/// after setting up the current scheduling region. [RegionBegin, RegionEnd)
212/// only includes instructions that have DAG nodes, not scheduling boundaries.
213void VLIWMachineScheduler::schedule() {
214 DEBUG(dbgs()
215 << "********** MI Converging Scheduling VLIW BB#" << BB->getNumber()
216 << " " << BB->getName()
217 << " in_func " << BB->getParent()->getFunction()->getName()
Alexey Samsonov8968e6d2014-08-20 19:36:05 +0000218 << " at loop depth " << MLI->getLoopDepth(BB)
Sergei Larin4d8986a2012-09-04 14:49:56 +0000219 << " \n");
220
Andrew Trick7a8e1002012-09-11 00:39:15 +0000221 buildDAGWithRegPressure();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000222
Andrew Tricke2c3f5c2013-01-25 06:33:57 +0000223 SmallVector<SUnit*, 8> TopRoots, BotRoots;
224 findRootsAndBiasEdges(TopRoots, BotRoots);
225
226 // Initialize the strategy before modifying the DAG.
227 SchedImpl->initialize(this);
228
Sergei Larinef4cc112012-09-10 17:31:34 +0000229 // To view Height/Depth correctly, they should be accessed at least once.
Andrew Trick63474622013-03-02 01:43:08 +0000230 //
231 // FIXME: SUnit::dumpAll always recompute depth and height now. The max
232 // depth/height could be computed directly from the roots and leaves.
Sergei Larinef4cc112012-09-10 17:31:34 +0000233 DEBUG(unsigned maxH = 0;
234 for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
235 if (SUnits[su].getHeight() > maxH)
236 maxH = SUnits[su].getHeight();
237 dbgs() << "Max Height " << maxH << "\n";);
238 DEBUG(unsigned maxD = 0;
239 for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
240 if (SUnits[su].getDepth() > maxD)
241 maxD = SUnits[su].getDepth();
242 dbgs() << "Max Depth " << maxD << "\n";);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000243 DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
244 SUnits[su].dumpAll(this));
245
Andrew Tricke2c3f5c2013-01-25 06:33:57 +0000246 initQueues(TopRoots, BotRoots);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000247
Sergei Larin4d8986a2012-09-04 14:49:56 +0000248 bool IsTopNode = false;
James Y Knighte72b0db2015-09-18 18:52:20 +0000249 while (true) {
250 DEBUG(dbgs() << "** VLIWMachineScheduler::schedule picking next node\n");
251 SUnit *SU = SchedImpl->pickNode(IsTopNode);
252 if (!SU) break;
253
Sergei Larin4d8986a2012-09-04 14:49:56 +0000254 if (!checkSchedLimit())
255 break;
256
Andrew Trick7a8e1002012-09-11 00:39:15 +0000257 scheduleMI(SU, IsTopNode);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000258
Andrew Trick7a8e1002012-09-11 00:39:15 +0000259 updateQueues(SU, IsTopNode);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000260
261 // Notify the scheduling strategy after updating the DAG.
262 SchedImpl->schedNode(SU, IsTopNode);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000263 }
264 assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
265
Sergei Larin4d8986a2012-09-04 14:49:56 +0000266 placeDebugValues();
267}
268
Andrew Trick7a8e1002012-09-11 00:39:15 +0000269void ConvergingVLIWScheduler::initialize(ScheduleDAGMI *dag) {
270 DAG = static_cast<VLIWMachineScheduler*>(dag);
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000271 SchedModel = DAG->getSchedModel();
Andrew Trick553e0fe2013-02-13 19:22:27 +0000272
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000273 Top.init(DAG, SchedModel);
274 Bot.init(DAG, SchedModel);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000275
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000276 // Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
277 // are disabled, then these HazardRecs will be disabled.
278 const InstrItineraryData *Itin = DAG->getSchedModel()->getInstrItineraries();
Eric Christopherf8b8e4a2015-02-02 22:11:40 +0000279 const TargetSubtargetInfo &STI = DAG->MF.getSubtarget();
280 const TargetInstrInfo *TII = STI.getInstrInfo();
Andrew Trick553e0fe2013-02-13 19:22:27 +0000281 delete Top.HazardRec;
282 delete Bot.HazardRec;
Eric Christopherf8b8e4a2015-02-02 22:11:40 +0000283 Top.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG);
284 Bot.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000285
Chandler Carruthc18e39c2013-07-27 10:48:45 +0000286 delete Top.ResourceModel;
287 delete Bot.ResourceModel;
Eric Christopherf8b8e4a2015-02-02 22:11:40 +0000288 Top.ResourceModel = new VLIWResourceModel(STI, DAG->getSchedModel());
289 Bot.ResourceModel = new VLIWResourceModel(STI, DAG->getSchedModel());
Sergei Larinef4cc112012-09-10 17:31:34 +0000290
Andrew Trick7a8e1002012-09-11 00:39:15 +0000291 assert((!llvm::ForceTopDown || !llvm::ForceBottomUp) &&
Sergei Larin4d8986a2012-09-04 14:49:56 +0000292 "-misched-topdown incompatible with -misched-bottomup");
Krzysztof Parzyszek9be66732016-07-15 17:48:09 +0000293
294 DAG->addMutation(make_unique<HexagonSubtarget::HexagonDAGMutation>());
Krzysztof Parzyszek36b0f932016-07-15 19:09:37 +0000295 DAG->addMutation(make_unique<HexagonCallMutation>());
Sergei Larin4d8986a2012-09-04 14:49:56 +0000296}
297
298void ConvergingVLIWScheduler::releaseTopNode(SUnit *SU) {
299 if (SU->isScheduled)
300 return;
301
302 for (SUnit::succ_iterator I = SU->Preds.begin(), E = SU->Preds.end();
303 I != E; ++I) {
304 unsigned PredReadyCycle = I->getSUnit()->TopReadyCycle;
Andrew Trickde2109e2013-06-15 04:49:57 +0000305 unsigned MinLatency = I->getLatency();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000306#ifndef NDEBUG
307 Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency);
308#endif
309 if (SU->TopReadyCycle < PredReadyCycle + MinLatency)
310 SU->TopReadyCycle = PredReadyCycle + MinLatency;
311 }
312 Top.releaseNode(SU, SU->TopReadyCycle);
313}
314
315void ConvergingVLIWScheduler::releaseBottomNode(SUnit *SU) {
316 if (SU->isScheduled)
317 return;
318
319 assert(SU->getInstr() && "Scheduled SUnit must have instr");
320
321 for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
322 I != E; ++I) {
323 unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle;
Andrew Trickde2109e2013-06-15 04:49:57 +0000324 unsigned MinLatency = I->getLatency();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000325#ifndef NDEBUG
326 Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency);
327#endif
328 if (SU->BotReadyCycle < SuccReadyCycle + MinLatency)
329 SU->BotReadyCycle = SuccReadyCycle + MinLatency;
330 }
331 Bot.releaseNode(SU, SU->BotReadyCycle);
332}
333
334/// Does this SU have a hazard within the current instruction group.
335///
336/// The scheduler supports two modes of hazard recognition. The first is the
337/// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that
338/// supports highly complicated in-order reservation tables
339/// (ScoreboardHazardRecognizer) and arbitrary target-specific logic.
340///
341/// The second is a streamlined mechanism that checks for hazards based on
342/// simple counters that the scheduler itself maintains. It explicitly checks
343/// for instruction dispatch limitations, including the number of micro-ops that
344/// can dispatch per cycle.
345///
346/// TODO: Also check whether the SU must start a new group.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000347bool ConvergingVLIWScheduler::VLIWSchedBoundary::checkHazard(SUnit *SU) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000348 if (HazardRec->isEnabled())
349 return HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard;
350
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000351 unsigned uops = SchedModel->getNumMicroOps(SU->getInstr());
352 if (IssueCount + uops > SchedModel->getIssueWidth())
Sergei Larin4d8986a2012-09-04 14:49:56 +0000353 return true;
354
355 return false;
356}
357
Andrew Trickd7f890e2013-12-28 21:56:47 +0000358void ConvergingVLIWScheduler::VLIWSchedBoundary::releaseNode(SUnit *SU,
Sergei Larin4d8986a2012-09-04 14:49:56 +0000359 unsigned ReadyCycle) {
360 if (ReadyCycle < MinReadyCycle)
361 MinReadyCycle = ReadyCycle;
362
363 // Check for interlocks first. For the purpose of other heuristics, an
364 // instruction that cannot issue appears as if it's not in the ReadyQueue.
365 if (ReadyCycle > CurrCycle || checkHazard(SU))
366
367 Pending.push(SU);
368 else
369 Available.push(SU);
370}
371
372/// Move the boundary of scheduled code by one cycle.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000373void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpCycle() {
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000374 unsigned Width = SchedModel->getIssueWidth();
Sergei Larin4d8986a2012-09-04 14:49:56 +0000375 IssueCount = (IssueCount <= Width) ? 0 : IssueCount - Width;
376
377 assert(MinReadyCycle < UINT_MAX && "MinReadyCycle uninitialized");
378 unsigned NextCycle = std::max(CurrCycle + 1, MinReadyCycle);
379
380 if (!HazardRec->isEnabled()) {
381 // Bypass HazardRec virtual calls.
382 CurrCycle = NextCycle;
Sergei Larinef4cc112012-09-10 17:31:34 +0000383 } else {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000384 // Bypass getHazardType calls in case of long latency.
385 for (; CurrCycle != NextCycle; ++CurrCycle) {
386 if (isTop())
387 HazardRec->AdvanceCycle();
388 else
389 HazardRec->RecedeCycle();
390 }
391 }
392 CheckPending = true;
393
394 DEBUG(dbgs() << "*** " << Available.getName() << " cycle "
395 << CurrCycle << '\n');
396}
397
398/// Move the boundary of scheduled code by one SUnit.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000399void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpNode(SUnit *SU) {
Sergei Larinef4cc112012-09-10 17:31:34 +0000400 bool startNewCycle = false;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000401
402 // Update the reservation table.
403 if (HazardRec->isEnabled()) {
404 if (!isTop() && SU->isCall) {
405 // Calls are scheduled with their preceding instructions. For bottom-up
406 // scheduling, clear the pipeline state before emitting.
407 HazardRec->Reset();
408 }
409 HazardRec->EmitInstruction(SU);
410 }
Sergei Larinef4cc112012-09-10 17:31:34 +0000411
412 // Update DFA model.
413 startNewCycle = ResourceModel->reserveResources(SU);
414
Sergei Larin4d8986a2012-09-04 14:49:56 +0000415 // Check the instruction group dispatch limit.
416 // TODO: Check if this SU must end a dispatch group.
Andrew Trickdd79f0f2012-10-10 05:43:09 +0000417 IssueCount += SchedModel->getNumMicroOps(SU->getInstr());
Sergei Larinef4cc112012-09-10 17:31:34 +0000418 if (startNewCycle) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000419 DEBUG(dbgs() << "*** Max instrs at cycle " << CurrCycle << '\n');
420 bumpCycle();
421 }
Sergei Larinef4cc112012-09-10 17:31:34 +0000422 else
423 DEBUG(dbgs() << "*** IssueCount " << IssueCount
424 << " at cycle " << CurrCycle << '\n');
Sergei Larin4d8986a2012-09-04 14:49:56 +0000425}
426
427/// Release pending ready nodes in to the available queue. This makes them
428/// visible to heuristics.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000429void ConvergingVLIWScheduler::VLIWSchedBoundary::releasePending() {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000430 // If the available queue is empty, it is safe to reset MinReadyCycle.
431 if (Available.empty())
432 MinReadyCycle = UINT_MAX;
433
434 // Check to see if any of the pending instructions are ready to issue. If
435 // so, add them to the available queue.
436 for (unsigned i = 0, e = Pending.size(); i != e; ++i) {
437 SUnit *SU = *(Pending.begin()+i);
438 unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle;
439
440 if (ReadyCycle < MinReadyCycle)
441 MinReadyCycle = ReadyCycle;
442
443 if (ReadyCycle > CurrCycle)
444 continue;
445
446 if (checkHazard(SU))
447 continue;
448
449 Available.push(SU);
450 Pending.remove(Pending.begin()+i);
451 --i; --e;
452 }
453 CheckPending = false;
454}
455
456/// Remove SU from the ready set for this boundary.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000457void ConvergingVLIWScheduler::VLIWSchedBoundary::removeReady(SUnit *SU) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000458 if (Available.isInQueue(SU))
459 Available.remove(Available.find(SU));
460 else {
461 assert(Pending.isInQueue(SU) && "bad ready count");
462 Pending.remove(Pending.find(SU));
463 }
464}
465
466/// If this queue only has one ready candidate, return it. As a side effect,
467/// advance the cycle until at least one node is ready. If multiple instructions
468/// are ready, return NULL.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000469SUnit *ConvergingVLIWScheduler::VLIWSchedBoundary::pickOnlyChoice() {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000470 if (CheckPending)
471 releasePending();
472
473 for (unsigned i = 0; Available.empty(); ++i) {
474 assert(i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) &&
475 "permanent hazard"); (void)i;
Craig Topper062a2ba2014-04-25 05:30:21 +0000476 ResourceModel->reserveResources(nullptr);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000477 bumpCycle();
478 releasePending();
479 }
480 if (Available.size() == 1)
481 return *Available.begin();
Craig Topper062a2ba2014-04-25 05:30:21 +0000482 return nullptr;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000483}
484
485#ifndef NDEBUG
Sergei Larinef4cc112012-09-10 17:31:34 +0000486void ConvergingVLIWScheduler::traceCandidate(const char *Label,
487 const ReadyQueue &Q,
Andrew Trick1a831342013-08-30 03:49:48 +0000488 SUnit *SU, PressureChange P) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000489 dbgs() << Label << " " << Q.getName() << " ";
490 if (P.isValid())
Andrew Trick1a831342013-08-30 03:49:48 +0000491 dbgs() << DAG->TRI->getRegPressureSetName(P.getPSet()) << ":"
492 << P.getUnitInc() << " ";
Sergei Larin4d8986a2012-09-04 14:49:56 +0000493 else
494 dbgs() << " ";
495 SU->dump(DAG);
496}
497#endif
498
Sergei Larinef4cc112012-09-10 17:31:34 +0000499/// getSingleUnscheduledPred - If there is exactly one unscheduled predecessor
500/// of SU, return it, otherwise return null.
501static SUnit *getSingleUnscheduledPred(SUnit *SU) {
Craig Topper062a2ba2014-04-25 05:30:21 +0000502 SUnit *OnlyAvailablePred = nullptr;
Sergei Larinef4cc112012-09-10 17:31:34 +0000503 for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
504 I != E; ++I) {
505 SUnit &Pred = *I->getSUnit();
506 if (!Pred.isScheduled) {
507 // We found an available, but not scheduled, predecessor. If it's the
508 // only one we have found, keep track of it... otherwise give up.
509 if (OnlyAvailablePred && OnlyAvailablePred != &Pred)
Craig Topper062a2ba2014-04-25 05:30:21 +0000510 return nullptr;
Sergei Larinef4cc112012-09-10 17:31:34 +0000511 OnlyAvailablePred = &Pred;
512 }
513 }
514 return OnlyAvailablePred;
515}
516
517/// getSingleUnscheduledSucc - If there is exactly one unscheduled successor
518/// of SU, return it, otherwise return null.
519static SUnit *getSingleUnscheduledSucc(SUnit *SU) {
Craig Topper062a2ba2014-04-25 05:30:21 +0000520 SUnit *OnlyAvailableSucc = nullptr;
Sergei Larinef4cc112012-09-10 17:31:34 +0000521 for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
522 I != E; ++I) {
523 SUnit &Succ = *I->getSUnit();
524 if (!Succ.isScheduled) {
525 // We found an available, but not scheduled, successor. If it's the
526 // only one we have found, keep track of it... otherwise give up.
527 if (OnlyAvailableSucc && OnlyAvailableSucc != &Succ)
Craig Topper062a2ba2014-04-25 05:30:21 +0000528 return nullptr;
Sergei Larinef4cc112012-09-10 17:31:34 +0000529 OnlyAvailableSucc = &Succ;
530 }
531 }
532 return OnlyAvailableSucc;
533}
534
Sergei Larin4d8986a2012-09-04 14:49:56 +0000535// Constants used to denote relative importance of
536// heuristic components for cost computation.
537static const unsigned PriorityOne = 200;
Eli Friedman8f06d552013-09-11 00:41:02 +0000538static const unsigned PriorityTwo = 50;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000539static const unsigned ScaleTwo = 10;
540static const unsigned FactorOne = 2;
541
542/// Single point to compute overall scheduling cost.
543/// TODO: More heuristics will be used soon.
544int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
545 SchedCandidate &Candidate,
546 RegPressureDelta &Delta,
547 bool verbose) {
548 // Initial trivial priority.
549 int ResCount = 1;
550
551 // Do not waste time on a node that is already scheduled.
552 if (!SU || SU->isScheduled)
553 return ResCount;
554
555 // Forced priority is high.
556 if (SU->isScheduleHigh)
557 ResCount += PriorityOne;
558
559 // Critical path first.
Sergei Larinef4cc112012-09-10 17:31:34 +0000560 if (Q.getID() == TopQID) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000561 ResCount += (SU->getHeight() * ScaleTwo);
Sergei Larinef4cc112012-09-10 17:31:34 +0000562
563 // If resources are available for it, multiply the
564 // chance of scheduling.
565 if (Top.ResourceModel->isResourceAvailable(SU))
566 ResCount <<= FactorOne;
567 } else {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000568 ResCount += (SU->getDepth() * ScaleTwo);
569
Sergei Larinef4cc112012-09-10 17:31:34 +0000570 // If resources are available for it, multiply the
571 // chance of scheduling.
572 if (Bot.ResourceModel->isResourceAvailable(SU))
573 ResCount <<= FactorOne;
574 }
575
576 unsigned NumNodesBlocking = 0;
577 if (Q.getID() == TopQID) {
578 // How many SUs does it block from scheduling?
579 // Look at all of the successors of this node.
580 // Count the number of nodes that
581 // this node is the sole unscheduled node for.
582 for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
583 I != E; ++I)
584 if (getSingleUnscheduledPred(I->getSUnit()) == SU)
585 ++NumNodesBlocking;
586 } else {
587 // How many unscheduled predecessors block this node?
588 for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
589 I != E; ++I)
590 if (getSingleUnscheduledSucc(I->getSUnit()) == SU)
591 ++NumNodesBlocking;
592 }
593 ResCount += (NumNodesBlocking * ScaleTwo);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000594
595 // Factor in reg pressure as a heuristic.
Eli Friedman8f06d552013-09-11 00:41:02 +0000596 ResCount -= (Delta.Excess.getUnitInc()*PriorityTwo);
597 ResCount -= (Delta.CriticalMax.getUnitInc()*PriorityTwo);
Sergei Larin4d8986a2012-09-04 14:49:56 +0000598
599 DEBUG(if (verbose) dbgs() << " Total(" << ResCount << ")");
600
601 return ResCount;
602}
603
604/// Pick the best candidate from the top queue.
605///
606/// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during
607/// DAG building. To adjust for the current scheduling location we need to
608/// maintain the number of vreg uses remaining to be top-scheduled.
609ConvergingVLIWScheduler::CandResult ConvergingVLIWScheduler::
610pickNodeFromQueue(ReadyQueue &Q, const RegPressureTracker &RPTracker,
611 SchedCandidate &Candidate) {
612 DEBUG(Q.dump());
613
614 // getMaxPressureDelta temporarily modifies the tracker.
615 RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker);
616
617 // BestSU remains NULL if no top candidates beat the best existing candidate.
618 CandResult FoundCandidate = NoCand;
619 for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) {
620 RegPressureDelta RPDelta;
621 TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
622 DAG->getRegionCriticalPSets(),
623 DAG->getRegPressure().MaxSetPressure);
624
625 int CurrentCost = SchedulingCost(Q, *I, Candidate, RPDelta, false);
626
627 // Initialize the candidate if needed.
628 if (!Candidate.SU) {
629 Candidate.SU = *I;
630 Candidate.RPDelta = RPDelta;
631 Candidate.SCost = CurrentCost;
632 FoundCandidate = NodeOrder;
633 continue;
634 }
635
Sergei Larin4d8986a2012-09-04 14:49:56 +0000636 // Best cost.
637 if (CurrentCost > Candidate.SCost) {
638 DEBUG(traceCandidate("CCAND", Q, *I));
639 Candidate.SU = *I;
640 Candidate.RPDelta = RPDelta;
641 Candidate.SCost = CurrentCost;
642 FoundCandidate = BestCost;
643 continue;
644 }
645
646 // Fall through to original instruction order.
647 // Only consider node order if Candidate was chosen from this Q.
648 if (FoundCandidate == NoCand)
649 continue;
650 }
651 return FoundCandidate;
652}
653
654/// Pick the best candidate node from either the top or bottom queue.
655SUnit *ConvergingVLIWScheduler::pickNodeBidrectional(bool &IsTopNode) {
656 // Schedule as far as possible in the direction of no choice. This is most
657 // efficient, but also provides the best heuristics for CriticalPSets.
658 if (SUnit *SU = Bot.pickOnlyChoice()) {
659 IsTopNode = false;
660 return SU;
661 }
662 if (SUnit *SU = Top.pickOnlyChoice()) {
663 IsTopNode = true;
664 return SU;
665 }
666 SchedCandidate BotCand;
667 // Prefer bottom scheduling when heuristics are silent.
668 CandResult BotResult = pickNodeFromQueue(Bot.Available,
669 DAG->getBotRPTracker(), BotCand);
670 assert(BotResult != NoCand && "failed to find the first candidate");
671
672 // If either Q has a single candidate that provides the least increase in
673 // Excess pressure, we can immediately schedule from that Q.
674 //
675 // RegionCriticalPSets summarizes the pressure within the scheduled region and
676 // affects picking from either Q. If scheduling in one direction must
677 // increase pressure for one of the excess PSets, then schedule in that
678 // direction first to provide more freedom in the other direction.
679 if (BotResult == SingleExcess || BotResult == SingleCritical) {
680 IsTopNode = false;
681 return BotCand.SU;
682 }
683 // Check if the top Q has a better candidate.
684 SchedCandidate TopCand;
685 CandResult TopResult = pickNodeFromQueue(Top.Available,
686 DAG->getTopRPTracker(), TopCand);
687 assert(TopResult != NoCand && "failed to find the first candidate");
688
689 if (TopResult == SingleExcess || TopResult == SingleCritical) {
690 IsTopNode = true;
691 return TopCand.SU;
692 }
693 // If either Q has a single candidate that minimizes pressure above the
694 // original region's pressure pick it.
695 if (BotResult == SingleMax) {
696 IsTopNode = false;
697 return BotCand.SU;
698 }
699 if (TopResult == SingleMax) {
700 IsTopNode = true;
701 return TopCand.SU;
702 }
703 if (TopCand.SCost > BotCand.SCost) {
704 IsTopNode = true;
705 return TopCand.SU;
706 }
707 // Otherwise prefer the bottom candidate in node order.
708 IsTopNode = false;
709 return BotCand.SU;
710}
711
712/// Pick the best node to balance the schedule. Implements MachineSchedStrategy.
713SUnit *ConvergingVLIWScheduler::pickNode(bool &IsTopNode) {
714 if (DAG->top() == DAG->bottom()) {
715 assert(Top.Available.empty() && Top.Pending.empty() &&
716 Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
Craig Topper062a2ba2014-04-25 05:30:21 +0000717 return nullptr;
Sergei Larin4d8986a2012-09-04 14:49:56 +0000718 }
719 SUnit *SU;
Andrew Trick7a8e1002012-09-11 00:39:15 +0000720 if (llvm::ForceTopDown) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000721 SU = Top.pickOnlyChoice();
722 if (!SU) {
723 SchedCandidate TopCand;
724 CandResult TopResult =
725 pickNodeFromQueue(Top.Available, DAG->getTopRPTracker(), TopCand);
726 assert(TopResult != NoCand && "failed to find the first candidate");
727 (void)TopResult;
728 SU = TopCand.SU;
729 }
730 IsTopNode = true;
Andrew Trick7a8e1002012-09-11 00:39:15 +0000731 } else if (llvm::ForceBottomUp) {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000732 SU = Bot.pickOnlyChoice();
733 if (!SU) {
734 SchedCandidate BotCand;
735 CandResult BotResult =
736 pickNodeFromQueue(Bot.Available, DAG->getBotRPTracker(), BotCand);
737 assert(BotResult != NoCand && "failed to find the first candidate");
738 (void)BotResult;
739 SU = BotCand.SU;
740 }
741 IsTopNode = false;
742 } else {
743 SU = pickNodeBidrectional(IsTopNode);
744 }
745 if (SU->isTopReady())
746 Top.removeReady(SU);
747 if (SU->isBottomReady())
748 Bot.removeReady(SU);
749
750 DEBUG(dbgs() << "*** " << (IsTopNode ? "Top" : "Bottom")
751 << " Scheduling Instruction in cycle "
752 << (IsTopNode ? Top.CurrCycle : Bot.CurrCycle) << '\n';
753 SU->dump(DAG));
754 return SU;
755}
756
757/// Update the scheduler's state after scheduling a node. This is the same node
Sergei Larinef4cc112012-09-10 17:31:34 +0000758/// that was just returned by pickNode(). However, VLIWMachineScheduler needs
759/// to update it's state based on the current cycle before MachineSchedStrategy
760/// does.
Sergei Larin4d8986a2012-09-04 14:49:56 +0000761void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) {
762 if (IsTopNode) {
763 SU->TopReadyCycle = Top.CurrCycle;
764 Top.bumpNode(SU);
Sergei Larinef4cc112012-09-10 17:31:34 +0000765 } else {
Sergei Larin4d8986a2012-09-04 14:49:56 +0000766 SU->BotReadyCycle = Bot.CurrCycle;
767 Bot.bumpNode(SU);
768 }
769}