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 // schedule() have seen a clustered memory operation. Set it to false 54 // before a region scheduling to know if the region had such clusters. 55 bool HasClusteredNodes; 56 57 // schedule() have seen a an excess register pressure and had to track 58 // register pressure for actual scheduling heuristics. 59 bool HasExcessPressure; 60 61 MachineFunction *MF; 62 63 public: 64 GCNMaxOccupancySchedStrategy(const MachineSchedContext *C); 65 66 SUnit *pickNode(bool &IsTopNode) override; 67 68 void initialize(ScheduleDAGMI *DAG) override; 69 70 void setTargetOccupancy(unsigned Occ) { TargetOccupancy = Occ; } 71 }; 72 73 class GCNScheduleDAGMILive final : public ScheduleDAGMILive { 74 75 enum : unsigned { 76 Collect, 77 InitialSchedule, 78 UnclusteredReschedule, 79 ClusteredLowOccupancyReschedule, 80 LastStage = ClusteredLowOccupancyReschedule 81 }; 82 83 const GCNSubtarget &ST; 84 85 SIMachineFunctionInfo &MFI; 86 87 // Occupancy target at the beginning of function scheduling cycle. 88 unsigned StartingOccupancy; 89 90 // Minimal real occupancy recorder for the function. 91 unsigned MinOccupancy; 92 93 // Scheduling stage number. 94 unsigned Stage; 95 96 // Current region index. 97 size_t RegionIdx; 98 99 // Vector of regions recorder for later rescheduling 100 SmallVector<std::pair<MachineBasicBlock::iterator, 101 MachineBasicBlock::iterator>, 32> Regions; 102 103 // Records if a region is not yet scheduled, or schedule has been reverted, 104 // or we generally desire to reschedule it. 105 BitVector RescheduleRegions; 106 107 // Record regions which use clustered loads/stores. 108 BitVector RegionsWithClusters; 109 110 // Record regions with high register pressure. 111 BitVector RegionsWithHighRP; 112 113 // Region live-in cache. 114 SmallVector<GCNRPTracker::LiveRegSet, 32> LiveIns; 115 116 // Region pressure cache. 117 SmallVector<GCNRegPressure, 32> Pressure; 118 119 // Temporary basic block live-in cache. 120 DenseMap<const MachineBasicBlock*, GCNRPTracker::LiveRegSet> MBBLiveIns; 121 122 DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> BBLiveInMap; 123 DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> getBBLiveInMap() const; 124 125 // Return current region pressure. 126 GCNRegPressure getRealRegPressure() const; 127 128 // Compute and cache live-ins and pressure for all regions in block. 129 void computeBlockPressure(const MachineBasicBlock *MBB); 130 131 132 public: 133 GCNScheduleDAGMILive(MachineSchedContext *C, 134 std::unique_ptr<MachineSchedStrategy> S); 135 136 void schedule() override; 137 138 void finalizeSchedule() override; 139 }; 140 141 } // End namespace llvm 142 143 #endif // GCNSCHEDSTRATEGY_H 144