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/CodeGen/MachineScheduler.h" 18 19 namespace llvm { 20 21 class SIMachineFunctionInfo; 22 class SIRegisterInfo; 23 class GCNSubtarget; 24 25 /// This is a minimal scheduler strategy. The main difference between this 26 /// and the GenericScheduler is that GCNSchedStrategy uses different 27 /// heuristics to determine excess/critical pressure sets. Its goal is to 28 /// maximize kernel occupancy (i.e. maximum number of waves per simd). 29 class GCNMaxOccupancySchedStrategy final : public GenericScheduler { 30 friend class GCNScheduleDAGMILive; 31 32 SUnit *pickNodeBidirectional(bool &IsTopNode); 33 34 void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, 35 const RegPressureTracker &RPTracker, 36 SchedCandidate &Cand); 37 38 void initCandidate(SchedCandidate &Cand, SUnit *SU, 39 bool AtTop, const RegPressureTracker &RPTracker, 40 const SIRegisterInfo *SRI, 41 unsigned SGPRPressure, unsigned VGPRPressure); 42 43 std::vector<unsigned> Pressure; 44 std::vector<unsigned> MaxPressure; 45 46 unsigned SGPRExcessLimit; 47 unsigned VGPRExcessLimit; 48 unsigned SGPRCriticalLimit; 49 unsigned VGPRCriticalLimit; 50 51 unsigned TargetOccupancy; 52 53 MachineFunction *MF; 54 55 public: 56 GCNMaxOccupancySchedStrategy(const MachineSchedContext *C); 57 58 SUnit *pickNode(bool &IsTopNode) override; 59 60 void initialize(ScheduleDAGMI *DAG) override; 61 setTargetOccupancy(unsigned Occ)62 void setTargetOccupancy(unsigned Occ) { TargetOccupancy = Occ; } 63 }; 64 65 class GCNScheduleDAGMILive final : public ScheduleDAGMILive { 66 67 enum : unsigned { 68 Collect, 69 InitialSchedule, 70 UnclusteredReschedule, 71 ClusteredLowOccupancyReschedule, 72 LastStage = ClusteredLowOccupancyReschedule 73 }; 74 75 const GCNSubtarget &ST; 76 77 SIMachineFunctionInfo &MFI; 78 79 // Occupancy target at the beginning of function scheduling cycle. 80 unsigned StartingOccupancy; 81 82 // Minimal real occupancy recorder for the function. 83 unsigned MinOccupancy; 84 85 // Scheduling stage number. 86 unsigned Stage; 87 88 // Current region index. 89 size_t RegionIdx; 90 91 // Vector of regions recorder for later rescheduling 92 SmallVector<std::pair<MachineBasicBlock::iterator, 93 MachineBasicBlock::iterator>, 32> Regions; 94 95 // Records if a region is not yet scheduled, or schedule has been reverted, 96 // or we generally desire to reschedule it. 97 BitVector RescheduleRegions; 98 99 // Region live-in cache. 100 SmallVector<GCNRPTracker::LiveRegSet, 32> LiveIns; 101 102 // Region pressure cache. 103 SmallVector<GCNRegPressure, 32> Pressure; 104 105 // Temporary basic block live-in cache. 106 DenseMap<const MachineBasicBlock*, GCNRPTracker::LiveRegSet> MBBLiveIns; 107 108 DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> BBLiveInMap; 109 DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> getBBLiveInMap() const; 110 111 // Return current region pressure. 112 GCNRegPressure getRealRegPressure() const; 113 114 // Compute and cache live-ins and pressure for all regions in block. 115 void computeBlockPressure(const MachineBasicBlock *MBB); 116 117 118 public: 119 GCNScheduleDAGMILive(MachineSchedContext *C, 120 std::unique_ptr<MachineSchedStrategy> S); 121 122 void schedule() override; 123 124 void finalizeSchedule() override; 125 }; 126 127 } // End namespace llvm 128 129 #endif // GCNSCHEDSTRATEGY_H 130