10b57cec5SDimitry Andric //===-- GCNSchedStrategy.h - GCN Scheduler Strategy -*- C++ -*-------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "GCNRegPressure.h" 1781ad6265SDimitry Andric #include "llvm/ADT/MapVector.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric namespace llvm { 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric class SIMachineFunctionInfo; 230b57cec5SDimitry Andric class SIRegisterInfo; 240b57cec5SDimitry Andric class GCNSubtarget; 25bdd1243dSDimitry Andric class GCNSchedStage; 26bdd1243dSDimitry Andric 27bdd1243dSDimitry Andric enum class GCNSchedStageID : unsigned { 28bdd1243dSDimitry Andric OccInitialSchedule = 0, 29bdd1243dSDimitry Andric UnclusteredHighRPReschedule = 1, 30bdd1243dSDimitry Andric ClusteredLowOccupancyReschedule = 2, 31bdd1243dSDimitry Andric PreRARematerialize = 3, 32bdd1243dSDimitry Andric ILPInitialSchedule = 4 33bdd1243dSDimitry Andric }; 34bdd1243dSDimitry Andric 35bdd1243dSDimitry Andric #ifndef NDEBUG 36bdd1243dSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const GCNSchedStageID &StageID); 37bdd1243dSDimitry Andric #endif 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric /// This is a minimal scheduler strategy. The main difference between this 400b57cec5SDimitry Andric /// and the GenericScheduler is that GCNSchedStrategy uses different 41bdd1243dSDimitry Andric /// heuristics to determine excess/critical pressure sets. 42bdd1243dSDimitry Andric class GCNSchedStrategy : public GenericScheduler { 43bdd1243dSDimitry Andric protected: 440b57cec5SDimitry Andric SUnit *pickNodeBidirectional(bool &IsTopNode); 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, 470b57cec5SDimitry Andric const RegPressureTracker &RPTracker, 48*0fca6ea1SDimitry Andric SchedCandidate &Cand, bool IsBottomUp); 490b57cec5SDimitry Andric 50*0fca6ea1SDimitry Andric void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, 51*0fca6ea1SDimitry Andric const RegPressureTracker &RPTracker, 52*0fca6ea1SDimitry Andric const SIRegisterInfo *SRI, unsigned SGPRPressure, 53*0fca6ea1SDimitry Andric unsigned VGPRPressure, bool IsBottomUp); 540b57cec5SDimitry Andric 558bcb0991SDimitry Andric std::vector<unsigned> Pressure; 56972a253aSDimitry Andric 578bcb0991SDimitry Andric std::vector<unsigned> MaxPressure; 588bcb0991SDimitry Andric 590b57cec5SDimitry Andric unsigned SGPRExcessLimit; 60972a253aSDimitry Andric 610b57cec5SDimitry Andric unsigned VGPRExcessLimit; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric unsigned TargetOccupancy; 640b57cec5SDimitry Andric 65972a253aSDimitry Andric MachineFunction *MF; 66972a253aSDimitry Andric 67bdd1243dSDimitry Andric // Scheduling stages for this strategy. 68bdd1243dSDimitry Andric SmallVector<GCNSchedStageID, 4> SchedStages; 69fe6060f1SDimitry Andric 70bdd1243dSDimitry Andric // Pointer to the current SchedStageID. 71bdd1243dSDimitry Andric SmallVectorImpl<GCNSchedStageID>::iterator CurrentStage = nullptr; 72bdd1243dSDimitry Andric 73bdd1243dSDimitry Andric public: 74bdd1243dSDimitry Andric // schedule() have seen register pressure over the critical limits and had to 75bdd1243dSDimitry Andric // track register pressure for actual scheduling heuristics. 76bdd1243dSDimitry Andric bool HasHighPressure; 77bdd1243dSDimitry Andric 78bdd1243dSDimitry Andric // Schedule known to have excess register pressure. Be more conservative in 79bdd1243dSDimitry Andric // increasing ILP and preserving VGPRs. 80bdd1243dSDimitry Andric bool KnownExcessRP = false; 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric // An error margin is necessary because of poor performance of the generic RP 83bdd1243dSDimitry Andric // tracker and can be adjusted up for tuning heuristics to try and more 84bdd1243dSDimitry Andric // aggressively reduce register pressure. 85bdd1243dSDimitry Andric unsigned ErrorMargin = 3; 86bdd1243dSDimitry Andric 87bdd1243dSDimitry Andric // Bias for SGPR limits under a high register pressure. 88bdd1243dSDimitry Andric const unsigned HighRPSGPRBias = 7; 89bdd1243dSDimitry Andric 90bdd1243dSDimitry Andric // Bias for VGPR limits under a high register pressure. 91bdd1243dSDimitry Andric const unsigned HighRPVGPRBias = 7; 92fe6060f1SDimitry Andric 93972a253aSDimitry Andric unsigned SGPRCriticalLimit; 940b57cec5SDimitry Andric 95972a253aSDimitry Andric unsigned VGPRCriticalLimit; 96972a253aSDimitry Andric 97bdd1243dSDimitry Andric unsigned SGPRLimitBias = 0; 98bdd1243dSDimitry Andric 99bdd1243dSDimitry Andric unsigned VGPRLimitBias = 0; 100bdd1243dSDimitry Andric 101bdd1243dSDimitry Andric GCNSchedStrategy(const MachineSchedContext *C); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric SUnit *pickNode(bool &IsTopNode) override; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric void initialize(ScheduleDAGMI *DAG) override; 1060b57cec5SDimitry Andric 107972a253aSDimitry Andric unsigned getTargetOccupancy() { return TargetOccupancy; } 108972a253aSDimitry Andric 1090b57cec5SDimitry Andric void setTargetOccupancy(unsigned Occ) { TargetOccupancy = Occ; } 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric GCNSchedStageID getCurrentStage(); 112bdd1243dSDimitry Andric 113bdd1243dSDimitry Andric // Advances stage. Returns true if there are remaining stages. 114bdd1243dSDimitry Andric bool advanceStage(); 115bdd1243dSDimitry Andric 116bdd1243dSDimitry Andric bool hasNextStage() const; 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric GCNSchedStageID getNextStage() const; 1190b57cec5SDimitry Andric }; 1200b57cec5SDimitry Andric 121bdd1243dSDimitry Andric /// The goal of this scheduling strategy is to maximize kernel occupancy (i.e. 122bdd1243dSDimitry Andric /// maximum number of waves per simd). 123bdd1243dSDimitry Andric class GCNMaxOccupancySchedStrategy final : public GCNSchedStrategy { 124bdd1243dSDimitry Andric public: 125bdd1243dSDimitry Andric GCNMaxOccupancySchedStrategy(const MachineSchedContext *C); 1265ffd83dbSDimitry Andric }; 1275ffd83dbSDimitry Andric 128bdd1243dSDimitry Andric /// The goal of this scheduling strategy is to maximize ILP for a single wave 129bdd1243dSDimitry Andric /// (i.e. latency hiding). 130bdd1243dSDimitry Andric class GCNMaxILPSchedStrategy final : public GCNSchedStrategy { 131bdd1243dSDimitry Andric protected: 132bdd1243dSDimitry Andric bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, 133bdd1243dSDimitry Andric SchedBoundary *Zone) const override; 134972a253aSDimitry Andric 135bdd1243dSDimitry Andric public: 136bdd1243dSDimitry Andric GCNMaxILPSchedStrategy(const MachineSchedContext *C); 137bdd1243dSDimitry Andric }; 138bdd1243dSDimitry Andric 139bdd1243dSDimitry Andric class ScheduleMetrics { 140bdd1243dSDimitry Andric unsigned ScheduleLength; 141bdd1243dSDimitry Andric unsigned BubbleCycles; 142bdd1243dSDimitry Andric 143bdd1243dSDimitry Andric public: 144bdd1243dSDimitry Andric ScheduleMetrics() {} 145bdd1243dSDimitry Andric ScheduleMetrics(unsigned L, unsigned BC) 146bdd1243dSDimitry Andric : ScheduleLength(L), BubbleCycles(BC) {} 147bdd1243dSDimitry Andric unsigned getLength() const { return ScheduleLength; } 148bdd1243dSDimitry Andric unsigned getBubbles() const { return BubbleCycles; } 149bdd1243dSDimitry Andric unsigned getMetric() const { 150bdd1243dSDimitry Andric unsigned Metric = (BubbleCycles * ScaleFactor) / ScheduleLength; 151bdd1243dSDimitry Andric // Metric is zero if the amount of bubbles is less than 1% which is too 152bdd1243dSDimitry Andric // small. So, return 1. 153bdd1243dSDimitry Andric return Metric ? Metric : 1; 154972a253aSDimitry Andric } 155bdd1243dSDimitry Andric static const unsigned ScaleFactor; 156bdd1243dSDimitry Andric }; 157972a253aSDimitry Andric 158bdd1243dSDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const ScheduleMetrics &Sm) { 159bdd1243dSDimitry Andric dbgs() << "\n Schedule Metric (scaled by " 160bdd1243dSDimitry Andric << ScheduleMetrics::ScaleFactor 161bdd1243dSDimitry Andric << " ) is: " << Sm.getMetric() << " [ " << Sm.getBubbles() << "/" 162bdd1243dSDimitry Andric << Sm.getLength() << " ]\n"; 163bdd1243dSDimitry Andric return OS; 164972a253aSDimitry Andric } 165972a253aSDimitry Andric 166972a253aSDimitry Andric class GCNScheduleDAGMILive final : public ScheduleDAGMILive { 167972a253aSDimitry Andric friend class GCNSchedStage; 168bdd1243dSDimitry Andric friend class OccInitialScheduleStage; 169bdd1243dSDimitry Andric friend class UnclusteredHighRPStage; 170972a253aSDimitry Andric friend class ClusteredLowOccStage; 171972a253aSDimitry Andric friend class PreRARematStage; 172bdd1243dSDimitry Andric friend class ILPInitialScheduleStage; 173972a253aSDimitry Andric 1740b57cec5SDimitry Andric const GCNSubtarget &ST; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric SIMachineFunctionInfo &MFI; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric // Occupancy target at the beginning of function scheduling cycle. 1790b57cec5SDimitry Andric unsigned StartingOccupancy; 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric // Minimal real occupancy recorder for the function. 1820b57cec5SDimitry Andric unsigned MinOccupancy; 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // Vector of regions recorder for later rescheduling 1850b57cec5SDimitry Andric SmallVector<std::pair<MachineBasicBlock::iterator, 1860b57cec5SDimitry Andric MachineBasicBlock::iterator>, 32> Regions; 1870b57cec5SDimitry Andric 1885ffd83dbSDimitry Andric // Records if a region is not yet scheduled, or schedule has been reverted, 1895ffd83dbSDimitry Andric // or we generally desire to reschedule it. 1905ffd83dbSDimitry Andric BitVector RescheduleRegions; 1915ffd83dbSDimitry Andric 192fe6060f1SDimitry Andric // Record regions with high register pressure. 193fe6060f1SDimitry Andric BitVector RegionsWithHighRP; 194fe6060f1SDimitry Andric 195bdd1243dSDimitry Andric // Record regions with excess register pressure over the physical register 196bdd1243dSDimitry Andric // limit. Register pressure in these regions usually will result in spilling. 197bdd1243dSDimitry Andric BitVector RegionsWithExcessRP; 198bdd1243dSDimitry Andric 19981ad6265SDimitry Andric // Regions that has the same occupancy as the latest MinOccupancy 20081ad6265SDimitry Andric BitVector RegionsWithMinOcc; 20181ad6265SDimitry Andric 202bdd1243dSDimitry Andric // Regions that have IGLP instructions (SCHED_GROUP_BARRIER or IGLP_OPT). 203bdd1243dSDimitry Andric BitVector RegionsWithIGLPInstrs; 204bdd1243dSDimitry Andric 2050b57cec5SDimitry Andric // Region live-in cache. 2060b57cec5SDimitry Andric SmallVector<GCNRPTracker::LiveRegSet, 32> LiveIns; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric // Region pressure cache. 2090b57cec5SDimitry Andric SmallVector<GCNRegPressure, 32> Pressure; 2100b57cec5SDimitry Andric 211972a253aSDimitry Andric // Temporary basic block live-in cache. 212972a253aSDimitry Andric DenseMap<const MachineBasicBlock *, GCNRPTracker::LiveRegSet> MBBLiveIns; 213972a253aSDimitry Andric 214972a253aSDimitry Andric DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> BBLiveInMap; 215972a253aSDimitry Andric 216972a253aSDimitry Andric DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> getBBLiveInMap() const; 217972a253aSDimitry Andric 218972a253aSDimitry Andric // Return current region pressure. 219972a253aSDimitry Andric GCNRegPressure getRealRegPressure(unsigned RegionIdx) const; 220972a253aSDimitry Andric 221972a253aSDimitry Andric // Compute and cache live-ins and pressure for all regions in block. 222972a253aSDimitry Andric void computeBlockPressure(unsigned RegionIdx, const MachineBasicBlock *MBB); 223972a253aSDimitry Andric 224972a253aSDimitry Andric // Update region boundaries when removing MI or inserting NewMI before MI. 225972a253aSDimitry Andric void updateRegionBoundaries( 226972a253aSDimitry Andric SmallVectorImpl<std::pair<MachineBasicBlock::iterator, 227972a253aSDimitry Andric MachineBasicBlock::iterator>> &RegionBoundaries, 228972a253aSDimitry Andric MachineBasicBlock::iterator MI, MachineInstr *NewMI, 229972a253aSDimitry Andric bool Removing = false); 230972a253aSDimitry Andric 231972a253aSDimitry Andric void runSchedStages(); 232972a253aSDimitry Andric 233bdd1243dSDimitry Andric std::unique_ptr<GCNSchedStage> createSchedStage(GCNSchedStageID SchedStageID); 234bdd1243dSDimitry Andric 235972a253aSDimitry Andric public: 236972a253aSDimitry Andric GCNScheduleDAGMILive(MachineSchedContext *C, 237972a253aSDimitry Andric std::unique_ptr<MachineSchedStrategy> S); 238972a253aSDimitry Andric 239972a253aSDimitry Andric void schedule() override; 240972a253aSDimitry Andric 241972a253aSDimitry Andric void finalizeSchedule() override; 242972a253aSDimitry Andric }; 243972a253aSDimitry Andric 244972a253aSDimitry Andric // GCNSchedStrategy applies multiple scheduling stages to a function. 245972a253aSDimitry Andric class GCNSchedStage { 246972a253aSDimitry Andric protected: 247972a253aSDimitry Andric GCNScheduleDAGMILive &DAG; 248972a253aSDimitry Andric 249bdd1243dSDimitry Andric GCNSchedStrategy &S; 250972a253aSDimitry Andric 251972a253aSDimitry Andric MachineFunction &MF; 252972a253aSDimitry Andric 253972a253aSDimitry Andric SIMachineFunctionInfo &MFI; 254972a253aSDimitry Andric 255972a253aSDimitry Andric const GCNSubtarget &ST; 256972a253aSDimitry Andric 257972a253aSDimitry Andric const GCNSchedStageID StageID; 258972a253aSDimitry Andric 259972a253aSDimitry Andric // The current block being scheduled. 260972a253aSDimitry Andric MachineBasicBlock *CurrentMBB = nullptr; 261972a253aSDimitry Andric 262972a253aSDimitry Andric // Current region index. 263972a253aSDimitry Andric unsigned RegionIdx = 0; 264972a253aSDimitry Andric 265972a253aSDimitry Andric // Record the original order of instructions before scheduling. 266972a253aSDimitry Andric std::vector<MachineInstr *> Unsched; 267972a253aSDimitry Andric 268972a253aSDimitry Andric // RP before scheduling the current region. 269972a253aSDimitry Andric GCNRegPressure PressureBefore; 270972a253aSDimitry Andric 271972a253aSDimitry Andric // RP after scheduling the current region. 272972a253aSDimitry Andric GCNRegPressure PressureAfter; 273972a253aSDimitry Andric 274bdd1243dSDimitry Andric std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations; 275bdd1243dSDimitry Andric 276972a253aSDimitry Andric GCNSchedStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG); 277972a253aSDimitry Andric 278972a253aSDimitry Andric public: 279972a253aSDimitry Andric // Initialize state for a scheduling stage. Returns false if the current stage 280972a253aSDimitry Andric // should be skipped. 281972a253aSDimitry Andric virtual bool initGCNSchedStage(); 282972a253aSDimitry Andric 283972a253aSDimitry Andric // Finalize state after finishing a scheduling pass on the function. 284972a253aSDimitry Andric virtual void finalizeGCNSchedStage(); 285972a253aSDimitry Andric 286972a253aSDimitry Andric // Setup for scheduling a region. Returns false if the current region should 287972a253aSDimitry Andric // be skipped. 288972a253aSDimitry Andric virtual bool initGCNRegion(); 289972a253aSDimitry Andric 290972a253aSDimitry Andric // Track whether a new region is also a new MBB. 291972a253aSDimitry Andric void setupNewBlock(); 292972a253aSDimitry Andric 293972a253aSDimitry Andric // Finalize state after scheudling a region. 294bdd1243dSDimitry Andric void finalizeGCNRegion(); 295972a253aSDimitry Andric 296972a253aSDimitry Andric // Check result of scheduling. 297972a253aSDimitry Andric void checkScheduling(); 298972a253aSDimitry Andric 299bdd1243dSDimitry Andric // computes the given schedule virtual execution time in clocks 300bdd1243dSDimitry Andric ScheduleMetrics getScheduleMetrics(const std::vector<SUnit> &InputSchedule); 301bdd1243dSDimitry Andric ScheduleMetrics getScheduleMetrics(const GCNScheduleDAGMILive &DAG); 302bdd1243dSDimitry Andric unsigned computeSUnitReadyCycle(const SUnit &SU, unsigned CurrCycle, 303bdd1243dSDimitry Andric DenseMap<unsigned, unsigned> &ReadyCycles, 304bdd1243dSDimitry Andric const TargetSchedModel &SM); 305bdd1243dSDimitry Andric 306972a253aSDimitry Andric // Returns true if scheduling should be reverted. 307972a253aSDimitry Andric virtual bool shouldRevertScheduling(unsigned WavesAfter); 308972a253aSDimitry Andric 309bdd1243dSDimitry Andric // Returns true if current region has known excess pressure. 310bdd1243dSDimitry Andric bool isRegionWithExcessRP() const { 311bdd1243dSDimitry Andric return DAG.RegionsWithExcessRP[RegionIdx]; 312bdd1243dSDimitry Andric } 313bdd1243dSDimitry Andric 314972a253aSDimitry Andric // Returns true if the new schedule may result in more spilling. 315972a253aSDimitry Andric bool mayCauseSpilling(unsigned WavesAfter); 316972a253aSDimitry Andric 317972a253aSDimitry Andric // Attempt to revert scheduling for this region. 318972a253aSDimitry Andric void revertScheduling(); 319972a253aSDimitry Andric 320972a253aSDimitry Andric void advanceRegion() { RegionIdx++; } 321972a253aSDimitry Andric 322972a253aSDimitry Andric virtual ~GCNSchedStage() = default; 323972a253aSDimitry Andric }; 324972a253aSDimitry Andric 325bdd1243dSDimitry Andric class OccInitialScheduleStage : public GCNSchedStage { 326972a253aSDimitry Andric public: 327972a253aSDimitry Andric bool shouldRevertScheduling(unsigned WavesAfter) override; 328972a253aSDimitry Andric 329bdd1243dSDimitry Andric OccInitialScheduleStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG) 330972a253aSDimitry Andric : GCNSchedStage(StageID, DAG) {} 331972a253aSDimitry Andric }; 332972a253aSDimitry Andric 333bdd1243dSDimitry Andric class UnclusteredHighRPStage : public GCNSchedStage { 334972a253aSDimitry Andric private: 335bdd1243dSDimitry Andric // Save the initial occupancy before starting this stage. 336bdd1243dSDimitry Andric unsigned InitialOccupancy; 337972a253aSDimitry Andric 338972a253aSDimitry Andric public: 339972a253aSDimitry Andric bool initGCNSchedStage() override; 340972a253aSDimitry Andric 341972a253aSDimitry Andric void finalizeGCNSchedStage() override; 342972a253aSDimitry Andric 343972a253aSDimitry Andric bool initGCNRegion() override; 344972a253aSDimitry Andric 345972a253aSDimitry Andric bool shouldRevertScheduling(unsigned WavesAfter) override; 346972a253aSDimitry Andric 347bdd1243dSDimitry Andric UnclusteredHighRPStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG) 348972a253aSDimitry Andric : GCNSchedStage(StageID, DAG) {} 349972a253aSDimitry Andric }; 350972a253aSDimitry Andric 351972a253aSDimitry Andric // Retry function scheduling if we found resulting occupancy and it is 352972a253aSDimitry Andric // lower than used for other scheduling passes. This will give more freedom 353972a253aSDimitry Andric // to schedule low register pressure blocks. 354972a253aSDimitry Andric class ClusteredLowOccStage : public GCNSchedStage { 355972a253aSDimitry Andric public: 356972a253aSDimitry Andric bool initGCNSchedStage() override; 357972a253aSDimitry Andric 358972a253aSDimitry Andric bool initGCNRegion() override; 359972a253aSDimitry Andric 360972a253aSDimitry Andric bool shouldRevertScheduling(unsigned WavesAfter) override; 361972a253aSDimitry Andric 362972a253aSDimitry Andric ClusteredLowOccStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG) 363972a253aSDimitry Andric : GCNSchedStage(StageID, DAG) {} 364972a253aSDimitry Andric }; 365972a253aSDimitry Andric 366972a253aSDimitry Andric class PreRARematStage : public GCNSchedStage { 367972a253aSDimitry Andric private: 36881ad6265SDimitry Andric // Each region at MinOccupancy will have their own list of trivially 36981ad6265SDimitry Andric // rematerializable instructions we can remat to reduce RP. The list maps an 37081ad6265SDimitry Andric // instruction to the position we should remat before, usually the MI using 37181ad6265SDimitry Andric // the rematerializable instruction. 37281ad6265SDimitry Andric MapVector<unsigned, MapVector<MachineInstr *, MachineInstr *>> 37381ad6265SDimitry Andric RematerializableInsts; 37481ad6265SDimitry Andric 375*0fca6ea1SDimitry Andric // Map a trivially rematerializable def to a list of regions at MinOccupancy 37681ad6265SDimitry Andric // that has the defined reg as a live-in. 37781ad6265SDimitry Andric DenseMap<MachineInstr *, SmallVector<unsigned, 4>> RematDefToLiveInRegions; 37881ad6265SDimitry Andric 37981ad6265SDimitry Andric // Collect all trivially rematerializable VGPR instructions with a single def 38081ad6265SDimitry Andric // and single use outside the defining block into RematerializableInsts. 38181ad6265SDimitry Andric void collectRematerializableInstructions(); 38281ad6265SDimitry Andric 383fcaf7f86SDimitry Andric bool isTriviallyReMaterializable(const MachineInstr &MI); 38481ad6265SDimitry Andric 38581ad6265SDimitry Andric // TODO: Should also attempt to reduce RP of SGPRs and AGPRs 38681ad6265SDimitry Andric // Attempt to reduce RP of VGPR by sinking trivially rematerializable 38781ad6265SDimitry Andric // instructions. Returns true if we were able to sink instruction(s). 38881ad6265SDimitry Andric bool sinkTriviallyRematInsts(const GCNSubtarget &ST, 38981ad6265SDimitry Andric const TargetInstrInfo *TII); 39081ad6265SDimitry Andric 3910b57cec5SDimitry Andric public: 392972a253aSDimitry Andric bool initGCNSchedStage() override; 3930b57cec5SDimitry Andric 394972a253aSDimitry Andric bool initGCNRegion() override; 3950b57cec5SDimitry Andric 396972a253aSDimitry Andric bool shouldRevertScheduling(unsigned WavesAfter) override; 397972a253aSDimitry Andric 398972a253aSDimitry Andric PreRARematStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG) 399972a253aSDimitry Andric : GCNSchedStage(StageID, DAG) {} 4000b57cec5SDimitry Andric }; 4010b57cec5SDimitry Andric 402bdd1243dSDimitry Andric class ILPInitialScheduleStage : public GCNSchedStage { 403bdd1243dSDimitry Andric public: 404bdd1243dSDimitry Andric bool shouldRevertScheduling(unsigned WavesAfter) override; 405bdd1243dSDimitry Andric 406bdd1243dSDimitry Andric ILPInitialScheduleStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG) 407bdd1243dSDimitry Andric : GCNSchedStage(StageID, DAG) {} 408bdd1243dSDimitry Andric }; 409bdd1243dSDimitry Andric 410bdd1243dSDimitry Andric class GCNPostScheduleDAGMILive final : public ScheduleDAGMI { 411bdd1243dSDimitry Andric private: 412bdd1243dSDimitry Andric std::vector<std::unique_ptr<ScheduleDAGMutation>> SavedMutations; 413bdd1243dSDimitry Andric 414bdd1243dSDimitry Andric bool HasIGLPInstrs = false; 415bdd1243dSDimitry Andric 416bdd1243dSDimitry Andric public: 417bdd1243dSDimitry Andric void schedule() override; 418bdd1243dSDimitry Andric 419bdd1243dSDimitry Andric void finalizeSchedule() override; 420bdd1243dSDimitry Andric 421bdd1243dSDimitry Andric GCNPostScheduleDAGMILive(MachineSchedContext *C, 422bdd1243dSDimitry Andric std::unique_ptr<MachineSchedStrategy> S, 423bdd1243dSDimitry Andric bool RemoveKillFlags); 424bdd1243dSDimitry Andric }; 425bdd1243dSDimitry Andric 4260b57cec5SDimitry Andric } // End namespace llvm 4270b57cec5SDimitry Andric 42804eeddc0SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H 429