LLVM 24.0.0git
GCNSchedStrategy.h
Go to the documentation of this file.
1//===-- GCNSchedStrategy.h - GCN Scheduler Strategy -*- C++ -*-------------===//
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//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H
14#define LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H
15
16#include "GCNRegPressure.h"
17#include "llvm/ADT/DenseMap.h"
24
25namespace llvm {
26
27struct VGPRThresholdParser : public cl::parser<unsigned> {
29 bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, unsigned &Value);
30};
31
32extern cl::opt<unsigned, false, VGPRThresholdParser> VGPRThresholdPercentOpt;
33
34class SIMachineFunctionInfo;
35class SIRegisterInfo;
36class GCNSubtarget;
37class GCNSchedStage;
38
49
50#ifndef NDEBUG
51raw_ostream &operator<<(raw_ostream &OS, const GCNSchedStageID &StageID);
52#endif
53
54/// This is a minimal scheduler strategy. The main difference between this
55/// and the GenericScheduler is that GCNSchedStrategy uses different
56/// heuristics to determine excess/critical pressure sets.
58protected:
59 SUnit *pickNodeBidirectional(bool &IsTopNode, bool &PickedPending);
60
61 void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy,
62 const RegPressureTracker &RPTracker,
63 SchedCandidate &Cand, bool &IsPending,
64 bool IsBottomUp);
65
66 void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop,
67 const RegPressureTracker &RPTracker,
68 const SIRegisterInfo *SRI, unsigned SGPRPressure,
69 unsigned VGPRPressure, unsigned AGPRPressure,
70 bool IsBottomUp);
71
72 /// Evaluates instructions in the pending queue using a subset of scheduling
73 /// heuristics.
74 ///
75 /// Instructions that cannot be issued due to hardware constraints are placed
76 /// in the pending queue rather than the available queue, making them normally
77 /// invisible to scheduling heuristics. However, in certain scenarios (such as
78 /// avoiding register spilling), it may be beneficial to consider scheduling
79 /// these not-yet-ready instructions.
81 SchedBoundary *Zone) const;
82
83 void printCandidateDecision(const SchedCandidate &Current,
84 const SchedCandidate &Preferred);
85
86 void getRegisterPressures(bool AtTop, const RegPressureTracker &RPTracker,
87 SUnit *SU, std::vector<unsigned> &Pressure,
88 std::vector<unsigned> &MaxPressure,
91 ScheduleDAGMI *DAG, const SIRegisterInfo *SRI);
92
93 std::vector<unsigned> Pressure;
94
95 std::vector<unsigned> MaxPressure;
96
98
100
101 // Scheduling stages for this strategy.
103
104 // Pointer to the current SchedStageID.
106
107 // GCN RP Tracker for top-down scheduling
109
110 // GCN RP Tracker for botttom-up scheduling
112
113 bool UseGCNTrackers = false;
114
115 std::optional<bool> GCNTrackersOverride;
116
117public:
118 // schedule() have seen register pressure over the critical limits and had to
119 // track register pressure for actual scheduling heuristics.
121
122 // Schedule known to have excess register pressure. Be more conservative in
123 // increasing ILP and preserving VGPRs.
124 bool KnownExcessRP = false;
125
126 // An error margin is necessary because of poor performance of the generic RP
127 // tracker and can be adjusted up for tuning heuristics to try and more
128 // aggressively reduce register pressure.
129 unsigned ErrorMargin = 3;
130
131 // Bias for SGPR limits under a high register pressure.
132 const unsigned HighRPSGPRBias = 7;
133
134 // Bias for VGPR limits under a high register pressure.
135 const unsigned HighRPVGPRBias = 7;
136
137 unsigned SGPRExcessLimit = 0;
138
139 unsigned VGPRExcessLimit = 0;
140
141 unsigned AGPRExcessLimit = 0;
142
143 unsigned SGPRCriticalLimit = 0;
144
145 unsigned VGPRCriticalLimit = 0;
146
147 // Occupancy budget for the combined VGPR/AGPR allocation on unified targets.
148 // Unlike the per-bank limit, this is not clamped to allocatable VGPRs.
150
151 unsigned AGPRCriticalLimit = 0;
152
153 unsigned SGPRLimitBias = 0;
154
155 unsigned VGPRLimitBias = 0;
156
158
160
161 SUnit *pickNode(bool &IsTopNode) override;
162
163 void schedNode(SUnit *SU, bool IsTopNode) override;
164
165 void initialize(ScheduleDAGMI *DAG) override;
166
167 unsigned getTargetOccupancy() { return TargetOccupancy; }
168
169 void setTargetOccupancy(unsigned Occ) { TargetOccupancy = Occ; }
170
172
173 // Advances stage. Returns true if there are remaining stages.
174 bool advanceStage();
175
176 bool hasNextStage() const;
177
178 bool useGCNTrackers() const {
179 return GCNTrackersOverride.value_or(UseGCNTrackers);
180 }
181
183
185};
186
187/// The goal of this scheduling strategy is to maximize kernel occupancy (i.e.
188/// maximum number of waves per simd).
190public:
192 bool IsLegacyScheduler = false);
193};
194
195/// The goal of this scheduling strategy is to maximize ILP for a single wave
196/// (i.e. latency hiding).
198protected:
199 bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
200 SchedBoundary *Zone) const override;
201
202public:
204};
205
206/// The goal of this scheduling strategy is to maximize memory clause for a
207/// single wave.
209protected:
210 bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
211 SchedBoundary *Zone) const override;
212
213public:
215};
216
218 unsigned ScheduleLength;
219 unsigned BubbleCycles;
220
221public:
222 ScheduleMetrics() = default;
223 ScheduleMetrics(unsigned L, unsigned BC)
224 : ScheduleLength(L), BubbleCycles(BC) {}
225 unsigned getLength() const { return ScheduleLength; }
226 unsigned getBubbles() const { return BubbleCycles; }
227 unsigned getMetric() const {
228 unsigned Metric = (BubbleCycles * ScaleFactor) / ScheduleLength;
229 // Metric is zero if the amount of bubbles is less than 1% which is too
230 // small. So, return 1.
231 return Metric ? Metric : 1;
232 }
233 static const unsigned ScaleFactor;
234};
235
237 dbgs() << "\n Schedule Metric (scaled by " << ScheduleMetrics::ScaleFactor
238 << " ) is: " << Sm.getMetric() << " [ " << Sm.getBubbles() << "/"
239 << Sm.getLength() << " ]\n";
240 return OS;
241}
242
243class GCNScheduleDAGMILive;
246 // The live in/out pressure as indexed by the first or last MI in the region
247 // before scheduling.
249 // The mapping of RegionIDx to key instruction
250 DenseMap<unsigned, MachineInstr *> IdxToInstruction;
251 // Whether we are calculating LiveOuts or LiveIns
252 bool IsLiveOut;
253
254public:
255 RegionPressureMap() = default;
257 : DAG(GCNDAG), IsLiveOut(LiveOut) {}
258 // Build the Instr->LiveReg and RegionIdx->Instr maps
259 void buildLiveRegMap();
260
261 // Retrieve the LiveReg for a given RegionIdx
263 assert(IdxToInstruction.contains(RegionIdx));
264 MachineInstr *Key = IdxToInstruction[RegionIdx];
265 return RegionLiveRegMap[Key];
266 }
267};
268
269/// A region's boundaries i.e. a pair of instruction bundle iterators. The lower
270/// boundary is inclusive, the upper boundary is exclusive.
272 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>;
273
275 friend class GCNSchedStage;
280 friend class PreRARematStage;
283 friend class RegionPressureMap;
284
285 const GCNSubtarget &ST;
286
288
289 // Occupancy target at the beginning of function scheduling cycle.
290 unsigned StartingOccupancy;
291
292 // Minimal real occupancy recorder for the function.
293 unsigned MinOccupancy;
294
295 // Vector of regions recorder for later rescheduling
297
298 // Record regions with high register pressure.
299 BitVector RegionsWithHighRP;
300
301 // Record regions with excess register pressure over the physical register
302 // limit. Register pressure in these regions usually will result in spilling.
303 BitVector RegionsWithExcessRP;
304
305 // Regions that have IGLP instructions (SCHED_GROUP_BARRIER or IGLP_OPT).
306 BitVector RegionsWithIGLPInstrs;
307
308 // Region live-in cache.
310
311 // Region pressure cache.
313
314 // Temporary basic block live-in cache.
316
317 // The map of the initial first region instruction to region live in registers
319
320 // Calculate the map of the initial first region instruction to region live in
321 // registers
323
324 // Calculate the map of the initial last region instruction to region live out
325 // registers
327 getRegionLiveOutMap() const;
328
329 // The live out registers per region. These are internally stored as a map of
330 // the initial last region instruction to region live out registers, but can
331 // be retreived with the regionIdx by calls to getLiveRegsForRegionIdx.
332 RegionPressureMap RegionLiveOuts;
333
334 // Return current region pressure.
335 GCNRegPressure getRealRegPressure(unsigned RegionIdx) const;
336
337 // Compute and cache live-ins and pressure for all regions in block.
338 void computeBlockPressure(unsigned RegionIdx, const MachineBasicBlock *MBB);
339
340 /// Makes the scheduler try to achieve an occupancy of \p TargetOccupancy.
341 void setTargetOccupancy(unsigned TargetOccupancy);
342
343 void runSchedStages();
344
345 std::unique_ptr<GCNSchedStage> createSchedStage(GCNSchedStageID SchedStageID);
346
347public:
349 std::unique_ptr<MachineSchedStrategy> S);
350
351 void schedule() override;
352
353 void finalizeSchedule() override;
354};
355
356// GCNSchedStrategy applies multiple scheduling stages to a function.
358protected:
360
362
364
366
368
370
371 // The current block being scheduled.
373
374 // Current region index.
375 unsigned RegionIdx = 0;
376
377 // Record the original order of instructions before scheduling.
378 std::vector<MachineInstr *> Unsched;
379
380 // RP before scheduling the current region.
382
383 // RP after scheduling the current region.
385
386 std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations;
387
389
390public:
391 // Initialize state for a scheduling stage. Returns false if the current stage
392 // should be skipped.
393 virtual bool initGCNSchedStage();
394
395 // Finalize state after finishing a scheduling pass on the function.
396 virtual void finalizeGCNSchedStage();
397
398 // Setup for scheduling a region. Returns false if the current region should
399 // be skipped.
400 virtual bool initGCNRegion();
401
402 // Finalize state after scheduling a region.
403 virtual void finalizeGCNRegion();
404
405 // Track whether a new region is also a new MBB.
406 void setupNewBlock();
407
408 // Check result of scheduling.
409 void checkScheduling();
410
411 // computes the given schedule virtual execution time in clocks
412 ScheduleMetrics getScheduleMetrics(const std::vector<SUnit> &InputSchedule);
414 unsigned computeSUnitReadyCycle(const SUnit &SU, unsigned CurrCycle,
415 DenseMap<unsigned, unsigned> &ReadyCycles,
416 const TargetSchedModel &SM);
417
418 // Returns true if scheduling should be reverted.
419 virtual bool shouldRevertScheduling(unsigned WavesAfter);
420
421 // Returns true if current region has known excess pressure.
422 bool isRegionWithExcessRP() const {
423 return DAG.RegionsWithExcessRP[RegionIdx];
424 }
425
426 // The region number this stage is currently working on
427 unsigned getRegionIdx() { return RegionIdx; }
428
429 // Returns true if the new schedule may result in more spilling.
430 bool mayCauseSpilling(unsigned WavesAfter);
431
432 /// Sets the schedule of region \p RegionIdx to \p MIOrder. The MIs in \p
433 /// MIOrder must be exactly the same as the ones currently existing inside the
434 /// region, only in a different order that honors def-use chains.
435 void modifyRegionSchedule(unsigned RegionIdx,
437
439
440 virtual ~GCNSchedStage() = default;
441};
442
450
452private:
453 // Record regions with excess archvgpr register pressure over the physical
454 // register limit. Register pressure in these regions usually will result in
455 // spilling.
456 BitVector RegionsWithExcessArchVGPR;
457
458 const SIInstrInfo *TII;
459 const SIRegisterInfo *SRI;
460
461 /// Per-candidate cache of the src2 "needs VGPR" decision, computed once
462 /// and reused on-demand.
463 DenseMap<const MachineInstr *, bool> Src2NeedsVGPRCache;
464
465 /// Do a speculative rewrite and collect copy locations. The speculative
466 /// rewrite allows us to calculate the RP of the code after the rewrite, and
467 /// the copy locations allow us to calculate the total cost of copies required
468 /// for the rewrite. Stores the rewritten instructions in \p RewriteCands ,
469 /// the copy locations for uses (of the MFMA result) in \p CopyForUse and the
470 /// copy locations for defs (of the MFMA operands) in \p CopyForDef
471 bool
472 initHeuristics(std::vector<std::pair<MachineInstr *, unsigned>> &RewriteCands,
473 DenseMap<MachineBasicBlock *, std::set<Register>> &CopyForUse,
475
476 /// Calculate the rewrite cost and undo the state change (e.g. rewriting) done
477 /// in initHeuristics. Uses \p CopyForUse and \p CopyForDef to calculate copy
478 /// costs, and \p RewriteCands to undo rewriting.
479 int64_t getRewriteCost(
480 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands,
481 const DenseMap<MachineBasicBlock *, std::set<Register>> &CopyForUse,
482 const SmallPtrSetImpl<MachineInstr *> &CopyForDef);
483
484 /// Do the final rewrite on \p RewriteCands and insert any needed copies.
485 bool rewrite(ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands);
486
487 /// \returns true if this MI is a rewrite candidate.
488 bool isRewriteCandidate(MachineInstr *MI) const;
489
490 /// Resets all candidates in \p RewriteCands back to VGPR form.
491 void resetRewriteCandsToVGPR(
492 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands);
493
494 /// Finds all the reaching defs of \p UseMO and stores the SlotIndexes into \p
495 /// DefIdxs
496 void findReachingDefs(MachineOperand &UseMO, LiveIntervals *LIS,
498
499 /// Finds all the reaching uses of \p DefMI and stores the use operands in \p
500 /// ReachingUses
501 void findReachingUses(const MachineInstr *DefMI, LiveIntervals *LIS,
503
504 /// Returns true if the src2 register with reaching defs \p Src2ReachingDefs
505 /// has a use other than a group MFMA (in \p RewriteSet) or a copy, which
506 /// would keep it in VGPR form rather than let it be reclassified to AGPR.
507 bool hasUseRequiringVGPR(ArrayRef<SlotIndex> Src2ReachingDefs,
508 const SmallPtrSetImpl<MachineInstr *> &RewriteSet);
509
510public:
511 bool initGCNSchedStage() override;
512
515};
516
518private:
519 // Save the initial occupancy before starting this stage.
520 unsigned InitialOccupancy;
521 // Save the temporary target occupancy before starting this stage.
522 unsigned TempTargetOccupancy;
523 // Track whether any region was scheduled by this stage.
524 bool IsAnyRegionScheduled;
525
526public:
527 bool initGCNSchedStage() override;
528
529 void finalizeGCNSchedStage() override;
530
531 bool initGCNRegion() override;
532
533 bool shouldRevertScheduling(unsigned WavesAfter) override;
534
537};
538
539// Retry function scheduling if we found resulting occupancy and it is
540// lower than used for other scheduling passes. This will give more freedom
541// to schedule low register pressure blocks.
543public:
544 bool initGCNSchedStage() override;
545
546 bool initGCNRegion() override;
547
548 bool shouldRevertScheduling(unsigned WavesAfter) override;
549
552};
553
554/// Attempts to reduce function spilling or, if there is no spilling, to
555/// increase function occupancy by one with respect to register usage by sinking
556/// rematerializable instructions to their use. When the stage estimates that
557/// reducing spilling or increasing occupancy is possible, it tries to
558/// rematerialize as few registers as possible to reduce potential negative
559/// effects on function latency.
560///
561/// The stage only supports rematerializing registers that meet all of the
562/// following constraints.
563/// 1. The register is virtual and has a single defining instruction.
564/// 2. The single defining instruction is either deemed rematerializable by the
565/// target-independent logic, or if not, has no non-constant and
566/// non-ignorable physical register use.
567/// 3 The register has no virtual register use whose live range would be
568/// extended by the rematerialization.
569/// 4. The register has at least one user outside its defining region. If
570/// rematerialized, one copy is made per using region and the original
571/// register stays if the defining region has users.
572/// 5. The register is not used by or using another register that is going to be
573/// rematerialized.
575private:
576 using RegisterIdx = Rematerializer::RegisterIdx;
577
578 /// A scored rematerialization candidate. Higher scores indicate more
579 /// beneficial rematerializations. A null score indicate the rematerialization
580 /// is not helpful to reduce RP in target regions.
581 struct ScoredRemat {
582 /// The register index handle in the rematerializer.
583 RegisterIdx RegIdx;
584 /// Regions in which the register is live-in/live-out/live anywhere.
585 BitVector LiveIn, LiveOut, Live;
586 /// Subset of \ref Live regions in which the rematerialization is not
587 /// guaranteed to reduce RP (i.e., regions in which the register is not
588 /// live-through and unused).
589 BitVector UnpredictableRPSave;
590 /// Expected register pressure decrease induced by rematerializing this
591 /// candidate.
592 GCNRegPressure RPSave;
593
594 ScoredRemat(RegisterIdx RegIdx, unsigned NumRegions)
595 : RegIdx(RegIdx), LiveIn(NumRegions), LiveOut(NumRegions),
596 Live(NumRegions), UnpredictableRPSave(NumRegions) {}
597
598 /// Execution frequency information required by scoring heuristics.
599 /// Frequencies are scaled down if they are high to avoid overflow/underflow
600 /// when combining them.
601 struct FreqInfo {
602 /// Per-region execution frequencies. 0 when unknown.
604 /// Minimum and maximum observed frequencies.
606
608
609 private:
610 static const uint64_t ScaleFactor = 1024;
611 };
612
613 /// Initializes the candidate with state-independent characteristics.
614 /// This doesn't update the actual score (call \ref update for this).
615 /// Note: LiveIn/LiveOut must be pre-populated before calling this.
616 void init(const FreqInfo &Freq, const Rematerializer &Remater,
618
619 /// Rematerializes the candidate using the \p Remater.
620 void rematerialize(Rematerializer &Remater) const;
621
622 /// Determines whether this rematerialization may be beneficial in at least
623 /// one target region.
624 bool maybeBeneficial(const BitVector &TargetRegions,
625 ArrayRef<GCNRPTarget> RPTargets) const;
626
627 /// Updates the rematerialization's score w.r.t. the current \p RPTargets.
628 /// \p RegionFreq indicates the frequency of each region.
629 void update(const BitVector &TargetRegions, ArrayRef<GCNRPTarget> RPTargets,
630 const FreqInfo &Freq, bool ReduceSpill);
631
632 /// Returns whether the current score is null, indicating the
633 /// rematerialization is useless.
634 bool hasNullScore() const { return !RegionImpact; }
635
636 /// Compare score components of non-null scores pair-wise. Scores shouldn't
637 /// be null (as defined by \ref hasNullScore).
638 bool operator<(const ScoredRemat &O) const {
639 assert(!hasNullScore() && "this has null score");
640 assert(!O.hasNullScore() && "other has null score");
641 if (MaxFreq != O.MaxFreq)
642 return MaxFreq < O.MaxFreq;
643 if (FreqDiff != O.FreqDiff)
644 return FreqDiff < O.FreqDiff;
645 if (RegionImpact != O.RegionImpact)
646 return RegionImpact < O.RegionImpact;
647 // Break ties using register index handles. If the two registers are
648 // connected in some dependency DAG of rematerializable registers, this
649 // will tend to give a higher score to the register further from the
650 // dependency DAG's root. If the two registers are disconnected, this will
651 // give a higher score to the register with lower virtual register index.
652 // In general, within a region, this should prefer registers defined
653 // earlier that have longer live ranges in their defining region (since
654 // the registers we consider are always live-out in their defining
655 // region).
656 return RegIdx > O.RegIdx;
657 }
658
659#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
660 Printable print() const;
661#endif
662
663 private:
664 // The three members below are the scoring components, top to bottom from
665 // most important to least important when comparing candidates.
666
667 /// Frequency of impacted target region with highest known frequency. This
668 /// only matters when the stage is trying to reduce spilling, so it is
669 /// always 0 when it is not.
670 uint64_t MaxFreq;
671 /// Frequency difference between defining and using regions. Negative values
672 /// indicate we are rematerializing to higher frequency regions; positive
673 /// values indicate the contrary.
674 int64_t FreqDiff;
675 /// Expected number of target regions impacted by the rematerialization,
676 /// scaled by the size of the register being rematerialized.
677 unsigned RegionImpact;
678 };
679
680 /// Register pressure targets for all regions.
681 SmallVector<GCNRPTarget> RPTargets;
682 /// Regions which are above the stage's RP target.
683 BitVector TargetRegions;
684 /// The target occupancy the set is trying to achieve. Empty when the
685 /// objective is spilling reduction.
686 std::optional<unsigned> TargetOcc;
687 /// Achieved occupancy *only* through rematerializations (pre-rescheduling).
688 unsigned AchievedOcc;
689 /// After successful stage initialization, indicates which regions should be
690 /// rescheduled.
691 BitVector RescheduleRegions;
692
693 /// Underlying utilities to identify and perform rematerializations.
694 Rematerializer Remater;
695
696 struct RollbackSupport {
698 /// The register index handle in the rematerializer.
699 RegisterIdx RegIdx;
700 /// Regions in which the original register was live-in or live-out.
702
706 };
707
708 /// Rollback listener.
709 Rollbacker Listener;
710 /// Registers removed from live-maps along with bitvectors indicationg the
711 /// regions in which they were live-ins and live-outs.
712 SmallVector<LiveMapUpdate> LiveMapUpdates;
713
714 /// Attaches the rollback listener to the rematerializer.
715 RollbackSupport(Rematerializer &Remater) { Remater.addListener(&Listener); }
716 };
717
718 /// Rollback support. Maintained through a unique pointer because it is
719 /// optional and needs to persist between stage initialization and
720 /// finalization.
721 std::unique_ptr<RollbackSupport> Rollback;
722
723 /// State of a region pre-re-scheduling but post-rematerializations that we
724 /// must keep to be able to revert re-scheduling effects.
725 struct RegionSchedRevert {
726 /// Region number;
727 unsigned RegionIdx;
728 /// Original instruction order (both debug and non-debug MIs).
729 std::vector<MachineInstr *> OrigMIOrder;
730 /// Maximum pressure recorded in the region.
731 GCNRegPressure MaxPressure;
732
733 RegionSchedRevert(unsigned RegionIdx, ArrayRef<MachineInstr *> OrigMIOrder,
734 const GCNRegPressure &MaxPressure)
735 : RegionIdx(RegionIdx), OrigMIOrder(OrigMIOrder),
736 MaxPressure(MaxPressure) {}
737 };
738 /// After re-scheduling, contains pre-re-scheduling data for all re-scheduled
739 /// regions.
740 SmallVector<RegionSchedRevert> RegionReverts;
741 /// Whether we should revert all re-scheduled regions.
742 bool RevertAllRegions = false;
743
744 /// Returns the occupancy the stage is trying to achieve.
745 unsigned getStageTargetOccupancy() const;
746
747 /// Determines the stage's objective (increasing occupancy or reducing
748 /// spilling, set in \ref TargetOcc). Defines \ref RPTargets in all regions to
749 /// achieve that objective and mark those that don't achieve it in \ref
750 /// TargetRegions. Returns whether there is any target region.
751 bool setObjective();
752
753 /// Determines whether users of rematerialization candidate \p CandIdx are
754 /// compatible with the stage's rematerialization constraints/limitations.
755 /// Registers in \p MarkedRegs have already been deemed rematerializable by
756 /// the stage.
757 bool candidateHasValidUsers(RegisterIdx CandIdx,
758 const SmallSet<Register, 4> &MarkedRegs) const;
759
760 /// In all regions set in \p Regions, saves pressure \p RPSave and clear it as
761 /// a target if its RP target has been reached.
762 void updateRPTargets(const BitVector &Regions, const GCNRegPressure &RPSave);
763
764 /// Fully recomputes RP from the DAG in \p Regions. Among those regions, sets
765 /// again all \ref TargetRegions that were optimistically marked as satisfied
766 /// but are actually not, and returns whether there were any such regions.
767 bool updateAndVerifyRPTargets(const BitVector &Regions);
768
769 /// Removes register \p Reg from the live-ins of regions set in \p LiveIn and
770 /// the live-outs of regions set in \p LiveOut.
771 void removeFromLiveMaps(Register Reg, const BitVector &LiveIn,
772 const BitVector &LiveOut);
773
774 /// Adds register \p Reg with mask \p Mask to the live-ins of regions set in
775 /// \p LiveIn and the live-outs of regions set in \p LiveOut.
776 void addToLiveMaps(Register Reg, LaneBitmask Mask, const BitVector &LiveIn,
777 const BitVector &LiveOut);
778
779 /// If remat alone did not increase occupancy to the target one, rollbacks all
780 /// rematerializations and resets live-ins/RP in all regions impacted by the
781 /// stage to their pre-stage values.
782 void finalizeGCNSchedStage() override;
783
784public:
785 bool initGCNSchedStage() override;
786
787 bool initGCNRegion() override;
788
789 void finalizeGCNRegion() override;
790
791 bool shouldRevertScheduling(unsigned WavesAfter) override;
792
795 TargetRegions(static_cast<unsigned>(DAG.Regions.size())),
796 RescheduleRegions(static_cast<unsigned>(DAG.Regions.size())),
797 Remater(MF, DAG.Regions, *DAG.LIS) {
798 const size_t NumRegions = DAG.Regions.size();
799 RPTargets.reserve(NumRegions);
800 }
801};
802
810
819
820// Live interval register pressure stage:
821// estimates register pressure accounting for live interval interference,
822// optionally reschedules the region with tigher register bounds.
824public:
825 bool initGCNSchedStage() override;
826 bool initGCNRegion() override;
827 void finalizeGCNRegion() override;
828
831
832private:
833 unsigned SavedVGPRThresholdPercent = 0;
834 unsigned SavedVGPRExcessLimit = 0;
835 unsigned SavedVGPRCriticalLimit = 0;
836 unsigned SavedUnifiedVGPRCriticalLimit = 0;
837};
838
840private:
841 std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations;
842
843 bool HasIGLPInstrs = false;
844
845public:
846 void schedule() override;
847
848 void finalizeSchedule() override;
849
851 std::unique_ptr<MachineSchedStrategy> S,
852 bool RemoveKillFlags);
853};
854
855} // End namespace llvm
856
857#endif // LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
MachineBasicBlock & MBB
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file defines the DenseMap class.
This file defines the GCNRegPressure class, which tracks registry pressure by bookkeeping number of S...
IRTranslator LLVM IR MI
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
MIR-level target-independent rematerialization helpers.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool shouldRevertScheduling(unsigned WavesAfter) override
ClusteredLowOccStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
Common behavior for downward RP trackers. Unconstructible directly.
Downward RP tracker that relies on the user to provide the next instruction down the instruction stre...
GCNMaxILPSchedStrategy(const MachineSchedContext *C)
bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const override
Apply a set of heuristics to a new candidate.
bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const override
GCNMaxMemoryClauseSchedStrategy tries best to clause memory instructions as much as possible.
GCNMaxMemoryClauseSchedStrategy(const MachineSchedContext *C)
GCNMaxOccupancySchedStrategy(const MachineSchedContext *C, bool IsLegacyScheduler=false)
void finalizeSchedule() override
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
void schedule() override
Orders nodes according to selected style.
GCNPostScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S, bool RemoveKillFlags)
DenseMap< unsigned, LaneBitmask > LiveRegSet
GCNSchedStrategy & S
GCNRegPressure PressureBefore
bool isRegionWithExcessRP() const
void modifyRegionSchedule(unsigned RegionIdx, ArrayRef< MachineInstr * > MIOrder)
Sets the schedule of region RegionIdx to MIOrder.
bool mayCauseSpilling(unsigned WavesAfter)
ScheduleMetrics getScheduleMetrics(const std::vector< SUnit > &InputSchedule)
GCNScheduleDAGMILive & DAG
const GCNSchedStageID StageID
std::vector< MachineInstr * > Unsched
GCNRegPressure PressureAfter
MachineFunction & MF
virtual void finalizeGCNRegion()
SIMachineFunctionInfo & MFI
unsigned computeSUnitReadyCycle(const SUnit &SU, unsigned CurrCycle, DenseMap< unsigned, unsigned > &ReadyCycles, const TargetSchedModel &SM)
virtual ~GCNSchedStage()=default
virtual void finalizeGCNSchedStage()
virtual bool initGCNSchedStage()
virtual bool shouldRevertScheduling(unsigned WavesAfter)
std::vector< std::unique_ptr< ScheduleDAGMutation > > SavedMutations
GCNSchedStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
MachineBasicBlock * CurrentMBB
const GCNSubtarget & ST
This is a minimal scheduler strategy.
const unsigned HighRPSGPRBias
GCNSchedStrategy(const MachineSchedContext *C)
SmallVector< GCNSchedStageID, 4 > SchedStages
std::vector< unsigned > MaxPressure
SUnit * pickNodeBidirectional(bool &IsTopNode, bool &PickedPending)
GCNSchedStageID getCurrentStage()
bool tryPendingCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const
Evaluates instructions in the pending queue using a subset of scheduling heuristics.
SmallVectorImpl< GCNSchedStageID >::iterator CurrentStage
void schedNode(SUnit *SU, bool IsTopNode) override
Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an instruction and updated scheduled/rem...
std::optional< bool > GCNTrackersOverride
void getRegisterPressures(bool AtTop, const RegPressureTracker &RPTracker, SUnit *SU, std::vector< unsigned > &Pressure, std::vector< unsigned > &MaxPressure, const GCNDownwardRPTrackerBase &DownwardTracker, const GCNUpwardRPTracker &UpwardTracker, ScheduleDAGMI *DAG, const SIRegisterInfo *SRI)
std::vector< unsigned > Pressure
void initialize(ScheduleDAGMI *DAG) override
Initialize the strategy after building the DAG for a new region.
GCNUpwardRPTracker UpwardTracker
void printCandidateDecision(const SchedCandidate &Current, const SchedCandidate &Preferred)
const unsigned HighRPVGPRBias
void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, const RegPressureTracker &RPTracker, SchedCandidate &Cand, bool &IsPending, bool IsBottomUp)
GCNManualDownwardRPTracker DownwardTracker
GCNUpwardRPTracker & getUpwardTracker()
void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, const RegPressureTracker &RPTracker, const SIRegisterInfo *SRI, unsigned SGPRPressure, unsigned VGPRPressure, unsigned AGPRPressure, bool IsBottomUp)
void setTargetOccupancy(unsigned Occ)
GCNDownwardRPTrackerBase & getDownwardTracker()
SUnit * pickNode(bool &IsTopNode) override
Pick the next node to schedule, or return NULL.
void finalizeSchedule() override
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
void schedule() override
Orders nodes according to selected style.
GCNScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S)
ScheduleDAGMILive * DAG
GenericScheduler(const MachineSchedContext *C)
bool shouldRevertScheduling(unsigned WavesAfter) override
ILPInitialScheduleStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
LiveIntervalRPStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
bool shouldRevertScheduling(unsigned WavesAfter) override
MemoryClauseInitialScheduleStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
bool shouldRevertScheduling(unsigned WavesAfter) override
OccInitialScheduleStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
PreRARematStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
bool shouldRevertScheduling(unsigned WavesAfter) override
void finalizeGCNRegion() override
bool initGCNSchedStage() override
Simple wrapper around std::function<void(raw_ostream&)>.
Definition Printable.h:38
Track the current register pressure at some position in the instruction stream, and remember the high...
GCNRPTracker::LiveRegSet & getLiveRegsForRegionIdx(unsigned RegionIdx)
RegionPressureMap(GCNScheduleDAGMILive *GCNDAG, bool LiveOut)
MIR-level target-independent rematerializer.
unsigned RegisterIdx
Index type for rematerializable registers.
RewriteMFMAFormStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
Rematerializer listener with the ability to re-create deleted registers and rollback rematerializatio...
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.
Each Scheduling boundary is associated with ready queues.
bool RemoveKillFlags
True if the DAG builder should remove kill flags (in preparation for rescheduling).
ScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S)
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S, bool RemoveKillFlags)
unsigned getBubbles() const
ScheduleMetrics(unsigned L, unsigned BC)
unsigned getLength() const
static const unsigned ScaleFactor
unsigned getMetric() const
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
typename SuperClass::iterator iterator
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Provide an instruction scheduling machine model to CodeGen passes.
UnclusteredHighRPStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
bool shouldRevertScheduling(unsigned WavesAfter) override
LLVM Value Representation.
Definition Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This namespace contains all of the command line option processing machinery.
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:360
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
std::pair< MachineBasicBlock::iterator, MachineBasicBlock::iterator > RegionBoundaries
A region's boundaries i.e.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
cl::opt< unsigned, false, VGPRThresholdParser > VGPRThresholdPercentOpt
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
Policy for scheduling the next instruction in the candidate's zone.
Store the state used by GenericScheduler heuristics, required for the lifetime of one invocation of p...
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
BitVector LiveIn
Regions in which the original register was live-in or live-out.
LiveMapUpdate(RegisterIdx RegIdx, const BitVector &LiveIn, const BitVector &LiveOut)
RegisterIdx RegIdx
The register index handle in the rematerializer.
Execution frequency information required by scoring heuristics.
SmallVector< uint64_t > Regions
Per-region execution frequencies. 0 when unknown.
uint64_t MinFreq
Minimum and maximum observed frequencies.
FreqInfo(MachineFunction &MF, const GCNScheduleDAGMILive &DAG)
bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, unsigned &Value)
VGPRThresholdParser(cl::Option &O)