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 unsigned AGPRCriticalLimit = 0;
148
149 unsigned SGPRLimitBias = 0;
150
151 unsigned VGPRLimitBias = 0;
152
154
156
157 SUnit *pickNode(bool &IsTopNode) override;
158
159 void schedNode(SUnit *SU, bool IsTopNode) override;
160
161 void initialize(ScheduleDAGMI *DAG) override;
162
163 unsigned getTargetOccupancy() { return TargetOccupancy; }
164
165 void setTargetOccupancy(unsigned Occ) { TargetOccupancy = Occ; }
166
168
169 // Advances stage. Returns true if there are remaining stages.
170 bool advanceStage();
171
172 bool hasNextStage() const;
173
174 bool useGCNTrackers() const {
175 return GCNTrackersOverride.value_or(UseGCNTrackers);
176 }
177
179
181
183};
184
185/// The goal of this scheduling strategy is to maximize kernel occupancy (i.e.
186/// maximum number of waves per simd).
188public:
190 bool IsLegacyScheduler = false);
191};
192
193/// The goal of this scheduling strategy is to maximize ILP for a single wave
194/// (i.e. latency hiding).
196protected:
197 bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
198 SchedBoundary *Zone) const override;
199
200public:
202};
203
204/// The goal of this scheduling strategy is to maximize memory clause for a
205/// single wave.
207protected:
208 bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
209 SchedBoundary *Zone) const override;
210
211public:
213};
214
216 unsigned ScheduleLength;
217 unsigned BubbleCycles;
218
219public:
220 ScheduleMetrics() = default;
221 ScheduleMetrics(unsigned L, unsigned BC)
222 : ScheduleLength(L), BubbleCycles(BC) {}
223 unsigned getLength() const { return ScheduleLength; }
224 unsigned getBubbles() const { return BubbleCycles; }
225 unsigned getMetric() const {
226 unsigned Metric = (BubbleCycles * ScaleFactor) / ScheduleLength;
227 // Metric is zero if the amount of bubbles is less than 1% which is too
228 // small. So, return 1.
229 return Metric ? Metric : 1;
230 }
231 static const unsigned ScaleFactor;
232};
233
235 dbgs() << "\n Schedule Metric (scaled by " << ScheduleMetrics::ScaleFactor
236 << " ) is: " << Sm.getMetric() << " [ " << Sm.getBubbles() << "/"
237 << Sm.getLength() << " ]\n";
238 return OS;
239}
240
241class GCNScheduleDAGMILive;
244 // The live in/out pressure as indexed by the first or last MI in the region
245 // before scheduling.
247 // The mapping of RegionIDx to key instruction
248 DenseMap<unsigned, MachineInstr *> IdxToInstruction;
249 // Whether we are calculating LiveOuts or LiveIns
250 bool IsLiveOut;
251
252public:
253 RegionPressureMap() = default;
255 : DAG(GCNDAG), IsLiveOut(LiveOut) {}
256 // Build the Instr->LiveReg and RegionIdx->Instr maps
257 void buildLiveRegMap();
258
259 // Retrieve the LiveReg for a given RegionIdx
261 assert(IdxToInstruction.contains(RegionIdx));
262 MachineInstr *Key = IdxToInstruction[RegionIdx];
263 return RegionLiveRegMap[Key];
264 }
265};
266
267/// A region's boundaries i.e. a pair of instruction bundle iterators. The lower
268/// boundary is inclusive, the upper boundary is exclusive.
270 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>;
271
273 friend class GCNSchedStage;
278 friend class PreRARematStage;
281 friend class RegionPressureMap;
282
283 const GCNSubtarget &ST;
284
286
287 // Occupancy target at the beginning of function scheduling cycle.
288 unsigned StartingOccupancy;
289
290 // Minimal real occupancy recorder for the function.
291 unsigned MinOccupancy;
292
293 // Vector of regions recorder for later rescheduling
295
296 // Record regions with high register pressure.
297 BitVector RegionsWithHighRP;
298
299 // Record regions with excess register pressure over the physical register
300 // limit. Register pressure in these regions usually will result in spilling.
301 BitVector RegionsWithExcessRP;
302
303 // Regions that have IGLP instructions (SCHED_GROUP_BARRIER or IGLP_OPT).
304 BitVector RegionsWithIGLPInstrs;
305
306 // Region live-in cache.
308
309 // Region pressure cache.
311
312 // Temporary basic block live-in cache.
314
315 // The map of the initial first region instruction to region live in registers
317
318 // Calculate the map of the initial first region instruction to region live in
319 // registers
321
322 // Calculate the map of the initial last region instruction to region live out
323 // registers
325 getRegionLiveOutMap() const;
326
327 // The live out registers per region. These are internally stored as a map of
328 // the initial last region instruction to region live out registers, but can
329 // be retreived with the regionIdx by calls to getLiveRegsForRegionIdx.
330 RegionPressureMap RegionLiveOuts;
331
332 // Return current region pressure.
333 GCNRegPressure getRealRegPressure(unsigned RegionIdx) const;
334
335 // Compute and cache live-ins and pressure for all regions in block.
336 void computeBlockPressure(unsigned RegionIdx, const MachineBasicBlock *MBB);
337
338 /// Makes the scheduler try to achieve an occupancy of \p TargetOccupancy.
339 void setTargetOccupancy(unsigned TargetOccupancy);
340
341 void runSchedStages();
342
343 std::unique_ptr<GCNSchedStage> createSchedStage(GCNSchedStageID SchedStageID);
344
345public:
347 std::unique_ptr<MachineSchedStrategy> S);
348
349 void schedule() override;
350
351 void finalizeSchedule() override;
352};
353
354// GCNSchedStrategy applies multiple scheduling stages to a function.
356protected:
358
360
362
364
366
368
369 // The current block being scheduled.
371
372 // Current region index.
373 unsigned RegionIdx = 0;
374
375 // Record the original order of instructions before scheduling.
376 std::vector<MachineInstr *> Unsched;
377
378 // RP before scheduling the current region.
380
381 // RP after scheduling the current region.
383
384 std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations;
385
387
388public:
389 // Initialize state for a scheduling stage. Returns false if the current stage
390 // should be skipped.
391 virtual bool initGCNSchedStage();
392
393 // Finalize state after finishing a scheduling pass on the function.
394 virtual void finalizeGCNSchedStage();
395
396 // Setup for scheduling a region. Returns false if the current region should
397 // be skipped.
398 virtual bool initGCNRegion();
399
400 // Finalize state after scheduling a region.
401 virtual void finalizeGCNRegion();
402
403 // Track whether a new region is also a new MBB.
404 void setupNewBlock();
405
406 // Check result of scheduling.
407 void checkScheduling();
408
409 // computes the given schedule virtual execution time in clocks
410 ScheduleMetrics getScheduleMetrics(const std::vector<SUnit> &InputSchedule);
412 unsigned computeSUnitReadyCycle(const SUnit &SU, unsigned CurrCycle,
413 DenseMap<unsigned, unsigned> &ReadyCycles,
414 const TargetSchedModel &SM);
415
416 // Returns true if scheduling should be reverted.
417 virtual bool shouldRevertScheduling(unsigned WavesAfter);
418
419 // Returns true if current region has known excess pressure.
420 bool isRegionWithExcessRP() const {
421 return DAG.RegionsWithExcessRP[RegionIdx];
422 }
423
424 // The region number this stage is currently working on
425 unsigned getRegionIdx() { return RegionIdx; }
426
427 // Returns true if the new schedule may result in more spilling.
428 bool mayCauseSpilling(unsigned WavesAfter);
429
430 /// Sets the schedule of region \p RegionIdx to \p MIOrder. The MIs in \p
431 /// MIOrder must be exactly the same as the ones currently existing inside the
432 /// region, only in a different order that honors def-use chains.
433 void modifyRegionSchedule(unsigned RegionIdx,
435
437
438 virtual ~GCNSchedStage() = default;
439};
440
448
450private:
451 // Record regions with excess archvgpr register pressure over the physical
452 // register limit. Register pressure in these regions usually will result in
453 // spilling.
454 BitVector RegionsWithExcessArchVGPR;
455
456 const SIInstrInfo *TII;
457 const SIRegisterInfo *SRI;
458
459 /// Per-candidate cache of the src2 "needs VGPR" decision, computed once
460 /// and reused on-demand.
461 DenseMap<const MachineInstr *, bool> Src2NeedsVGPRCache;
462
463 /// Do a speculative rewrite and collect copy locations. The speculative
464 /// rewrite allows us to calculate the RP of the code after the rewrite, and
465 /// the copy locations allow us to calculate the total cost of copies required
466 /// for the rewrite. Stores the rewritten instructions in \p RewriteCands ,
467 /// the copy locations for uses (of the MFMA result) in \p CopyForUse and the
468 /// copy locations for defs (of the MFMA operands) in \p CopyForDef
469 bool
470 initHeuristics(std::vector<std::pair<MachineInstr *, unsigned>> &RewriteCands,
471 DenseMap<MachineBasicBlock *, std::set<Register>> &CopyForUse,
473
474 /// Calculate the rewrite cost and undo the state change (e.g. rewriting) done
475 /// in initHeuristics. Uses \p CopyForUse and \p CopyForDef to calculate copy
476 /// costs, and \p RewriteCands to undo rewriting.
477 int64_t getRewriteCost(
478 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands,
479 const DenseMap<MachineBasicBlock *, std::set<Register>> &CopyForUse,
480 const SmallPtrSetImpl<MachineInstr *> &CopyForDef);
481
482 /// Do the final rewrite on \p RewriteCands and insert any needed copies.
483 bool rewrite(ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands);
484
485 /// \returns true if this MI is a rewrite candidate.
486 bool isRewriteCandidate(MachineInstr *MI) const;
487
488 /// Resets all candidates in \p RewriteCands back to VGPR form.
489 void resetRewriteCandsToVGPR(
490 ArrayRef<std::pair<MachineInstr *, unsigned>> RewriteCands);
491
492 /// Finds all the reaching defs of \p UseMO and stores the SlotIndexes into \p
493 /// DefIdxs
494 void findReachingDefs(MachineOperand &UseMO, LiveIntervals *LIS,
496
497 /// Finds all the reaching uses of \p DefMI and stores the use operands in \p
498 /// ReachingUses
499 void findReachingUses(const MachineInstr *DefMI, LiveIntervals *LIS,
501
502 /// Returns true if the src2 register with reaching defs \p Src2ReachingDefs
503 /// has a use other than a group MFMA (in \p RewriteSet) or a copy, which
504 /// would keep it in VGPR form rather than let it be reclassified to AGPR.
505 bool hasUseRequiringVGPR(ArrayRef<SlotIndex> Src2ReachingDefs,
506 const SmallPtrSetImpl<MachineInstr *> &RewriteSet);
507
508public:
509 bool initGCNSchedStage() override;
510
513};
514
516private:
517 // Save the initial occupancy before starting this stage.
518 unsigned InitialOccupancy;
519 // Save the temporary target occupancy before starting this stage.
520 unsigned TempTargetOccupancy;
521 // Track whether any region was scheduled by this stage.
522 bool IsAnyRegionScheduled;
523
524public:
525 bool initGCNSchedStage() override;
526
527 void finalizeGCNSchedStage() override;
528
529 bool initGCNRegion() override;
530
531 bool shouldRevertScheduling(unsigned WavesAfter) override;
532
535};
536
537// Retry function scheduling if we found resulting occupancy and it is
538// lower than used for other scheduling passes. This will give more freedom
539// to schedule low register pressure blocks.
541public:
542 bool initGCNSchedStage() override;
543
544 bool initGCNRegion() override;
545
546 bool shouldRevertScheduling(unsigned WavesAfter) override;
547
550};
551
552/// Attempts to reduce function spilling or, if there is no spilling, to
553/// increase function occupancy by one with respect to register usage by sinking
554/// rematerializable instructions to their use. When the stage estimates that
555/// reducing spilling or increasing occupancy is possible, it tries to
556/// rematerialize as few registers as possible to reduce potential negative
557/// effects on function latency.
558///
559/// The stage only supports rematerializing registers that meet all of the
560/// following constraints.
561/// 1. The register is virtual and has a single defining instruction.
562/// 2. The single defining instruction is either deemed rematerializable by the
563/// target-independent logic, or if not, has no non-constant and
564/// non-ignorable physical register use.
565/// 3 The register has no virtual register use whose live range would be
566/// extended by the rematerialization.
567/// 4. The register has a single non-debug user in a different region from its
568/// defining region.
569/// 5. The register is not used by or using another register that is going to be
570/// rematerialized.
572private:
573 using RegisterIdx = Rematerializer::RegisterIdx;
574
575 /// A scored rematerialization candidate. Higher scores indicate more
576 /// beneficial rematerializations. A null score indicate the rematerialization
577 /// is not helpful to reduce RP in target regions.
578 struct ScoredRemat {
579 /// The register index handle in the rematerializer.
580 RegisterIdx RegIdx;
581 /// Regions in which the register is live-in/live-out/live anywhere.
582 BitVector LiveIn, LiveOut, Live;
583 /// Subset of \ref Live regions in which the rematerialization is not
584 /// guaranteed to reduce RP (i.e., regions in which the register is not
585 /// live-through and unused).
586 BitVector UnpredictableRPSave;
587 /// Expected register pressure decrease induced by rematerializing this
588 /// candidate.
589 GCNRegPressure RPSave;
590
591 ScoredRemat(RegisterIdx RegIdx, unsigned NumRegions)
592 : RegIdx(RegIdx), LiveIn(NumRegions), LiveOut(NumRegions),
593 Live(NumRegions), UnpredictableRPSave(NumRegions) {}
594
595 /// Execution frequency information required by scoring heuristics.
596 /// Frequencies are scaled down if they are high to avoid overflow/underflow
597 /// when combining them.
598 struct FreqInfo {
599 /// Per-region execution frequencies. 0 when unknown.
601 /// Minimum and maximum observed frequencies.
603
605
606 private:
607 static const uint64_t ScaleFactor = 1024;
608 };
609
610 /// Initializes the candidate with state-independent characteristics.
611 /// This doesn't update the actual score (call \ref update for this).
612 /// Note: LiveIn/LiveOut must be pre-populated before calling this.
613 void init(const FreqInfo &Freq, const Rematerializer &Remater,
615
616 /// Rematerializes the candidate using the \p Remater.
617 void rematerialize(Rematerializer &Remater) const;
618
619 /// Determines whether this rematerialization may be beneficial in at least
620 /// one target region.
621 bool maybeBeneficial(const BitVector &TargetRegions,
622 ArrayRef<GCNRPTarget> RPTargets) const;
623
624 /// Updates the rematerialization's score w.r.t. the current \p RPTargets.
625 /// \p RegionFreq indicates the frequency of each region.
626 void update(const BitVector &TargetRegions, ArrayRef<GCNRPTarget> RPTargets,
627 const FreqInfo &Freq, bool ReduceSpill);
628
629 /// Returns whether the current score is null, indicating the
630 /// rematerialization is useless.
631 bool hasNullScore() const { return !RegionImpact; }
632
633 /// Compare score components of non-null scores pair-wise. Scores shouldn't
634 /// be null (as defined by \ref hasNullScore).
635 bool operator<(const ScoredRemat &O) const {
636 assert(!hasNullScore() && "this has null score");
637 assert(!O.hasNullScore() && "other has null score");
638 if (MaxFreq != O.MaxFreq)
639 return MaxFreq < O.MaxFreq;
640 if (FreqDiff != O.FreqDiff)
641 return FreqDiff < O.FreqDiff;
642 if (RegionImpact != O.RegionImpact)
643 return RegionImpact < O.RegionImpact;
644 // Break ties using register index handles. If the two registers are
645 // connected in some dependency DAG of rematerializable registers, this
646 // will tend to give a higher score to the register further from the
647 // dependency DAG's root. If the two registers are disconnected, this will
648 // give a higher score to the register with lower virtual register index.
649 // In general, within a region, this should prefer registers defined
650 // earlier that have longer live ranges in their defining region (since
651 // the registers we consider are always live-out in their defining
652 // region).
653 return RegIdx > O.RegIdx;
654 }
655
656#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
657 Printable print() const;
658#endif
659
660 private:
661 // The three members below are the scoring components, top to bottom from
662 // most important to least important when comparing candidates.
663
664 /// Frequency of impacted target region with highest known frequency. This
665 /// only matters when the stage is trying to reduce spilling, so it is
666 /// always 0 when it is not.
667 uint64_t MaxFreq;
668 /// Frequency difference between defining and using regions. Negative values
669 /// indicate we are rematerializing to higher frequency regions; positive
670 /// values indicate the contrary.
671 int64_t FreqDiff;
672 /// Expected number of target regions impacted by the rematerialization,
673 /// scaled by the size of the register being rematerialized.
674 unsigned RegionImpact;
675 };
676
677 /// Register pressure targets for all regions.
678 SmallVector<GCNRPTarget> RPTargets;
679 /// Regions which are above the stage's RP target.
680 BitVector TargetRegions;
681 /// The target occupancy the set is trying to achieve. Empty when the
682 /// objective is spilling reduction.
683 std::optional<unsigned> TargetOcc;
684 /// Achieved occupancy *only* through rematerializations (pre-rescheduling).
685 unsigned AchievedOcc;
686 /// After successful stage initialization, indicates which regions should be
687 /// rescheduled.
688 BitVector RescheduleRegions;
689
690 /// Underlying utilities to identify and perform rematerializations.
691 Rematerializer Remater;
692
693 struct RollbackSupport {
695 /// The register index handle in the rematerializer.
696 RegisterIdx RegIdx;
697 /// Regions in which the original register was live-in or live-out.
699
703 };
704
705 /// Rollback listener.
706 Rollbacker Listener;
707 /// Registers removed from live-maps along with bitvectors indicationg the
708 /// regions in which they were live-ins and live-outs.
709 SmallVector<LiveMapUpdate> LiveMapUpdates;
710
711 /// Attaches the rollback listener to the rematerializer.
712 RollbackSupport(Rematerializer &Remater) { Remater.addListener(&Listener); }
713 };
714
715 /// Rollback support. Maintained through a unique pointer because it is
716 /// optional and needs to persist between stage initialization and
717 /// finalization.
718 std::unique_ptr<RollbackSupport> Rollback;
719
720 /// State of a region pre-re-scheduling but post-rematerializations that we
721 /// must keep to be able to revert re-scheduling effects.
722 struct RegionSchedRevert {
723 /// Region number;
724 unsigned RegionIdx;
725 /// Original instruction order (both debug and non-debug MIs).
726 std::vector<MachineInstr *> OrigMIOrder;
727 /// Maximum pressure recorded in the region.
728 GCNRegPressure MaxPressure;
729
730 RegionSchedRevert(unsigned RegionIdx, ArrayRef<MachineInstr *> OrigMIOrder,
731 const GCNRegPressure &MaxPressure)
732 : RegionIdx(RegionIdx), OrigMIOrder(OrigMIOrder),
733 MaxPressure(MaxPressure) {}
734 };
735 /// After re-scheduling, contains pre-re-scheduling data for all re-scheduled
736 /// regions.
737 SmallVector<RegionSchedRevert> RegionReverts;
738 /// Whether we should revert all re-scheduled regions.
739 bool RevertAllRegions = false;
740
741 /// Returns the occupancy the stage is trying to achieve.
742 unsigned getStageTargetOccupancy() const;
743
744 /// Determines the stage's objective (increasing occupancy or reducing
745 /// spilling, set in \ref TargetOcc). Defines \ref RPTargets in all regions to
746 /// achieve that objective and mark those that don't achieve it in \ref
747 /// TargetRegions. Returns whether there is any target region.
748 bool setObjective();
749
750 /// In all regions set in \p Regions, saves pressure \p RPSave and clear it as
751 /// a target if its RP target has been reached.
752 void updateRPTargets(const BitVector &Regions, const GCNRegPressure &RPSave);
753
754 /// Fully recomputes RP from the DAG in \p Regions. Among those regions, sets
755 /// again all \ref TargetRegions that were optimistically marked as satisfied
756 /// but are actually not, and returns whether there were any such regions.
757 bool updateAndVerifyRPTargets(const BitVector &Regions);
758
759 /// Removes register \p Reg from the live-ins of regions set in \p LiveIn and
760 /// the live-outs of regions set in \p LiveOut.
761 void removeFromLiveMaps(Register Reg, const BitVector &LiveIn,
762 const BitVector &LiveOut);
763
764 /// Adds register \p Reg with mask \p Mask to the live-ins of regions set in
765 /// \p LiveIn and the live-outs of regions set in \p LiveOut.
766 void addToLiveMaps(Register Reg, LaneBitmask Mask, const BitVector &LiveIn,
767 const BitVector &LiveOut);
768
769 /// If remat alone did not increase occupancy to the target one, rollbacks all
770 /// rematerializations and resets live-ins/RP in all regions impacted by the
771 /// stage to their pre-stage values.
772 void finalizeGCNSchedStage() override;
773
774public:
775 bool initGCNSchedStage() override;
776
777 bool initGCNRegion() override;
778
779 void finalizeGCNRegion() override;
780
781 bool shouldRevertScheduling(unsigned WavesAfter) override;
782
784 : GCNSchedStage(StageID, DAG), TargetRegions(DAG.Regions.size()),
785 RescheduleRegions(DAG.Regions.size()),
786 Remater(MF, DAG.Regions, *DAG.LIS) {
787 const unsigned NumRegions = DAG.Regions.size();
788 RPTargets.reserve(NumRegions);
789 }
790};
791
799
808
809// Live interval register pressure stage:
810// estimates register pressure accounting for live interval interference,
811// optionally reschedules the region with tigher register bounds.
813public:
814 bool initGCNSchedStage() override;
815 bool initGCNRegion() override;
816 void finalizeGCNRegion() override;
817
820
821private:
822 unsigned SavedVGPRThresholdPercent = 0;
823 unsigned SavedVGPRExcessLimit = 0;
824 unsigned SavedVGPRCriticalLimit = 0;
825};
826
828private:
829 std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations;
830
831 bool HasIGLPInstrs = false;
832
833public:
834 void schedule() override;
835
836 void finalizeSchedule() override;
837
839 std::unique_ptr<MachineSchedStrategy> S,
840 bool RemoveKillFlags);
841};
842
843} // End namespace llvm
844
845#endif // LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned 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)
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
GCNDownwardRPTracker DownwardTracker
void getRegisterPressures(bool AtTop, const RegPressureTracker &RPTracker, SUnit *SU, std::vector< unsigned > &Pressure, std::vector< unsigned > &MaxPressure, GCNDownwardRPTracker &DownwardTracker, GCNUpwardRPTracker &UpwardTracker, ScheduleDAGMI *DAG, const SIRegisterInfo *SRI)
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
GCNDownwardRPTracker * getDownwardTracker()
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)
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)
SUnit * pickNode(bool &IsTopNode) override
Pick the next node to schedule, or return NULL.
GCNUpwardRPTracker * getUpwardTracker()
GCNSchedStageID getNextStage() const
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.
Definition MCSchedule.h:35
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)