LLVM  10.0.0svn
GCNSchedStrategy.cpp
Go to the documentation of this file.
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"
21 
22 #define DEBUG_TYPE "machine-scheduler"
23 
24 using namespace llvm;
25 
27  const MachineSchedContext *C) :
28  GenericScheduler(C), TargetOccupancy(0), MF(nullptr) { }
29 
32 
33  const SIRegisterInfo *SRI = static_cast<const SIRegisterInfo*>(TRI);
34 
35  MF = &DAG->MF;
36 
37  const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
38 
39  // FIXME: This is also necessary, because some passes that run after
40  // scheduling and before regalloc increase register pressure.
41  const int ErrorMargin = 3;
42 
43  SGPRExcessLimit = Context->RegClassInfo
44  ->getNumAllocatableRegs(&AMDGPU::SGPR_32RegClass) - ErrorMargin;
45  VGPRExcessLimit = Context->RegClassInfo
46  ->getNumAllocatableRegs(&AMDGPU::VGPR_32RegClass) - ErrorMargin;
47  if (TargetOccupancy) {
48  SGPRCriticalLimit = ST.getMaxNumSGPRs(TargetOccupancy, true);
49  VGPRCriticalLimit = ST.getMaxNumVGPRs(TargetOccupancy);
50  } else {
51  SGPRCriticalLimit = SRI->getRegPressureSetLimit(DAG->MF,
52  SRI->getSGPRPressureSet());
53  VGPRCriticalLimit = SRI->getRegPressureSetLimit(DAG->MF,
54  SRI->getVGPRPressureSet());
55  }
56 
57  SGPRCriticalLimit -= ErrorMargin;
58  VGPRCriticalLimit -= ErrorMargin;
59 }
60 
61 void GCNMaxOccupancySchedStrategy::initCandidate(SchedCandidate &Cand, SUnit *SU,
62  bool AtTop, const RegPressureTracker &RPTracker,
63  const SIRegisterInfo *SRI,
64  unsigned SGPRPressure,
65  unsigned VGPRPressure) {
66 
67  Cand.SU = SU;
68  Cand.AtTop = AtTop;
69 
70  // getDownwardPressure() and getUpwardPressure() make temporary changes to
71  // the tracker, so we need to pass those function a non-const copy.
72  RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker);
73 
74  std::vector<unsigned> Pressure;
75  std::vector<unsigned> MaxPressure;
76 
77  if (AtTop)
78  TempTracker.getDownwardPressure(SU->getInstr(), Pressure, MaxPressure);
79  else {
80  // FIXME: I think for bottom up scheduling, the register pressure is cached
81  // and can be retrieved by DAG->getPressureDif(SU).
82  TempTracker.getUpwardPressure(SU->getInstr(), Pressure, MaxPressure);
83  }
84 
85  unsigned NewSGPRPressure = Pressure[SRI->getSGPRPressureSet()];
86  unsigned NewVGPRPressure = Pressure[SRI->getVGPRPressureSet()];
87 
88  // If two instructions increase the pressure of different register sets
89  // by the same amount, the generic scheduler will prefer to schedule the
90  // instruction that increases the set with the least amount of registers,
91  // which in our case would be SGPRs. This is rarely what we want, so
92  // when we report excess/critical register pressure, we do it either
93  // only for VGPRs or only for SGPRs.
94 
95  // FIXME: Better heuristics to determine whether to prefer SGPRs or VGPRs.
96  const unsigned MaxVGPRPressureInc = 16;
97  bool ShouldTrackVGPRs = VGPRPressure + MaxVGPRPressureInc >= VGPRExcessLimit;
98  bool ShouldTrackSGPRs = !ShouldTrackVGPRs && SGPRPressure >= SGPRExcessLimit;
99 
100 
101  // FIXME: We have to enter REG-EXCESS before we reach the actual threshold
102  // to increase the likelihood we don't go over the limits. We should improve
103  // the analysis to look through dependencies to find the path with the least
104  // register pressure.
105 
106  // We only need to update the RPDelata for instructions that increase
107  // register pressure. Instructions that decrease or keep reg pressure
108  // the same will be marked as RegExcess in tryCandidate() when they
109  // are compared with instructions that increase the register pressure.
110  if (ShouldTrackVGPRs && NewVGPRPressure >= VGPRExcessLimit) {
112  Cand.RPDelta.Excess.setUnitInc(NewVGPRPressure - VGPRExcessLimit);
113  }
114 
115  if (ShouldTrackSGPRs && NewSGPRPressure >= SGPRExcessLimit) {
117  Cand.RPDelta.Excess.setUnitInc(NewSGPRPressure - SGPRExcessLimit);
118  }
119 
120  // Register pressure is considered 'CRITICAL' if it is approaching a value
121  // that would reduce the wave occupancy for the execution unit. When
122  // register pressure is 'CRITICAL', increading SGPR and VGPR pressure both
123  // has the same cost, so we don't need to prefer one over the other.
124 
125  int SGPRDelta = NewSGPRPressure - SGPRCriticalLimit;
126  int VGPRDelta = NewVGPRPressure - VGPRCriticalLimit;
127 
128  if (SGPRDelta >= 0 || VGPRDelta >= 0) {
129  if (SGPRDelta > VGPRDelta) {
131  Cand.RPDelta.CriticalMax.setUnitInc(SGPRDelta);
132  } else {
134  Cand.RPDelta.CriticalMax.setUnitInc(VGPRDelta);
135  }
136  }
137 }
138 
139 // This function is mostly cut and pasted from
140 // GenericScheduler::pickNodeFromQueue()
141 void GCNMaxOccupancySchedStrategy::pickNodeFromQueue(SchedBoundary &Zone,
142  const CandPolicy &ZonePolicy,
143  const RegPressureTracker &RPTracker,
144  SchedCandidate &Cand) {
145  const SIRegisterInfo *SRI = static_cast<const SIRegisterInfo*>(TRI);
146  ArrayRef<unsigned> Pressure = RPTracker.getRegSetPressureAtPos();
147  unsigned SGPRPressure = Pressure[SRI->getSGPRPressureSet()];
148  unsigned VGPRPressure = Pressure[SRI->getVGPRPressureSet()];
149  ReadyQueue &Q = Zone.Available;
150  for (SUnit *SU : Q) {
151 
152  SchedCandidate TryCand(ZonePolicy);
153  initCandidate(TryCand, SU, Zone.isTop(), RPTracker, SRI,
154  SGPRPressure, VGPRPressure);
155  // Pass SchedBoundary only when comparing nodes from the same boundary.
156  SchedBoundary *ZoneArg = Cand.AtTop == TryCand.AtTop ? &Zone : nullptr;
157  GenericScheduler::tryCandidate(Cand, TryCand, ZoneArg);
158  if (TryCand.Reason != NoCand) {
159  // Initialize resource delta if needed in case future heuristics query it.
160  if (TryCand.ResDelta == SchedResourceDelta())
161  TryCand.initResourceDelta(Zone.DAG, SchedModel);
162  Cand.setBest(TryCand);
163  }
164  }
165 }
166 
167 // This function is mostly cut and pasted from
168 // GenericScheduler::pickNodeBidirectional()
169 SUnit *GCNMaxOccupancySchedStrategy::pickNodeBidirectional(bool &IsTopNode) {
170  // Schedule as far as possible in the direction of no choice. This is most
171  // efficient, but also provides the best heuristics for CriticalPSets.
172  if (SUnit *SU = Bot.pickOnlyChoice()) {
173  IsTopNode = false;
174  return SU;
175  }
176  if (SUnit *SU = Top.pickOnlyChoice()) {
177  IsTopNode = true;
178  return SU;
179  }
180  // Set the bottom-up policy based on the state of the current bottom zone and
181  // the instructions outside the zone, including the top zone.
182  CandPolicy BotPolicy;
183  setPolicy(BotPolicy, /*IsPostRA=*/false, Bot, &Top);
184  // Set the top-down policy based on the state of the current top zone and
185  // the instructions outside the zone, including the bottom zone.
186  CandPolicy TopPolicy;
187  setPolicy(TopPolicy, /*IsPostRA=*/false, Top, &Bot);
188 
189  // See if BotCand is still valid (because we previously scheduled from Top).
190  LLVM_DEBUG(dbgs() << "Picking from Bot:\n");
191  if (!BotCand.isValid() || BotCand.SU->isScheduled ||
192  BotCand.Policy != BotPolicy) {
194  pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), BotCand);
195  assert(BotCand.Reason != NoCand && "failed to find the first candidate");
196  } else {
198  }
199 
200  // Check if the top Q has a better candidate.
201  LLVM_DEBUG(dbgs() << "Picking from Top:\n");
202  if (!TopCand.isValid() || TopCand.SU->isScheduled ||
203  TopCand.Policy != TopPolicy) {
205  pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TopCand);
206  assert(TopCand.Reason != NoCand && "failed to find the first candidate");
207  } else {
209  }
210 
211  // Pick best from BotCand and TopCand.
212  LLVM_DEBUG(dbgs() << "Top Cand: "; traceCandidate(TopCand);
213  dbgs() << "Bot Cand: "; traceCandidate(BotCand););
214  SchedCandidate Cand;
215  if (TopCand.Reason == BotCand.Reason) {
216  Cand = BotCand;
219  GenericScheduler::tryCandidate(Cand, TopCand, nullptr);
220  if (TopCand.Reason != NoCand) {
221  Cand.setBest(TopCand);
222  } else {
223  TopCand.Reason = TopReason;
224  }
225  } else {
227  Cand = TopCand;
228  } else if (BotCand.Reason == RegExcess && BotCand.RPDelta.Excess.getUnitInc() <= 0) {
229  Cand = BotCand;
230  } else if (TopCand.Reason == RegCritical && TopCand.RPDelta.CriticalMax.getUnitInc() <= 0) {
231  Cand = TopCand;
232  } else if (BotCand.Reason == RegCritical && BotCand.RPDelta.CriticalMax.getUnitInc() <= 0) {
233  Cand = BotCand;
234  } else {
235  if (BotCand.Reason > TopCand.Reason) {
236  Cand = TopCand;
237  } else {
238  Cand = BotCand;
239  }
240  }
241  }
242  LLVM_DEBUG(dbgs() << "Picking: "; traceCandidate(Cand););
243 
244  IsTopNode = Cand.AtTop;
245  return Cand.SU;
246 }
247 
248 // This function is mostly cut and pasted from
249 // GenericScheduler::pickNode()
251  if (DAG->top() == DAG->bottom()) {
253  Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
254  return nullptr;
255  }
256  SUnit *SU;
257  do {
259  SU = Top.pickOnlyChoice();
260  if (!SU) {
261  CandPolicy NoPolicy;
262  TopCand.reset(NoPolicy);
263  pickNodeFromQueue(Top, NoPolicy, DAG->getTopRPTracker(), TopCand);
264  assert(TopCand.Reason != NoCand && "failed to find a candidate");
265  SU = TopCand.SU;
266  }
267  IsTopNode = true;
268  } else if (RegionPolicy.OnlyBottomUp) {
269  SU = Bot.pickOnlyChoice();
270  if (!SU) {
271  CandPolicy NoPolicy;
272  BotCand.reset(NoPolicy);
273  pickNodeFromQueue(Bot, NoPolicy, DAG->getBotRPTracker(), BotCand);
274  assert(BotCand.Reason != NoCand && "failed to find a candidate");
275  SU = BotCand.SU;
276  }
277  IsTopNode = false;
278  } else {
279  SU = pickNodeBidirectional(IsTopNode);
280  }
281  } while (SU->isScheduled);
282 
283  if (SU->isTopReady())
284  Top.removeReady(SU);
285  if (SU->isBottomReady())
286  Bot.removeReady(SU);
287 
288  LLVM_DEBUG(dbgs() << "Scheduling SU(" << SU->NodeNum << ") "
289  << *SU->getInstr());
290  return SU;
291 }
292 
294  std::unique_ptr<MachineSchedStrategy> S) :
295  ScheduleDAGMILive(C, std::move(S)),
296  ST(MF.getSubtarget<GCNSubtarget>()),
297  MFI(*MF.getInfo<SIMachineFunctionInfo>()),
298  StartingOccupancy(MFI.getOccupancy()),
299  MinOccupancy(StartingOccupancy), Stage(0), RegionIdx(0) {
300 
301  LLVM_DEBUG(dbgs() << "Starting occupancy is " << StartingOccupancy << ".\n");
302 }
303 
305  if (Stage == 0) {
306  // Just record regions at the first pass.
307  Regions.push_back(std::make_pair(RegionBegin, RegionEnd));
308  return;
309  }
310 
311  std::vector<MachineInstr*> Unsched;
312  Unsched.reserve(NumRegionInstrs);
313  for (auto &I : *this) {
314  Unsched.push_back(&I);
315  }
316 
317  GCNRegPressure PressureBefore;
318  if (LIS) {
319  PressureBefore = Pressure[RegionIdx];
320 
321  LLVM_DEBUG(dbgs() << "Pressure before scheduling:\nRegion live-ins:";
322  GCNRPTracker::printLiveRegs(dbgs(), LiveIns[RegionIdx], MRI);
323  dbgs() << "Region live-in pressure: ";
324  llvm::getRegPressure(MRI, LiveIns[RegionIdx]).print(dbgs());
325  dbgs() << "Region register pressure: ";
326  PressureBefore.print(dbgs()));
327  }
328 
330  Regions[RegionIdx] = std::make_pair(RegionBegin, RegionEnd);
331 
332  if (!LIS)
333  return;
334 
335  // Check the results of scheduling.
337  auto PressureAfter = getRealRegPressure();
338 
339  LLVM_DEBUG(dbgs() << "Pressure after scheduling: ";
340  PressureAfter.print(dbgs()));
341 
342  if (PressureAfter.getSGPRNum() <= S.SGPRCriticalLimit &&
343  PressureAfter.getVGPRNum() <= S.VGPRCriticalLimit) {
344  Pressure[RegionIdx] = PressureAfter;
345  LLVM_DEBUG(dbgs() << "Pressure in desired limits, done.\n");
346  return;
347  }
348  unsigned Occ = MFI.getOccupancy();
349  unsigned WavesAfter = std::min(Occ, PressureAfter.getOccupancy(ST));
350  unsigned WavesBefore = std::min(Occ, PressureBefore.getOccupancy(ST));
351  LLVM_DEBUG(dbgs() << "Occupancy before scheduling: " << WavesBefore
352  << ", after " << WavesAfter << ".\n");
353 
354  // We could not keep current target occupancy because of the just scheduled
355  // region. Record new occupancy for next scheduling cycle.
356  unsigned NewOccupancy = std::max(WavesAfter, WavesBefore);
357  // Allow memory bound functions to drop to 4 waves if not limited by an
358  // attribute.
359  if (WavesAfter < WavesBefore && WavesAfter < MinOccupancy &&
360  WavesAfter >= MFI.getMinAllowedOccupancy()) {
361  LLVM_DEBUG(dbgs() << "Function is memory bound, allow occupancy drop up to "
362  << MFI.getMinAllowedOccupancy() << " waves\n");
363  NewOccupancy = WavesAfter;
364  }
365  if (NewOccupancy < MinOccupancy) {
366  MinOccupancy = NewOccupancy;
367  MFI.limitOccupancy(MinOccupancy);
368  LLVM_DEBUG(dbgs() << "Occupancy lowered for the function to "
369  << MinOccupancy << ".\n");
370  }
371 
372  if (WavesAfter >= MinOccupancy) {
373  Pressure[RegionIdx] = PressureAfter;
374  return;
375  }
376 
377  LLVM_DEBUG(dbgs() << "Attempting to revert scheduling.\n");
379  for (MachineInstr *MI : Unsched) {
380  if (MI->isDebugInstr())
381  continue;
382 
383  if (MI->getIterator() != RegionEnd) {
384  BB->remove(MI);
385  BB->insert(RegionEnd, MI);
386  if (!MI->isDebugInstr())
387  LIS->handleMove(*MI, true);
388  }
389  // Reset read-undef flags and update them later.
390  for (auto &Op : MI->operands())
391  if (Op.isReg() && Op.isDef())
392  Op.setIsUndef(false);
393  RegisterOperands RegOpers;
394  RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, false);
395  if (!MI->isDebugInstr()) {
396  if (ShouldTrackLaneMasks) {
397  // Adjust liveness and add missing dead+read-undef flags.
398  SlotIndex SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot();
399  RegOpers.adjustLaneLiveness(*LIS, MRI, SlotIdx, MI);
400  } else {
401  // Adjust for missing dead-def flags.
402  RegOpers.detectDeadDefs(*MI, *LIS);
403  }
404  }
405  RegionEnd = MI->getIterator();
406  ++RegionEnd;
407  LLVM_DEBUG(dbgs() << "Scheduling " << *MI);
408  }
409  RegionBegin = Unsched.front()->getIterator();
410  Regions[RegionIdx] = std::make_pair(RegionBegin, RegionEnd);
411 
413 }
414 
415 GCNRegPressure GCNScheduleDAGMILive::getRealRegPressure() const {
417  RPTracker.advance(begin(), end(), &LiveIns[RegionIdx]);
418  return RPTracker.moveMaxPressure();
419 }
420 
421 void GCNScheduleDAGMILive::computeBlockPressure(const MachineBasicBlock *MBB) {
423 
424  // If the block has the only successor then live-ins of that successor are
425  // live-outs of the current block. We can reuse calculated live set if the
426  // successor will be sent to scheduling past current block.
427  const MachineBasicBlock *OnlySucc = nullptr;
428  if (MBB->succ_size() == 1 && !(*MBB->succ_begin())->empty()) {
429  SlotIndexes *Ind = LIS->getSlotIndexes();
430  if (Ind->getMBBStartIdx(MBB) < Ind->getMBBStartIdx(*MBB->succ_begin()))
431  OnlySucc = *MBB->succ_begin();
432  }
433 
434  // Scheduler sends regions from the end of the block upwards.
435  size_t CurRegion = RegionIdx;
436  for (size_t E = Regions.size(); CurRegion != E; ++CurRegion)
437  if (Regions[CurRegion].first->getParent() != MBB)
438  break;
439  --CurRegion;
440 
441  auto I = MBB->begin();
442  auto LiveInIt = MBBLiveIns.find(MBB);
443  if (LiveInIt != MBBLiveIns.end()) {
444  auto LiveIn = std::move(LiveInIt->second);
445  RPTracker.reset(*MBB->begin(), &LiveIn);
446  MBBLiveIns.erase(LiveInIt);
447  } else {
448  auto &Rgn = Regions[CurRegion];
449  I = Rgn.first;
450  auto *NonDbgMI = &*skipDebugInstructionsForward(Rgn.first, Rgn.second);
451  auto LRS = BBLiveInMap.lookup(NonDbgMI);
452  assert(isEqual(getLiveRegsBefore(*NonDbgMI, *LIS), LRS));
453  RPTracker.reset(*I, &LRS);
454  }
455 
456  for ( ; ; ) {
457  I = RPTracker.getNext();
458 
459  if (Regions[CurRegion].first == I) {
460  LiveIns[CurRegion] = RPTracker.getLiveRegs();
461  RPTracker.clearMaxPressure();
462  }
463 
464  if (Regions[CurRegion].second == I) {
465  Pressure[CurRegion] = RPTracker.moveMaxPressure();
466  if (CurRegion-- == RegionIdx)
467  break;
468  }
469  RPTracker.advanceToNext();
470  RPTracker.advanceBeforeNext();
471  }
472 
473  if (OnlySucc) {
474  if (I != MBB->end()) {
475  RPTracker.advanceToNext();
476  RPTracker.advance(MBB->end());
477  }
478  RPTracker.reset(*OnlySucc->begin(), &RPTracker.getLiveRegs());
479  RPTracker.advanceBeforeNext();
480  MBBLiveIns[OnlySucc] = RPTracker.moveLiveRegs();
481  }
482 }
483 
485 GCNScheduleDAGMILive::getBBLiveInMap() const {
486  assert(!Regions.empty());
487  std::vector<MachineInstr *> BBStarters;
488  BBStarters.reserve(Regions.size());
489  auto I = Regions.rbegin(), E = Regions.rend();
490  auto *BB = I->first->getParent();
491  do {
492  auto *MI = &*skipDebugInstructionsForward(I->first, I->second);
493  BBStarters.push_back(MI);
494  do {
495  ++I;
496  } while (I != E && I->first->getParent() == BB);
497  } while (I != E);
498  return getLiveRegMap(BBStarters, false /*After*/, *LIS);
499 }
500 
503  LLVM_DEBUG(dbgs() << "All regions recorded, starting actual scheduling.\n");
504 
505  LiveIns.resize(Regions.size());
506  Pressure.resize(Regions.size());
507 
508  if (!Regions.empty())
509  BBLiveInMap = getBBLiveInMap();
510 
511  do {
512  Stage++;
513  RegionIdx = 0;
514  MachineBasicBlock *MBB = nullptr;
515 
516  if (Stage > 1) {
517  // Retry function scheduling if we found resulting occupancy and it is
518  // lower than used for first pass scheduling. This will give more freedom
519  // to schedule low register pressure blocks.
520  // Code is partially copied from MachineSchedulerBase::scheduleRegions().
521 
522  if (!LIS || StartingOccupancy <= MinOccupancy)
523  break;
524 
525  LLVM_DEBUG(
526  dbgs()
527  << "Retrying function scheduling with lowest recorded occupancy "
528  << MinOccupancy << ".\n");
529 
530  S.setTargetOccupancy(MinOccupancy);
531  }
532 
533  for (auto Region : Regions) {
534  RegionBegin = Region.first;
535  RegionEnd = Region.second;
536 
537  if (RegionBegin->getParent() != MBB) {
538  if (MBB) finishBlock();
539  MBB = RegionBegin->getParent();
540  startBlock(MBB);
541  if (Stage == 1)
542  computeBlockPressure(MBB);
543  }
544 
545  unsigned NumRegionInstrs = std::distance(begin(), end());
546  enterRegion(MBB, begin(), end(), NumRegionInstrs);
547 
548  // Skip empty scheduling regions (0 or 1 schedulable instructions).
549  if (begin() == end() || begin() == std::prev(end())) {
550  exitRegion();
551  continue;
552  }
553 
554  LLVM_DEBUG(dbgs() << "********** MI Scheduling **********\n");
555  LLVM_DEBUG(dbgs() << MF.getName() << ":" << printMBBReference(*MBB) << " "
556  << MBB->getName() << "\n From: " << *begin()
557  << " To: ";
558  if (RegionEnd != MBB->end()) dbgs() << *RegionEnd;
559  else dbgs() << "End";
560  dbgs() << " RegionInstrs: " << NumRegionInstrs << '\n');
561 
562  schedule();
563 
564  exitRegion();
565  ++RegionIdx;
566  }
567  finishBlock();
568 
569  } while (Stage < 2);
570 }
uint64_t CallInst * C
Interface definition for SIRegisterInfo.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
SUnit * pickNode(bool &IsTopNode) override
Pick the best node to balance the schedule. Implements MachineSchedStrategy.
AMDGPU specific subclass of TargetSubtarget.
void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS)
Use liveness information to find dead defs not marked with a dead flag and move them to the DeadDefs ...
Each Scheduling boundary is associated with ready queues.
static void printLiveRegs(raw_ostream &OS, const LiveRegSet &LiveRegs, const MachineRegisterInfo &MRI)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
const MachineSchedContext * Context
This is a minimal scheduler strategy.
decltype(MaxPressure) moveMaxPressure()
void startBlock(MachineBasicBlock *bb) override
Prepares to perform scheduling in the given block.
bool reset(const MachineInstr &MI, const LiveRegSet *LiveRegs=nullptr)
void setUnitInc(int Inc)
void traceCandidate(const SchedCandidate &Cand)
unsigned second
void reset(const CandPolicy &NewPolicy)
ScheduleDAGMI * DAG
bool isBottomReady() const
Definition: ScheduleDAG.h:449
unsigned NumRegionInstrs
Instructions in this region (distance(RegionBegin, RegionEnd)).
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
std::unique_ptr< MachineSchedStrategy > SchedImpl
decltype(LiveRegs) moveLiveRegs()
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
MachineFunction & MF
Machine function.
Definition: ScheduleDAG.h:560
bool isScheduled
True once scheduled.
Definition: ScheduleDAG.h:284
const RegPressureTracker & getBotRPTracker() const
decltype(LiveRegs) const & getLiveRegs() const
Definition: BitVector.h:937
MachineBasicBlock::iterator RegionEnd
The end of the range to be scheduled.
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
unsigned getOccupancy(const GCNSubtarget &ST) const
SlotIndexes pass.
Definition: SlotIndexes.h:314
void limitOccupancy(const MachineFunction &MF)
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def...
Definition: SlotIndexes.h:254
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
MachineBasicBlock::iterator top() const
MachineSchedPolicy RegionPolicy
MachineBasicBlock::iterator begin() const
Returns an iterator to the top of the current scheduling region.
GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI, const LiveIntervals &LIS)
bool isTopReady() const
Definition: ScheduleDAG.h:446
void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, bool TrackLaneMasks, bool IgnoreDead)
Analyze the given instruction MI and fill in the Uses, Defs and DeadDefs list based on the MachineOpe...
List of registers defined and used by a machine instruction.
const MachineBasicBlock::const_iterator getNext() const
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
RegisterClassInfo * RegClassInfo
unsigned getMaxNumSGPRs(unsigned WavesPerEU, bool Addressable) const
CandReason
Represent the type of SchedCandidate found within a single queue.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
Definition: ScheduleDAG.h:373
Helpers for implementing custom MachineSchedStrategy classes.
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
GCNScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void removeReady(SUnit *SU)
Remove SU from the ready set for this boundary.
SlotIndex getMBBStartIdx(unsigned Num) const
Returns the first index in the given basic block number.
Definition: SlotIndexes.h:469
DenseMap< MachineInstr *, GCNRPTracker::LiveRegSet > getLiveRegMap(Range &&R, bool After, LiveIntervals &LIS)
creates a map MachineInstr -> LiveRegSet R - range of iterators on instructions After - upon entry or...
Store the state used by GenericScheduler heuristics, required for the lifetime of one invocation of p...
Track the current register pressure at some position in the instruction stream, and remember the high...
unsigned getSGPRPressureSet() const
Policy for scheduling the next instruction in the candidate&#39;s zone.
unsigned getNumAllocatableRegs(const TargetRegisterClass *RC) const
getNumAllocatableRegs - Returns the number of actually allocatable registers in RC in the current fun...
const TargetSchedModel * SchedModel
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
const TargetRegisterInfo * TRI
ScheduleDAGMILive * DAG
void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone, SchedBoundary *OtherZone)
Set the CandPolicy given a scheduling zone given the current resources and latencies inside and outsi...
unsigned first
unsigned getVGPRPressureSet() const
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Definition: STLExtras.h:209
const std::vector< unsigned > & getRegSetPressureAtPos() const
Get the register set pressure at the current position, which may be less than the pressure across the...
void adjustLaneLiveness(const LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos, MachineInstr *AddFlagsMI=nullptr)
Use liveness information to find out which uses/defs are partially undefined/dead and adjust the Regi...
GenericScheduler shrinks the unscheduled zone using heuristics to balance the schedule.
unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const override
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
const RegPressureTracker & getTopRPTracker() const
MachineInstr * remove(MachineInstr *I)
Remove the unbundled instruction from the instruction list without deleting it.
void initResourceDelta(const ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
PressureChange CriticalMax
unsigned succ_size() const
IterT skipDebugInstructionsForward(IterT It, IterT End)
Increment It until it points to a non-debug instruction or to End and return the resulting iterator...
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI, Range &&LiveRegs)
void initialize(ScheduleDAGMI *dag) override
Initialize the strategy after building the DAG for a new region.
virtual void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const
Apply a set of heuristics to a new candidate.
Representation of each machine instruction.
Definition: MachineInstr.h:64
LiveIntervals * LIS
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Interface definition for SIInstrInfo.
const TargetRegisterInfo * TRI
Target processor register info.
Definition: ScheduleDAG.h:559
SUnit * pickOnlyChoice()
Call this before applying any other heuristics to the Available queue.
Status of an instruction&#39;s critical resource consumption.
SchedCandidate BotCand
Candidate last picked from Bot boundary.
MachineBasicBlock::iterator bottom() const
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
#define I(x, y, z)
Definition: MD5.cpp:58
Capture a change in pressure for a single pressure set.
void getUpwardPressure(const MachineInstr *MI, std::vector< unsigned > &PressureResult, std::vector< unsigned > &MaxPressureResult)
Get the pressure of each PSet after traversing this instruction bottom-up.
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
SlotIndexes * getSlotIndexes() const
unsigned NodeNum
Entry # of node in the node vector.
Definition: ScheduleDAG.h:264
unsigned getMaxNumVGPRs(unsigned WavesPerEU) const
MachineBasicBlock::iterator end() const
Returns an iterator to the bottom of the current scheduling region.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void print(raw_ostream &OS, const GCNSubtarget *ST=nullptr) const
GCNMaxOccupancySchedStrategy(const MachineSchedContext *C)
SchedCandidate TopCand
Candidate last picked from Top boundary.
void finalizeSchedule() override
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)
void getDownwardPressure(const MachineInstr *MI, std::vector< unsigned > &PressureResult, std::vector< unsigned > &MaxPressureResult)
Get the pressure of each PSet after traversing this instruction top-down.
MachineBasicBlock * BB
The block in which to insert instructions.
IRTranslator LLVM IR MI
bool empty() const
MachineRegisterInfo & MRI
Virtual/real register map.
Definition: ScheduleDAG.h:561
#define LLVM_DEBUG(X)
Definition: Debug.h:122
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:83
void initialize(ScheduleDAGMI *DAG) override
Initialize the strategy after building the DAG for a new region.
void finishBlock() override
Cleans up after scheduling in the given block.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
RegPressureTracker RPTracker
void handleMove(MachineInstr &MI, bool UpdateFlags=false)
Call this method to notify LiveIntervals that instruction MI has been moved within a basic block...
Scheduling unit. This is a node in the scheduling DAG.
Definition: ScheduleDAG.h:242