GCNSchedStrategy.cpp revision 360784
1//===-- GCNSchedStrategy.cpp - GCN Scheduler Strategy ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// This contains a MachineSchedStrategy implementation for maximizing wave
11/// occupancy on GCN hardware.
12//===----------------------------------------------------------------------===//
13
14#include "GCNSchedStrategy.h"
15#include "AMDGPUSubtarget.h"
16#include "SIInstrInfo.h"
17#include "SIMachineFunctionInfo.h"
18#include "SIRegisterInfo.h"
19#include "Utils/AMDGPUBaseInfo.h"
20#include "llvm/CodeGen/RegisterClassInfo.h"
21#include "llvm/Support/MathExtras.h"
22
23#define DEBUG_TYPE "machine-scheduler"
24
25using namespace llvm;
26
27GCNMaxOccupancySchedStrategy::GCNMaxOccupancySchedStrategy(
28    const MachineSchedContext *C) :
29    GenericScheduler(C), TargetOccupancy(0), MF(nullptr) { }
30
31void GCNMaxOccupancySchedStrategy::initialize(ScheduleDAGMI *DAG) {
32  GenericScheduler::initialize(DAG);
33
34  const SIRegisterInfo *SRI = static_cast<const SIRegisterInfo*>(TRI);
35
36  MF = &DAG->MF;
37
38  const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
39
40  // FIXME: This is also necessary, because some passes that run after
41  // scheduling and before regalloc increase register pressure.
42  const int ErrorMargin = 3;
43
44  SGPRExcessLimit = Context->RegClassInfo
45    ->getNumAllocatableRegs(&AMDGPU::SGPR_32RegClass) - ErrorMargin;
46  VGPRExcessLimit = Context->RegClassInfo
47    ->getNumAllocatableRegs(&AMDGPU::VGPR_32RegClass) - ErrorMargin;
48  if (TargetOccupancy) {
49    SGPRCriticalLimit = ST.getMaxNumSGPRs(TargetOccupancy, true);
50    VGPRCriticalLimit = ST.getMaxNumVGPRs(TargetOccupancy);
51  } else {
52    SGPRCriticalLimit = SRI->getRegPressureSetLimit(DAG->MF,
53                                                    SRI->getSGPRPressureSet());
54    VGPRCriticalLimit = SRI->getRegPressureSetLimit(DAG->MF,
55                                                    SRI->getVGPRPressureSet());
56  }
57
58  SGPRCriticalLimit -= ErrorMargin;
59  VGPRCriticalLimit -= ErrorMargin;
60}
61
62void GCNMaxOccupancySchedStrategy::initCandidate(SchedCandidate &Cand, SUnit *SU,
63                                     bool AtTop, const RegPressureTracker &RPTracker,
64                                     const SIRegisterInfo *SRI,
65                                     unsigned SGPRPressure,
66                                     unsigned VGPRPressure) {
67
68  Cand.SU = SU;
69  Cand.AtTop = AtTop;
70
71  // getDownwardPressure() and getUpwardPressure() make temporary changes to
72  // the tracker, so we need to pass those function a non-const copy.
73  RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker);
74
75  Pressure.clear();
76  MaxPressure.clear();
77
78  if (AtTop)
79    TempTracker.getDownwardPressure(SU->getInstr(), Pressure, MaxPressure);
80  else {
81    // FIXME: I think for bottom up scheduling, the register pressure is cached
82    // and can be retrieved by DAG->getPressureDif(SU).
83    TempTracker.getUpwardPressure(SU->getInstr(), Pressure, MaxPressure);
84  }
85
86  unsigned NewSGPRPressure = Pressure[SRI->getSGPRPressureSet()];
87  unsigned NewVGPRPressure = Pressure[SRI->getVGPRPressureSet()];
88
89  // If two instructions increase the pressure of different register sets
90  // by the same amount, the generic scheduler will prefer to schedule the
91  // instruction that increases the set with the least amount of registers,
92  // which in our case would be SGPRs.  This is rarely what we want, so
93  // when we report excess/critical register pressure, we do it either
94  // only for VGPRs or only for SGPRs.
95
96  // FIXME: Better heuristics to determine whether to prefer SGPRs or VGPRs.
97  const unsigned MaxVGPRPressureInc = 16;
98  bool ShouldTrackVGPRs = VGPRPressure + MaxVGPRPressureInc >= VGPRExcessLimit;
99  bool ShouldTrackSGPRs = !ShouldTrackVGPRs && SGPRPressure >= SGPRExcessLimit;
100
101
102  // FIXME: We have to enter REG-EXCESS before we reach the actual threshold
103  // to increase the likelihood we don't go over the limits.  We should improve
104  // the analysis to look through dependencies to find the path with the least
105  // register pressure.
106
107  // We only need to update the RPDelta for instructions that increase register
108  // pressure. Instructions that decrease or keep reg pressure the same will be
109  // marked as RegExcess in tryCandidate() when they are compared with
110  // instructions that increase the register pressure.
111  if (ShouldTrackVGPRs && NewVGPRPressure >= VGPRExcessLimit) {
112    Cand.RPDelta.Excess = PressureChange(SRI->getVGPRPressureSet());
113    Cand.RPDelta.Excess.setUnitInc(NewVGPRPressure - VGPRExcessLimit);
114  }
115
116  if (ShouldTrackSGPRs && NewSGPRPressure >= SGPRExcessLimit) {
117    Cand.RPDelta.Excess = PressureChange(SRI->getSGPRPressureSet());
118    Cand.RPDelta.Excess.setUnitInc(NewSGPRPressure - SGPRExcessLimit);
119  }
120
121  // Register pressure is considered 'CRITICAL' if it is approaching a value
122  // that would reduce the wave occupancy for the execution unit.  When
123  // register pressure is 'CRITICAL', increading SGPR and VGPR pressure both
124  // has the same cost, so we don't need to prefer one over the other.
125
126  int SGPRDelta = NewSGPRPressure - SGPRCriticalLimit;
127  int VGPRDelta = NewVGPRPressure - VGPRCriticalLimit;
128
129  if (SGPRDelta >= 0 || VGPRDelta >= 0) {
130    if (SGPRDelta > VGPRDelta) {
131      Cand.RPDelta.CriticalMax = PressureChange(SRI->getSGPRPressureSet());
132      Cand.RPDelta.CriticalMax.setUnitInc(SGPRDelta);
133    } else {
134      Cand.RPDelta.CriticalMax = PressureChange(SRI->getVGPRPressureSet());
135      Cand.RPDelta.CriticalMax.setUnitInc(VGPRDelta);
136    }
137  }
138}
139
140// This function is mostly cut and pasted from
141// GenericScheduler::pickNodeFromQueue()
142void GCNMaxOccupancySchedStrategy::pickNodeFromQueue(SchedBoundary &Zone,
143                                         const CandPolicy &ZonePolicy,
144                                         const RegPressureTracker &RPTracker,
145                                         SchedCandidate &Cand) {
146  const SIRegisterInfo *SRI = static_cast<const SIRegisterInfo*>(TRI);
147  ArrayRef<unsigned> Pressure = RPTracker.getRegSetPressureAtPos();
148  unsigned SGPRPressure = Pressure[SRI->getSGPRPressureSet()];
149  unsigned VGPRPressure = Pressure[SRI->getVGPRPressureSet()];
150  ReadyQueue &Q = Zone.Available;
151  for (SUnit *SU : Q) {
152
153    SchedCandidate TryCand(ZonePolicy);
154    initCandidate(TryCand, SU, Zone.isTop(), RPTracker, SRI,
155                  SGPRPressure, VGPRPressure);
156    // Pass SchedBoundary only when comparing nodes from the same boundary.
157    SchedBoundary *ZoneArg = Cand.AtTop == TryCand.AtTop ? &Zone : nullptr;
158    GenericScheduler::tryCandidate(Cand, TryCand, ZoneArg);
159    if (TryCand.Reason != NoCand) {
160      // Initialize resource delta if needed in case future heuristics query it.
161      if (TryCand.ResDelta == SchedResourceDelta())
162        TryCand.initResourceDelta(Zone.DAG, SchedModel);
163      Cand.setBest(TryCand);
164      LLVM_DEBUG(traceCandidate(Cand));
165    }
166  }
167}
168
169// This function is mostly cut and pasted from
170// GenericScheduler::pickNodeBidirectional()
171SUnit *GCNMaxOccupancySchedStrategy::pickNodeBidirectional(bool &IsTopNode) {
172  // Schedule as far as possible in the direction of no choice. This is most
173  // efficient, but also provides the best heuristics for CriticalPSets.
174  if (SUnit *SU = Bot.pickOnlyChoice()) {
175    IsTopNode = false;
176    return SU;
177  }
178  if (SUnit *SU = Top.pickOnlyChoice()) {
179    IsTopNode = true;
180    return SU;
181  }
182  // Set the bottom-up policy based on the state of the current bottom zone and
183  // the instructions outside the zone, including the top zone.
184  CandPolicy BotPolicy;
185  setPolicy(BotPolicy, /*IsPostRA=*/false, Bot, &Top);
186  // Set the top-down policy based on the state of the current top zone and
187  // the instructions outside the zone, including the bottom zone.
188  CandPolicy TopPolicy;
189  setPolicy(TopPolicy, /*IsPostRA=*/false, Top, &Bot);
190
191  // See if BotCand is still valid (because we previously scheduled from Top).
192  LLVM_DEBUG(dbgs() << "Picking from Bot:\n");
193  if (!BotCand.isValid() || BotCand.SU->isScheduled ||
194      BotCand.Policy != BotPolicy) {
195    BotCand.reset(CandPolicy());
196    pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), BotCand);
197    assert(BotCand.Reason != NoCand && "failed to find the first candidate");
198  } else {
199    LLVM_DEBUG(traceCandidate(BotCand));
200#ifndef NDEBUG
201    if (VerifyScheduling) {
202      SchedCandidate TCand;
203      TCand.reset(CandPolicy());
204      pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), TCand);
205      assert(TCand.SU == BotCand.SU &&
206             "Last pick result should correspond to re-picking right now");
207    }
208#endif
209  }
210
211  // Check if the top Q has a better candidate.
212  LLVM_DEBUG(dbgs() << "Picking from Top:\n");
213  if (!TopCand.isValid() || TopCand.SU->isScheduled ||
214      TopCand.Policy != TopPolicy) {
215    TopCand.reset(CandPolicy());
216    pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TopCand);
217    assert(TopCand.Reason != NoCand && "failed to find the first candidate");
218  } else {
219    LLVM_DEBUG(traceCandidate(TopCand));
220#ifndef NDEBUG
221    if (VerifyScheduling) {
222      SchedCandidate TCand;
223      TCand.reset(CandPolicy());
224      pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TCand);
225      assert(TCand.SU == TopCand.SU &&
226           "Last pick result should correspond to re-picking right now");
227    }
228#endif
229  }
230
231  // Pick best from BotCand and TopCand.
232  LLVM_DEBUG(dbgs() << "Top Cand: "; traceCandidate(TopCand);
233             dbgs() << "Bot Cand: "; traceCandidate(BotCand););
234  SchedCandidate Cand;
235  if (TopCand.Reason == BotCand.Reason) {
236    Cand = BotCand;
237    GenericSchedulerBase::CandReason TopReason = TopCand.Reason;
238    TopCand.Reason = NoCand;
239    GenericScheduler::tryCandidate(Cand, TopCand, nullptr);
240    if (TopCand.Reason != NoCand) {
241      Cand.setBest(TopCand);
242    } else {
243      TopCand.Reason = TopReason;
244    }
245  } else {
246    if (TopCand.Reason == RegExcess && TopCand.RPDelta.Excess.getUnitInc() <= 0) {
247      Cand = TopCand;
248    } else if (BotCand.Reason == RegExcess && BotCand.RPDelta.Excess.getUnitInc() <= 0) {
249      Cand = BotCand;
250    } else if (TopCand.Reason == RegCritical && TopCand.RPDelta.CriticalMax.getUnitInc() <= 0) {
251      Cand = TopCand;
252    } else if (BotCand.Reason == RegCritical && BotCand.RPDelta.CriticalMax.getUnitInc() <= 0) {
253      Cand = BotCand;
254    } else {
255      if (BotCand.Reason > TopCand.Reason) {
256        Cand = TopCand;
257      } else {
258        Cand = BotCand;
259      }
260    }
261  }
262  LLVM_DEBUG(dbgs() << "Picking: "; traceCandidate(Cand););
263
264  IsTopNode = Cand.AtTop;
265  return Cand.SU;
266}
267
268// This function is mostly cut and pasted from
269// GenericScheduler::pickNode()
270SUnit *GCNMaxOccupancySchedStrategy::pickNode(bool &IsTopNode) {
271  if (DAG->top() == DAG->bottom()) {
272    assert(Top.Available.empty() && Top.Pending.empty() &&
273           Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
274    return nullptr;
275  }
276  SUnit *SU;
277  do {
278    if (RegionPolicy.OnlyTopDown) {
279      SU = Top.pickOnlyChoice();
280      if (!SU) {
281        CandPolicy NoPolicy;
282        TopCand.reset(NoPolicy);
283        pickNodeFromQueue(Top, NoPolicy, DAG->getTopRPTracker(), TopCand);
284        assert(TopCand.Reason != NoCand && "failed to find a candidate");
285        SU = TopCand.SU;
286      }
287      IsTopNode = true;
288    } else if (RegionPolicy.OnlyBottomUp) {
289      SU = Bot.pickOnlyChoice();
290      if (!SU) {
291        CandPolicy NoPolicy;
292        BotCand.reset(NoPolicy);
293        pickNodeFromQueue(Bot, NoPolicy, DAG->getBotRPTracker(), BotCand);
294        assert(BotCand.Reason != NoCand && "failed to find a candidate");
295        SU = BotCand.SU;
296      }
297      IsTopNode = false;
298    } else {
299      SU = pickNodeBidirectional(IsTopNode);
300    }
301  } while (SU->isScheduled);
302
303  if (SU->isTopReady())
304    Top.removeReady(SU);
305  if (SU->isBottomReady())
306    Bot.removeReady(SU);
307
308  LLVM_DEBUG(dbgs() << "Scheduling SU(" << SU->NodeNum << ") "
309                    << *SU->getInstr());
310  return SU;
311}
312
313GCNScheduleDAGMILive::GCNScheduleDAGMILive(MachineSchedContext *C,
314                        std::unique_ptr<MachineSchedStrategy> S) :
315  ScheduleDAGMILive(C, std::move(S)),
316  ST(MF.getSubtarget<GCNSubtarget>()),
317  MFI(*MF.getInfo<SIMachineFunctionInfo>()),
318  StartingOccupancy(MFI.getOccupancy()),
319  MinOccupancy(StartingOccupancy), Stage(0), RegionIdx(0) {
320
321  LLVM_DEBUG(dbgs() << "Starting occupancy is " << StartingOccupancy << ".\n");
322}
323
324void GCNScheduleDAGMILive::schedule() {
325  if (Stage == 0) {
326    // Just record regions at the first pass.
327    Regions.push_back(std::make_pair(RegionBegin, RegionEnd));
328    return;
329  }
330
331  std::vector<MachineInstr*> Unsched;
332  Unsched.reserve(NumRegionInstrs);
333  for (auto &I : *this) {
334    Unsched.push_back(&I);
335  }
336
337  GCNRegPressure PressureBefore;
338  if (LIS) {
339    PressureBefore = Pressure[RegionIdx];
340
341    LLVM_DEBUG(dbgs() << "Pressure before scheduling:\nRegion live-ins:";
342               GCNRPTracker::printLiveRegs(dbgs(), LiveIns[RegionIdx], MRI);
343               dbgs() << "Region live-in pressure:  ";
344               llvm::getRegPressure(MRI, LiveIns[RegionIdx]).print(dbgs());
345               dbgs() << "Region register pressure: ";
346               PressureBefore.print(dbgs()));
347  }
348
349  ScheduleDAGMILive::schedule();
350  Regions[RegionIdx] = std::make_pair(RegionBegin, RegionEnd);
351
352  if (!LIS)
353    return;
354
355  // Check the results of scheduling.
356  GCNMaxOccupancySchedStrategy &S = (GCNMaxOccupancySchedStrategy&)*SchedImpl;
357  auto PressureAfter = getRealRegPressure();
358
359  LLVM_DEBUG(dbgs() << "Pressure after scheduling: ";
360             PressureAfter.print(dbgs()));
361
362  if (PressureAfter.getSGPRNum() <= S.SGPRCriticalLimit &&
363      PressureAfter.getVGPRNum() <= S.VGPRCriticalLimit) {
364    Pressure[RegionIdx] = PressureAfter;
365    LLVM_DEBUG(dbgs() << "Pressure in desired limits, done.\n");
366    return;
367  }
368  unsigned Occ = MFI.getOccupancy();
369  unsigned WavesAfter = std::min(Occ, PressureAfter.getOccupancy(ST));
370  unsigned WavesBefore = std::min(Occ, PressureBefore.getOccupancy(ST));
371  LLVM_DEBUG(dbgs() << "Occupancy before scheduling: " << WavesBefore
372                    << ", after " << WavesAfter << ".\n");
373
374  // We could not keep current target occupancy because of the just scheduled
375  // region. Record new occupancy for next scheduling cycle.
376  unsigned NewOccupancy = std::max(WavesAfter, WavesBefore);
377  // Allow memory bound functions to drop to 4 waves if not limited by an
378  // attribute.
379  if (WavesAfter < WavesBefore && WavesAfter < MinOccupancy &&
380      WavesAfter >= MFI.getMinAllowedOccupancy()) {
381    LLVM_DEBUG(dbgs() << "Function is memory bound, allow occupancy drop up to "
382                      << MFI.getMinAllowedOccupancy() << " waves\n");
383    NewOccupancy = WavesAfter;
384  }
385  if (NewOccupancy < MinOccupancy) {
386    MinOccupancy = NewOccupancy;
387    MFI.limitOccupancy(MinOccupancy);
388    LLVM_DEBUG(dbgs() << "Occupancy lowered for the function to "
389                      << MinOccupancy << ".\n");
390  }
391
392  if (WavesAfter >= MinOccupancy) {
393    unsigned TotalVGPRs = AMDGPU::IsaInfo::getAddressableNumVGPRs(&ST);
394    unsigned TotalSGPRs = AMDGPU::IsaInfo::getAddressableNumSGPRs(&ST);
395    if (WavesAfter > MFI.getMinWavesPerEU() ||
396        PressureAfter.less(ST, PressureBefore) ||
397        (TotalVGPRs >= PressureAfter.getVGPRNum() &&
398         TotalSGPRs >= PressureAfter.getSGPRNum())) {
399      Pressure[RegionIdx] = PressureAfter;
400      return;
401    }
402    LLVM_DEBUG(dbgs() << "New pressure will result in more spilling.\n");
403  }
404
405  LLVM_DEBUG(dbgs() << "Attempting to revert scheduling.\n");
406  RegionEnd = RegionBegin;
407  for (MachineInstr *MI : Unsched) {
408    if (MI->isDebugInstr())
409      continue;
410
411    if (MI->getIterator() != RegionEnd) {
412      BB->remove(MI);
413      BB->insert(RegionEnd, MI);
414      if (!MI->isDebugInstr())
415        LIS->handleMove(*MI, true);
416    }
417    // Reset read-undef flags and update them later.
418    for (auto &Op : MI->operands())
419      if (Op.isReg() && Op.isDef())
420        Op.setIsUndef(false);
421    RegisterOperands RegOpers;
422    RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, false);
423    if (!MI->isDebugInstr()) {
424      if (ShouldTrackLaneMasks) {
425        // Adjust liveness and add missing dead+read-undef flags.
426        SlotIndex SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot();
427        RegOpers.adjustLaneLiveness(*LIS, MRI, SlotIdx, MI);
428      } else {
429        // Adjust for missing dead-def flags.
430        RegOpers.detectDeadDefs(*MI, *LIS);
431      }
432    }
433    RegionEnd = MI->getIterator();
434    ++RegionEnd;
435    LLVM_DEBUG(dbgs() << "Scheduling " << *MI);
436  }
437  RegionBegin = Unsched.front()->getIterator();
438  Regions[RegionIdx] = std::make_pair(RegionBegin, RegionEnd);
439
440  placeDebugValues();
441}
442
443GCNRegPressure GCNScheduleDAGMILive::getRealRegPressure() const {
444  GCNDownwardRPTracker RPTracker(*LIS);
445  RPTracker.advance(begin(), end(), &LiveIns[RegionIdx]);
446  return RPTracker.moveMaxPressure();
447}
448
449void GCNScheduleDAGMILive::computeBlockPressure(const MachineBasicBlock *MBB) {
450  GCNDownwardRPTracker RPTracker(*LIS);
451
452  // If the block has the only successor then live-ins of that successor are
453  // live-outs of the current block. We can reuse calculated live set if the
454  // successor will be sent to scheduling past current block.
455  const MachineBasicBlock *OnlySucc = nullptr;
456  if (MBB->succ_size() == 1 && !(*MBB->succ_begin())->empty()) {
457    SlotIndexes *Ind = LIS->getSlotIndexes();
458    if (Ind->getMBBStartIdx(MBB) < Ind->getMBBStartIdx(*MBB->succ_begin()))
459      OnlySucc = *MBB->succ_begin();
460  }
461
462  // Scheduler sends regions from the end of the block upwards.
463  size_t CurRegion = RegionIdx;
464  for (size_t E = Regions.size(); CurRegion != E; ++CurRegion)
465    if (Regions[CurRegion].first->getParent() != MBB)
466      break;
467  --CurRegion;
468
469  auto I = MBB->begin();
470  auto LiveInIt = MBBLiveIns.find(MBB);
471  if (LiveInIt != MBBLiveIns.end()) {
472    auto LiveIn = std::move(LiveInIt->second);
473    RPTracker.reset(*MBB->begin(), &LiveIn);
474    MBBLiveIns.erase(LiveInIt);
475  } else {
476    auto &Rgn = Regions[CurRegion];
477    I = Rgn.first;
478    auto *NonDbgMI = &*skipDebugInstructionsForward(Rgn.first, Rgn.second);
479    auto LRS = BBLiveInMap.lookup(NonDbgMI);
480    assert(isEqual(getLiveRegsBefore(*NonDbgMI, *LIS), LRS));
481    RPTracker.reset(*I, &LRS);
482  }
483
484  for ( ; ; ) {
485    I = RPTracker.getNext();
486
487    if (Regions[CurRegion].first == I) {
488      LiveIns[CurRegion] = RPTracker.getLiveRegs();
489      RPTracker.clearMaxPressure();
490    }
491
492    if (Regions[CurRegion].second == I) {
493      Pressure[CurRegion] = RPTracker.moveMaxPressure();
494      if (CurRegion-- == RegionIdx)
495        break;
496    }
497    RPTracker.advanceToNext();
498    RPTracker.advanceBeforeNext();
499  }
500
501  if (OnlySucc) {
502    if (I != MBB->end()) {
503      RPTracker.advanceToNext();
504      RPTracker.advance(MBB->end());
505    }
506    RPTracker.reset(*OnlySucc->begin(), &RPTracker.getLiveRegs());
507    RPTracker.advanceBeforeNext();
508    MBBLiveIns[OnlySucc] = RPTracker.moveLiveRegs();
509  }
510}
511
512DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet>
513GCNScheduleDAGMILive::getBBLiveInMap() const {
514  assert(!Regions.empty());
515  std::vector<MachineInstr *> BBStarters;
516  BBStarters.reserve(Regions.size());
517  auto I = Regions.rbegin(), E = Regions.rend();
518  auto *BB = I->first->getParent();
519  do {
520    auto *MI = &*skipDebugInstructionsForward(I->first, I->second);
521    BBStarters.push_back(MI);
522    do {
523      ++I;
524    } while (I != E && I->first->getParent() == BB);
525  } while (I != E);
526  return getLiveRegMap(BBStarters, false /*After*/, *LIS);
527}
528
529void GCNScheduleDAGMILive::finalizeSchedule() {
530  GCNMaxOccupancySchedStrategy &S = (GCNMaxOccupancySchedStrategy&)*SchedImpl;
531  LLVM_DEBUG(dbgs() << "All regions recorded, starting actual scheduling.\n");
532
533  LiveIns.resize(Regions.size());
534  Pressure.resize(Regions.size());
535
536  if (!Regions.empty())
537    BBLiveInMap = getBBLiveInMap();
538
539  do {
540    Stage++;
541    RegionIdx = 0;
542    MachineBasicBlock *MBB = nullptr;
543
544    if (Stage > 1) {
545      // Retry function scheduling if we found resulting occupancy and it is
546      // lower than used for first pass scheduling. This will give more freedom
547      // to schedule low register pressure blocks.
548      // Code is partially copied from MachineSchedulerBase::scheduleRegions().
549
550      if (!LIS || StartingOccupancy <= MinOccupancy)
551        break;
552
553      LLVM_DEBUG(
554          dbgs()
555          << "Retrying function scheduling with lowest recorded occupancy "
556          << MinOccupancy << ".\n");
557
558      S.setTargetOccupancy(MinOccupancy);
559    }
560
561    for (auto Region : Regions) {
562      RegionBegin = Region.first;
563      RegionEnd = Region.second;
564
565      if (RegionBegin->getParent() != MBB) {
566        if (MBB) finishBlock();
567        MBB = RegionBegin->getParent();
568        startBlock(MBB);
569        if (Stage == 1)
570          computeBlockPressure(MBB);
571      }
572
573      unsigned NumRegionInstrs = std::distance(begin(), end());
574      enterRegion(MBB, begin(), end(), NumRegionInstrs);
575
576      // Skip empty scheduling regions (0 or 1 schedulable instructions).
577      if (begin() == end() || begin() == std::prev(end())) {
578        exitRegion();
579        continue;
580      }
581
582      LLVM_DEBUG(dbgs() << "********** MI Scheduling **********\n");
583      LLVM_DEBUG(dbgs() << MF.getName() << ":" << printMBBReference(*MBB) << " "
584                        << MBB->getName() << "\n  From: " << *begin()
585                        << "    To: ";
586                 if (RegionEnd != MBB->end()) dbgs() << *RegionEnd;
587                 else dbgs() << "End";
588                 dbgs() << " RegionInstrs: " << NumRegionInstrs << '\n');
589
590      schedule();
591
592      exitRegion();
593      ++RegionIdx;
594    }
595    finishBlock();
596
597  } while (Stage < 2);
598}
599