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" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric namespace llvm { 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric class SIMachineFunctionInfo; 220b57cec5SDimitry Andric class SIRegisterInfo; 230b57cec5SDimitry Andric class GCNSubtarget; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric /// This is a minimal scheduler strategy. The main difference between this 260b57cec5SDimitry Andric /// and the GenericScheduler is that GCNSchedStrategy uses different 270b57cec5SDimitry Andric /// heuristics to determine excess/critical pressure sets. Its goal is to 280b57cec5SDimitry Andric /// maximize kernel occupancy (i.e. maximum number of waves per simd). 290b57cec5SDimitry Andric class GCNMaxOccupancySchedStrategy final : public GenericScheduler { 300b57cec5SDimitry Andric friend class GCNScheduleDAGMILive; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric SUnit *pickNodeBidirectional(bool &IsTopNode); 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, 350b57cec5SDimitry Andric const RegPressureTracker &RPTracker, 360b57cec5SDimitry Andric SchedCandidate &Cand); 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric void initCandidate(SchedCandidate &Cand, SUnit *SU, 390b57cec5SDimitry Andric bool AtTop, const RegPressureTracker &RPTracker, 400b57cec5SDimitry Andric const SIRegisterInfo *SRI, 410b57cec5SDimitry Andric unsigned SGPRPressure, unsigned VGPRPressure); 420b57cec5SDimitry Andric 438bcb0991SDimitry Andric std::vector<unsigned> Pressure; 448bcb0991SDimitry Andric std::vector<unsigned> MaxPressure; 458bcb0991SDimitry Andric 460b57cec5SDimitry Andric unsigned SGPRExcessLimit; 470b57cec5SDimitry Andric unsigned VGPRExcessLimit; 480b57cec5SDimitry Andric unsigned SGPRCriticalLimit; 490b57cec5SDimitry Andric unsigned VGPRCriticalLimit; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric unsigned TargetOccupancy; 520b57cec5SDimitry Andric 53*fe6060f1SDimitry Andric // schedule() have seen a clustered memory operation. Set it to false 54*fe6060f1SDimitry Andric // before a region scheduling to know if the region had such clusters. 55*fe6060f1SDimitry Andric bool HasClusteredNodes; 56*fe6060f1SDimitry Andric 57*fe6060f1SDimitry Andric // schedule() have seen a an excess register pressure and had to track 58*fe6060f1SDimitry Andric // register pressure for actual scheduling heuristics. 59*fe6060f1SDimitry Andric bool HasExcessPressure; 60*fe6060f1SDimitry Andric 610b57cec5SDimitry Andric MachineFunction *MF; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric public: 640b57cec5SDimitry Andric GCNMaxOccupancySchedStrategy(const MachineSchedContext *C); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric SUnit *pickNode(bool &IsTopNode) override; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric void initialize(ScheduleDAGMI *DAG) override; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric void setTargetOccupancy(unsigned Occ) { TargetOccupancy = Occ; } 710b57cec5SDimitry Andric }; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric class GCNScheduleDAGMILive final : public ScheduleDAGMILive { 740b57cec5SDimitry Andric 755ffd83dbSDimitry Andric enum : unsigned { 765ffd83dbSDimitry Andric Collect, 775ffd83dbSDimitry Andric InitialSchedule, 785ffd83dbSDimitry Andric UnclusteredReschedule, 795ffd83dbSDimitry Andric ClusteredLowOccupancyReschedule, 805ffd83dbSDimitry Andric LastStage = ClusteredLowOccupancyReschedule 815ffd83dbSDimitry Andric }; 825ffd83dbSDimitry Andric 830b57cec5SDimitry Andric const GCNSubtarget &ST; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric SIMachineFunctionInfo &MFI; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // Occupancy target at the beginning of function scheduling cycle. 880b57cec5SDimitry Andric unsigned StartingOccupancy; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric // Minimal real occupancy recorder for the function. 910b57cec5SDimitry Andric unsigned MinOccupancy; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // Scheduling stage number. 940b57cec5SDimitry Andric unsigned Stage; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric // Current region index. 970b57cec5SDimitry Andric size_t RegionIdx; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric // Vector of regions recorder for later rescheduling 1000b57cec5SDimitry Andric SmallVector<std::pair<MachineBasicBlock::iterator, 1010b57cec5SDimitry Andric MachineBasicBlock::iterator>, 32> Regions; 1020b57cec5SDimitry Andric 1035ffd83dbSDimitry Andric // Records if a region is not yet scheduled, or schedule has been reverted, 1045ffd83dbSDimitry Andric // or we generally desire to reschedule it. 1055ffd83dbSDimitry Andric BitVector RescheduleRegions; 1065ffd83dbSDimitry Andric 107*fe6060f1SDimitry Andric // Record regions which use clustered loads/stores. 108*fe6060f1SDimitry Andric BitVector RegionsWithClusters; 109*fe6060f1SDimitry Andric 110*fe6060f1SDimitry Andric // Record regions with high register pressure. 111*fe6060f1SDimitry Andric BitVector RegionsWithHighRP; 112*fe6060f1SDimitry Andric 1130b57cec5SDimitry Andric // Region live-in cache. 1140b57cec5SDimitry Andric SmallVector<GCNRPTracker::LiveRegSet, 32> LiveIns; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // Region pressure cache. 1170b57cec5SDimitry Andric SmallVector<GCNRegPressure, 32> Pressure; 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric // Temporary basic block live-in cache. 1200b57cec5SDimitry Andric DenseMap<const MachineBasicBlock*, GCNRPTracker::LiveRegSet> MBBLiveIns; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> BBLiveInMap; 1230b57cec5SDimitry Andric DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> getBBLiveInMap() const; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric // Return current region pressure. 1260b57cec5SDimitry Andric GCNRegPressure getRealRegPressure() const; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric // Compute and cache live-ins and pressure for all regions in block. 1290b57cec5SDimitry Andric void computeBlockPressure(const MachineBasicBlock *MBB); 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric public: 1330b57cec5SDimitry Andric GCNScheduleDAGMILive(MachineSchedContext *C, 1340b57cec5SDimitry Andric std::unique_ptr<MachineSchedStrategy> S); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric void schedule() override; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric void finalizeSchedule() override; 1390b57cec5SDimitry Andric }; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric } // End namespace llvm 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric #endif // GCNSCHEDSTRATEGY_H 144