LLVM 24.0.0git
GCNIterativeScheduler.cpp
Go to the documentation of this file.
1//===- GCNIterativeScheduler.cpp ------------------------------------------===//
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 file implements the class GCNIterativeScheduler.
11///
12//===----------------------------------------------------------------------===//
13
15#include "AMDGPUIGroupLP.h"
16#include "GCNSchedStrategy.h"
18
19using namespace llvm;
20
21#define DEBUG_TYPE "machine-scheduler"
22
23namespace llvm {
24
25std::vector<const SUnit *> makeMinRegSchedule(ArrayRef<const SUnit *> TopRoots,
26 const ScheduleDAG &DAG);
27
28std::vector<const SUnit *> makeGCNILPScheduler(ArrayRef<const SUnit *> BotRoots,
29 const ScheduleDAG &DAG);
30} // namespace llvm
31
32// shim accessors for different order containers
34 return MI;
35}
36static inline MachineInstr *getMachineInstr(const SUnit *SU) {
37 return SU->getInstr();
38}
39static inline MachineInstr *getMachineInstr(const SUnit &SU) {
40 return SU.getInstr();
41}
42
43#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
45static void printRegion(raw_ostream &OS,
48 const LiveIntervals *LIS,
49 unsigned MaxInstNum =
50 std::numeric_limits<unsigned>::max()) {
51 auto *BB = Begin->getParent();
52 OS << BB->getParent()->getName() << ":" << printMBBReference(*BB) << ' '
53 << BB->getName() << ":\n";
54 auto I = Begin;
55 MaxInstNum = std::max(MaxInstNum, 1u);
56 for (; I != End && MaxInstNum; ++I, --MaxInstNum) {
57 if (!I->isDebugInstr() && LIS)
58 OS << LIS->getInstructionIndex(*I);
59 OS << '\t' << *I;
60 }
61 if (I != End) {
62 OS << "\t...\n";
63 I = std::prev(End);
64 if (!I->isDebugInstr() && LIS)
65 OS << LIS->getInstructionIndex(*I);
66 OS << '\t' << *I;
67 }
68 if (End != BB->end()) { // print boundary inst if present
69 OS << "----\n";
70 if (LIS) OS << LIS->getInstructionIndex(*End) << '\t';
71 OS << *End;
72 }
73}
74
79 const LiveIntervals *LIS) {
80 auto *const BB = Begin->getParent();
81 const auto &MRI = BB->getParent()->getRegInfo();
82
83 const auto LiveIns = getLiveRegsBefore(*Begin, *LIS);
84 OS << "LIn RP: " << print(getRegPressure(MRI, LiveIns));
85
86 const auto BottomMI = End == BB->end() ? std::prev(End) : End;
87 const auto LiveOuts = getLiveRegsAfter(*BottomMI, *LIS);
88 OS << "LOt RP: " << print(getRegPressure(MRI, LiveOuts));
89}
90
93 const auto &ST = MF.getSubtarget<GCNSubtarget>();
94 for (auto *const R : Regions) {
95 OS << "Region to schedule ";
96 printRegion(OS, R->Begin, R->End, LIS, 1);
97 printLivenessInfo(OS, R->Begin, R->End, LIS);
98 OS << "Max RP: " << print(R->MaxPressure, &ST);
99 }
100}
101
104 const Region *R,
105 const GCNRegPressure &RP) const {
106 OS << "\nAfter scheduling ";
107 printRegion(OS, R->Begin, R->End, LIS);
108 printSchedRP(OS, R->MaxPressure, RP);
109 OS << '\n';
110}
111
114 const GCNRegPressure &Before,
115 const GCNRegPressure &After) const {
116 const auto &ST = MF.getSubtarget<GCNSubtarget>();
117 OS << "RP before: " << print(Before, &ST)
118 << "RP after: " << print(After, &ST);
119}
120#endif
121
122void GCNIterativeScheduler::swapIGLPMutations(const Region &R, bool IsReentry) {
123 bool HasIGLPInstrs = false;
124 const SIInstrInfo *SII = static_cast<const SIInstrInfo *>(TII);
125 for (MachineBasicBlock::iterator I = R.Begin; I != R.End; I++) {
126 if (SII->isIGLPMutationOnly(I->getOpcode())) {
127 HasIGLPInstrs = true;
128 break;
129 }
130 }
131
132 if (HasIGLPInstrs) {
133 SavedMutations.clear();
135 auto SchedPhase = IsReentry ? AMDGPU::SchedulingPhase::PreRAReentry
137
139 }
140}
141
142// DAG builder helper
146
147 SmallVector<SUnit*, 8> BotRoots;
148public:
149 BuildDAG(const Region &R, GCNIterativeScheduler &_Sch, bool IsReentry = false)
150 : Sch(_Sch) {
151 auto *BB = R.Begin->getParent();
152 Sch.BaseClass::startBlock(BB);
153 Sch.BaseClass::enterRegion(BB, R.Begin, R.End, R.NumRegionInstrs);
154 Sch.swapIGLPMutations(R, IsReentry);
155 Sch.buildSchedGraph(Sch.AA, nullptr, nullptr, nullptr,
156 /*TrackLaneMask*/true);
157 Sch.postProcessDAG();
158 Sch.Topo.InitDAGTopologicalSorting();
159 Sch.findRootsAndBiasEdges(TopRoots, BotRoots);
160 }
161
163 Sch.BaseClass::exitRegion();
164 Sch.BaseClass::finishBlock();
165 }
166
168 return TopRoots;
169 }
171 return BotRoots;
172 }
173};
174
177 Region &Rgn;
178 std::unique_ptr<MachineSchedStrategy> SaveSchedImpl;
179 GCNRegPressure SaveMaxRP;
180
181public:
183 MachineSchedStrategy &OverrideStrategy,
185 : Sch(_Sch)
186 , Rgn(R)
187 , SaveSchedImpl(std::move(_Sch.SchedImpl))
188 , SaveMaxRP(R.MaxPressure) {
189 Sch.SchedImpl.reset(&OverrideStrategy);
190 auto *BB = R.Begin->getParent();
191 Sch.BaseClass::startBlock(BB);
192 Sch.BaseClass::enterRegion(BB, R.Begin, R.End, R.NumRegionInstrs);
193 }
194
196 Sch.BaseClass::exitRegion();
197 Sch.BaseClass::finishBlock();
198 Sch.SchedImpl.release();
199 Sch.SchedImpl = std::move(SaveSchedImpl);
200 }
201
202 void schedule() {
203 assert(Sch.RegionBegin == Rgn.Begin && Sch.RegionEnd == Rgn.End);
204 LLVM_DEBUG(dbgs() << "\nScheduling ";
205 printRegion(dbgs(), Rgn.Begin, Rgn.End, Sch.LIS, 2));
206 Sch.BaseClass::schedule();
207
208 // Unfortunately placeDebugValues incorrectly modifies RegionEnd, restore
209 Sch.RegionEnd = Rgn.End;
210 //assert(Rgn.End == Sch.RegionEnd);
211 Rgn.Begin = Sch.RegionBegin;
212 Rgn.MaxPressure.clear();
213 }
214
216 assert(Sch.RegionBegin == Rgn.Begin && Sch.RegionEnd == Rgn.End);
217 // DAG SUnits are stored using original region's order
218 // so just use SUnits as the restoring schedule
219 Sch.scheduleRegion(Rgn, Sch.SUnits, SaveMaxRP);
220 }
221};
222
223namespace {
224
225// just a stub to make base class happy
226class SchedStrategyStub : public MachineSchedStrategy {
227public:
228 bool shouldTrackPressure() const override { return false; }
229 bool shouldTrackLaneMasks() const override { return false; }
230 void initialize(ScheduleDAGMI *DAG) override {}
231 SUnit *pickNode(bool &IsTopNode) override { return nullptr; }
232 void schedNode(SUnit *SU, bool IsTopNode) override {}
233 void releaseTopNode(SUnit *SU) override {}
234 void releaseBottomNode(SUnit *SU) override {}
235};
236
237} // end anonymous namespace
238
240 StrategyKind S)
241 : BaseClass(C, std::make_unique<SchedStrategyStub>())
242 , Context(C)
243 , Strategy(S)
244 , UPTracker(*LIS) {
245}
246
247// returns max pressure for a region
251 const {
252 // For the purpose of pressure tracking bottom inst of the region should
253 // be also processed. End is either BB end, BB terminator inst or sched
254 // boundary inst.
255 auto const BBEnd = Begin->getParent()->end();
256 auto const BottomMI = End == BBEnd ? std::prev(End) : End;
257
258 // scheduleRegions walks bottom to top, so its likely we just get next
259 // instruction to track
260 auto AfterBottomMI = std::next(BottomMI);
261 if (AfterBottomMI == BBEnd ||
262 &*AfterBottomMI != UPTracker.getLastTrackedMI()) {
263 UPTracker.reset(*BottomMI);
264 } else {
265 assert(UPTracker.isValid());
266 }
267
268 for (auto I = BottomMI; I != Begin; --I)
269 UPTracker.recede(*I);
270
271 UPTracker.recede(*Begin);
272
273 assert(UPTracker.isValid() ||
274 (dbgs() << "Tracked region ",
275 printRegion(dbgs(), Begin, End, LIS), false));
276 return UPTracker.getMaxPressureAndReset();
277}
278
279// returns max pressure for a tentative schedule
280template <typename Range> GCNRegPressure
282 Range &&Schedule) const {
283 auto const BBEnd = R.Begin->getParent()->end();
285 if (R.End != BBEnd) {
286 // R.End points to the boundary instruction but the
287 // schedule doesn't include it
288 RPTracker.reset(*R.End);
289 RPTracker.recede(*R.End);
290 } else {
291 // R.End doesn't point to the boundary instruction
292 RPTracker.reset(*std::prev(BBEnd));
293 }
294 for (auto I = Schedule.end(), B = Schedule.begin(); I != B;) {
295 RPTracker.recede(*getMachineInstr(*--I));
296 }
297 return RPTracker.getMaxPressureAndReset();
298}
299
303 unsigned NumRegionInstrs) {
305 if (NumRegionInstrs > 2) {
306 Regions.push_back(
307 new (Alloc.Allocate())
308 Region { Begin, End, NumRegionInstrs,
309 getRegionPressure(Begin, End), nullptr });
310 }
311}
312
314 // do nothing
316 if (!Regions.empty() && Regions.back()->Begin == RegionBegin) {
317 dbgs() << "Max RP: "
318 << print(Regions.back()->MaxPressure,
319 &MF.getSubtarget<GCNSubtarget>());
320 } dbgs()
321 << '\n';);
322}
323
325 if (Regions.empty())
326 return;
327 switch (Strategy) {
328 case SCHEDULE_MINREGONLY: scheduleMinReg(); break;
329 case SCHEDULE_MINREGFORCED: scheduleMinReg(true); break;
331 case SCHEDULE_ILP: scheduleILP(false); break;
332 }
333}
334
335// Detach schedule from SUnits and interleave it with debug values.
336// Returned schedule becomes independent of DAG state.
337std::vector<MachineInstr*>
339 std::vector<MachineInstr*> Res;
340 Res.reserve(Schedule.size() * 2);
341
342 if (FirstDbgValue)
343 Res.push_back(FirstDbgValue);
344
345 const auto DbgB = DbgValues.begin(), DbgE = DbgValues.end();
346 for (const auto *SU : Schedule) {
347 Res.push_back(SU->getInstr());
348 const auto &D = std::find_if(DbgB, DbgE, [SU](decltype(*DbgB) &P) {
349 return P.second == SU->getInstr();
350 });
351 if (D != DbgE)
352 Res.push_back(D->first);
353 }
354 return Res;
355}
356
358 ScheduleRef Schedule,
359 const GCNRegPressure &MaxRP) {
360 R.BestSchedule.reset(
361 new TentativeSchedule{ detachSchedule(Schedule), MaxRP });
362}
363
365 assert(R.BestSchedule.get() && "No schedule specified");
366 scheduleRegion(R, R.BestSchedule->Schedule, R.BestSchedule->MaxPressure);
367 R.BestSchedule.reset();
368}
369
371 assert(!MI.isDebugInstr());
372
373 for (MachineOperand &Op : MI.all_defs())
374 Op.setIsUndef(false);
375
376 RegisterOperands RegOpers;
377 RegOpers.collect(MI, *TRI, MRI, /*ShouldTrackLaneMasks=*/true,
378 /*IgnoreDead=*/false);
379 RegOpers.adjustLaneLiveness(*LIS, MRI, MI);
380}
381
383 for (MachineBasicBlock::iterator I = R.Begin; I != R.End; ++I) {
384 if (!I->isDebugInstr())
386 }
387}
388
389// minimal required region scheduler, works for ranges of SUnits*,
390// SUnits or MachineIntrs*
391template <typename Range>
393 const GCNRegPressure &MaxRP) {
394 assert(RegionBegin == R.Begin && RegionEnd == R.End);
395 assert(LIS != nullptr);
396#ifndef NDEBUG
397 const auto SchedMaxRP = getSchedulePressure(R, Schedule);
398#endif
399 auto *BB = R.Begin->getParent();
400 auto Top = R.Begin;
401 for (const auto &I : Schedule) {
402 auto MI = getMachineInstr(I);
403
404 MachineBasicBlock::iterator MII = MI->getIterator();
405 if (MII != Top) {
406 bool NonDebugReordered =
407 !MI->isDebugInstr() && skipDebugInstructionsForward(Top, MII) != MII;
408 BB->remove(MI);
409 BB->insert(Top, MI);
410 if (NonDebugReordered)
411 LIS->handleMove(*MI, true);
412 }
413 if (!MI->isDebugInstr())
415 Top = std::next(MI->getIterator());
416 }
417 RegionBegin = getMachineInstr(Schedule.front());
418
419 // Schedule consisting of MachineInstr* is considered 'detached'
420 // and already interleaved with debug values
421 if (!std::is_same_v<decltype(*Schedule.begin()), MachineInstr*>) {
423 // Unfortunately placeDebugValues incorrectly modifies RegionEnd, restore
424 // assert(R.End == RegionEnd);
425 RegionEnd = R.End;
426 }
427
428 R.Begin = RegionBegin;
429 R.MaxPressure = MaxRP;
430
431#ifndef NDEBUG
432 const auto RegionMaxRP = getRegionPressure(R);
433 const auto &ST = MF.getSubtarget<GCNSubtarget>();
434#endif
435 assert(
436 (SchedMaxRP == RegionMaxRP && (MaxRP.empty() || SchedMaxRP == MaxRP)) ||
437 (dbgs() << "Max RP mismatch!!!\n"
438 "RP for schedule (calculated): "
439 << print(SchedMaxRP, &ST)
440 << "RP for schedule (reported): " << print(MaxRP, &ST)
441 << "RP after scheduling: " << print(RegionMaxRP, &ST),
442 false));
443}
444
445// Sort recorded regions by pressure - highest at the front
447 llvm::sort(Regions, [this, TargetOcc](const Region *R1, const Region *R2) {
448 return R2->MaxPressure.less(MF, R1->MaxPressure, TargetOcc);
449 });
450}
451
452///////////////////////////////////////////////////////////////////////////////
453// Legacy MaxOccupancy Strategy
454
455// Tries to increase occupancy applying minreg scheduler for a sequence of
456// most demanding regions. Obtained schedules are saved as BestSchedule for a
457// region.
458// TargetOcc is the best achievable occupancy for a kernel.
459// Returns better occupancy on success or current occupancy on fail.
460// BestSchedules aren't deleted on fail.
462 // TODO: assert Regions are sorted descending by pressure
463 const auto &ST = MF.getSubtarget<GCNSubtarget>();
464 const unsigned DynamicVGPRBlockSize =
465 MF.getInfo<SIMachineFunctionInfo>()->getDynamicVGPRBlockSize();
466 const auto Occ =
467 Regions.front()->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize);
468 LLVM_DEBUG(dbgs() << "Trying to improve occupancy, target = " << TargetOcc
469 << ", current = " << Occ << '\n');
470
471 auto NewOcc = TargetOcc;
472 for (auto *R : Regions) {
473 // Always build the DAG to add mutations
474 BuildDAG DAG(*R, *this);
475
476 if (R->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize) >= NewOcc)
477 continue;
478
479 LLVM_DEBUG(printRegion(dbgs(), R->Begin, R->End, LIS, 3);
480 printLivenessInfo(dbgs(), R->Begin, R->End, LIS));
481
482 const auto MinSchedule = makeMinRegSchedule(DAG.getTopRoots(), *this);
483 const auto MaxRP = getSchedulePressure(*R, MinSchedule);
484 LLVM_DEBUG(dbgs() << "Occupancy improvement attempt:\n";
485 printSchedRP(dbgs(), R->MaxPressure, MaxRP));
486
487 NewOcc = std::min(NewOcc, MaxRP.getOccupancy(ST, DynamicVGPRBlockSize));
488 if (NewOcc <= Occ)
489 break;
490
491 setBestSchedule(*R, MinSchedule, MaxRP);
492 }
493 LLVM_DEBUG(dbgs() << "New occupancy = " << NewOcc
494 << ", prev occupancy = " << Occ << '\n');
495 if (NewOcc > Occ) {
497 MFI->increaseOccupancy(MF, NewOcc);
498 }
499
500 return std::max(NewOcc, Occ);
501}
502
504 bool TryMaximizeOccupancy) {
505 const auto &ST = MF.getSubtarget<GCNSubtarget>();
507 auto TgtOcc = MFI->getMinAllowedOccupancy();
508 unsigned DynamicVGPRBlockSize = MFI->getDynamicVGPRBlockSize();
509
510 sortRegionsByPressure(TgtOcc);
511 auto Occ =
512 Regions.front()->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize);
513
514 bool IsReentry = false;
515 if (TryMaximizeOccupancy && Occ < TgtOcc) {
516 Occ = tryMaximizeOccupancy(TgtOcc);
517 IsReentry = true;
518 }
519
520 // This is really weird but for some magic scheduling regions twice
521 // gives performance improvement
522 const int NumPasses = Occ < TgtOcc ? 2 : 1;
523
524 TgtOcc = std::min(Occ, TgtOcc);
525 LLVM_DEBUG(dbgs() << "Scheduling using default scheduler, "
526 "target occupancy = "
527 << TgtOcc << '\n');
528 GCNMaxOccupancySchedStrategy LStrgy(Context, /*IsLegacyScheduler=*/true);
529 unsigned FinalOccupancy = std::min(Occ, MFI->getOccupancy());
530
531 for (int I = 0; I < NumPasses; ++I) {
532 // running first pass with TargetOccupancy = 0 mimics previous scheduling
533 // approach and is a performance magic
534 LStrgy.setTargetOccupancy(I == 0 ? 0 : TgtOcc);
535 for (auto *R : Regions) {
536 OverrideLegacyStrategy Ovr(*R, LStrgy, *this);
537 IsReentry |= I > 0;
538 swapIGLPMutations(*R, IsReentry);
539 Ovr.schedule();
540 const auto RP = getRegionPressure(*R);
541 LLVM_DEBUG(printSchedRP(dbgs(), R->MaxPressure, RP));
542
543 if (RP.getOccupancy(ST, DynamicVGPRBlockSize) < TgtOcc) {
544 LLVM_DEBUG(dbgs() << "Didn't fit into target occupancy O" << TgtOcc);
545 if (R->BestSchedule.get() && R->BestSchedule->MaxPressure.getOccupancy(
546 ST, DynamicVGPRBlockSize) >= TgtOcc) {
547 LLVM_DEBUG(dbgs() << ", scheduling minimal register\n");
548 scheduleBest(*R);
549 } else {
550 LLVM_DEBUG(dbgs() << ", restoring\n");
551 Ovr.restoreOrder();
552 assert(R->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize) >=
553 TgtOcc);
554 }
555 }
556 FinalOccupancy =
557 std::min(FinalOccupancy, RP.getOccupancy(ST, DynamicVGPRBlockSize));
558 }
559 }
560 MFI->limitOccupancy(FinalOccupancy);
561}
562
563///////////////////////////////////////////////////////////////////////////////
564// Minimal Register Strategy
565
568 const auto TgtOcc = MFI->getOccupancy();
569 sortRegionsByPressure(TgtOcc);
570
571 auto MaxPressure = Regions.front()->MaxPressure;
572 for (auto *R : Regions) {
573 if (!force && R->MaxPressure.less(MF, MaxPressure, TgtOcc))
574 break;
575
576 BuildDAG DAG(*R, *this);
577 const auto MinSchedule = makeMinRegSchedule(DAG.getTopRoots(), *this);
578
579 const auto RP = getSchedulePressure(*R, MinSchedule);
580 LLVM_DEBUG(if (R->MaxPressure.less(MF, RP, TgtOcc)) {
581 dbgs() << "\nWarning: Pressure becomes worse after minreg!";
582 printSchedRP(dbgs(), R->MaxPressure, RP);
583 });
584
585 if (!force && MaxPressure.less(MF, RP, TgtOcc))
586 break;
587
588 scheduleRegion(*R, MinSchedule, RP);
590
591 MaxPressure = RP;
592 }
593}
594
595///////////////////////////////////////////////////////////////////////////////
596// ILP scheduler port
597
599 bool TryMaximizeOccupancy) {
600 const auto &ST = MF.getSubtarget<GCNSubtarget>();
602 auto TgtOcc = MFI->getMinAllowedOccupancy();
603 unsigned DynamicVGPRBlockSize = MFI->getDynamicVGPRBlockSize();
604
605 sortRegionsByPressure(TgtOcc);
606 auto Occ =
607 Regions.front()->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize);
608
609 bool IsReentry = false;
610 if (TryMaximizeOccupancy && Occ < TgtOcc) {
611 Occ = tryMaximizeOccupancy(TgtOcc);
612 IsReentry = true;
613 }
614
615 TgtOcc = std::min(Occ, TgtOcc);
616 LLVM_DEBUG(dbgs() << "Scheduling using default scheduler, "
617 "target occupancy = "
618 << TgtOcc << '\n');
619
620 unsigned FinalOccupancy = std::min(Occ, MFI->getOccupancy());
621 for (auto *R : Regions) {
622 BuildDAG DAG(*R, *this, IsReentry);
623 const auto ILPSchedule = makeGCNILPScheduler(DAG.getBottomRoots(), *this);
624
625 const auto RP = getSchedulePressure(*R, ILPSchedule);
626 LLVM_DEBUG(printSchedRP(dbgs(), R->MaxPressure, RP));
627
628 if (RP.getOccupancy(ST, DynamicVGPRBlockSize) < TgtOcc) {
629 LLVM_DEBUG(dbgs() << "Didn't fit into target occupancy O" << TgtOcc);
630 if (R->BestSchedule.get() && R->BestSchedule->MaxPressure.getOccupancy(
631 ST, DynamicVGPRBlockSize) >= TgtOcc) {
632 LLVM_DEBUG(dbgs() << ", scheduling minimal register\n");
633 scheduleBest(*R);
634 } else {
636 }
637 } else {
638 scheduleRegion(*R, ILPSchedule, RP);
640 FinalOccupancy =
641 std::min(FinalOccupancy, RP.getOccupancy(ST, DynamicVGPRBlockSize));
642 }
643 }
644 MFI->limitOccupancy(FinalOccupancy);
645}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:678
static LLVM_DUMP_METHOD void printLivenessInfo(raw_ostream &OS, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, const LiveIntervals *LIS)
static MachineInstr * getMachineInstr(MachineInstr *MI)
static LLVM_DUMP_METHOD void printRegion(raw_ostream &OS, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, const LiveIntervals *LIS, unsigned MaxInstNum=std::numeric_limits< unsigned >::max())
This file defines the class GCNIterativeScheduler, which uses an iterative approach to find a best sc...
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
#define R2(n)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define P(N)
#define LLVM_DEBUG(...)
Definition Debug.h:119
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
ArrayRef< const SUnit * > getTopRoots() const
BuildDAG(const Region &R, GCNIterativeScheduler &_Sch, bool IsReentry=false)
OverrideLegacyStrategy(Region &R, MachineSchedStrategy &OverrideStrategy, GCNIterativeScheduler &_Sch)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
SpecificBumpPtrAllocator< Region > Alloc
void printSchedRP(raw_ostream &OS, const GCNRegPressure &Before, const GCNRegPressure &After) const
void enterRegion(MachineBasicBlock *BB, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned RegionInstrs) override
Initialize the DAG and common scheduler state for a new scheduling region.
void sortRegionsByPressure(unsigned TargetOcc)
std::vector< Region * > Regions
void restoreLivenessFlags(MachineInstr &MI)
void scheduleILP(bool TryMaximizeOccupancy=true)
void swapIGLPMutations(const Region &R, bool IsReentry)
GCNIterativeScheduler(MachineSchedContext *C, StrategyKind S)
void printSchedResult(raw_ostream &OS, const Region *R, const GCNRegPressure &RP) const
unsigned tryMaximizeOccupancy(unsigned TargetOcc=std::numeric_limits< unsigned >::max())
void printRegions(raw_ostream &OS) const
void setBestSchedule(Region &R, ScheduleRef Schedule, const GCNRegPressure &MaxRP=GCNRegPressure())
void finalizeSchedule() override
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
void scheduleLegacyMaxOccupancy(bool TryMaximizeOccupancy=true)
std::vector< std::unique_ptr< ScheduleDAGMutation > > SavedMutations
void restoreRegionLivenessFlags(const Region &R)
void schedule() override
Orders nodes according to selected style.
GCNRegPressure getSchedulePressure(const Region &R, Range &&Schedule) const
void scheduleMinReg(bool force=false)
GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End) const
ArrayRef< const SUnit * > ScheduleRef
void scheduleRegion(Region &R, Range &&Schedule, const GCNRegPressure &MaxRP=GCNRegPressure())
std::vector< MachineInstr * > detachSchedule(ScheduleRef Schedule) const
The goal of this scheduling strategy is to maximize kernel occupancy (i.e.
void setTargetOccupancy(unsigned Occ)
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
MachineInstrBundleIterator< MachineInstr > iterator
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
MachineSchedStrategy - Interface to the scheduling algorithm used by ScheduleDAGMI.
List of registers defined and used by a machine instruction.
LLVM_ABI void adjustLaneLiveness(const LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos)
Use liveness information to find out which uses/defs are partially undefined/dead at Pos and adjust t...
LLVM_ABI 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...
bool isIGLPMutationOnly(unsigned Opcode) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Scheduling unit. This is a node in the scheduling DAG.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
MachineBasicBlock * BB
The block in which to insert instructions.
MachineBasicBlock::iterator RegionEnd
The end of the range to be scheduled.
DbgValueVector DbgValues
Remember instruction that precedes DBG_VALUE.
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
unsigned NumRegionInstrs
Instructions in this region (distance(RegionBegin, RegionEnd)).
const MachineFrameInfo & MFI
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
RegPressureTracker RPTracker
std::unique_ptr< MachineSchedStrategy > SchedImpl
void addMutation(std::unique_ptr< ScheduleDAGMutation > Mutation)
Add a postprocessing step to the DAG builder.
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
std::vector< std::unique_ptr< ScheduleDAGMutation > > Mutations
Ordered list of DAG postprocessing steps.
MachineRegisterInfo & MRI
Virtual/real register map.
const TargetInstrInfo * TII
Target instruction information.
const TargetRegisterInfo * TRI
Target processor register info.
MachineFunction & MF
Machine function.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This is an optimization pass for GlobalISel generic memory operations.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI, Range &&LiveRegs)
std::unique_ptr< ScheduleDAGMutation > createIGroupLPDAGMutation(AMDGPU::SchedulingPhase Phase)
Phase specifes whether or not this is a reentry into the IGroupLPDAGMutation.
IterT skipDebugInstructionsForward(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It until it points to a non-debug instruction or to End and return the resulting iterator.
GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI, const LiveIntervals &LIS)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
DWARFExpression::Operation Op
std::vector< const SUnit * > makeGCNILPScheduler(ArrayRef< const SUnit * > BotRoots, const ScheduleDAG &DAG)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
std::vector< const SUnit * > makeMinRegSchedule(ArrayRef< const SUnit * > TopRoots, const ScheduleDAG &DAG)
GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI, const LiveIntervals &LIS)
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...