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" 17*81ad6265SDimitry 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; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric /// This is a minimal scheduler strategy. The main difference between this 270b57cec5SDimitry Andric /// and the GenericScheduler is that GCNSchedStrategy uses different 280b57cec5SDimitry Andric /// heuristics to determine excess/critical pressure sets. Its goal is to 290b57cec5SDimitry Andric /// maximize kernel occupancy (i.e. maximum number of waves per simd). 300b57cec5SDimitry Andric class GCNMaxOccupancySchedStrategy final : public GenericScheduler { 310b57cec5SDimitry Andric friend class GCNScheduleDAGMILive; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric SUnit *pickNodeBidirectional(bool &IsTopNode); 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, 360b57cec5SDimitry Andric const RegPressureTracker &RPTracker, 370b57cec5SDimitry Andric SchedCandidate &Cand); 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric void initCandidate(SchedCandidate &Cand, SUnit *SU, 400b57cec5SDimitry Andric bool AtTop, const RegPressureTracker &RPTracker, 410b57cec5SDimitry Andric const SIRegisterInfo *SRI, 420b57cec5SDimitry Andric unsigned SGPRPressure, unsigned VGPRPressure); 430b57cec5SDimitry Andric 448bcb0991SDimitry Andric std::vector<unsigned> Pressure; 458bcb0991SDimitry Andric std::vector<unsigned> MaxPressure; 468bcb0991SDimitry Andric 470b57cec5SDimitry Andric unsigned SGPRExcessLimit; 480b57cec5SDimitry Andric unsigned VGPRExcessLimit; 490b57cec5SDimitry Andric unsigned SGPRCriticalLimit; 500b57cec5SDimitry Andric unsigned VGPRCriticalLimit; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric unsigned TargetOccupancy; 530b57cec5SDimitry Andric 54fe6060f1SDimitry Andric // schedule() have seen a clustered memory operation. Set it to false 55fe6060f1SDimitry Andric // before a region scheduling to know if the region had such clusters. 56fe6060f1SDimitry Andric bool HasClusteredNodes; 57fe6060f1SDimitry Andric 58349cc55cSDimitry Andric // schedule() have seen an excess register pressure and had to track 59fe6060f1SDimitry Andric // register pressure for actual scheduling heuristics. 60fe6060f1SDimitry Andric bool HasExcessPressure; 61fe6060f1SDimitry Andric 620b57cec5SDimitry Andric MachineFunction *MF; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric public: 650b57cec5SDimitry Andric GCNMaxOccupancySchedStrategy(const MachineSchedContext *C); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric SUnit *pickNode(bool &IsTopNode) override; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric void initialize(ScheduleDAGMI *DAG) override; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric void setTargetOccupancy(unsigned Occ) { TargetOccupancy = Occ; } 720b57cec5SDimitry Andric }; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric class GCNScheduleDAGMILive final : public ScheduleDAGMILive { 750b57cec5SDimitry Andric 765ffd83dbSDimitry Andric enum : unsigned { 775ffd83dbSDimitry Andric Collect, 785ffd83dbSDimitry Andric InitialSchedule, 795ffd83dbSDimitry Andric UnclusteredReschedule, 805ffd83dbSDimitry Andric ClusteredLowOccupancyReschedule, 81*81ad6265SDimitry Andric PreRARematerialize, 82*81ad6265SDimitry Andric LastStage = PreRARematerialize 835ffd83dbSDimitry Andric }; 845ffd83dbSDimitry Andric 850b57cec5SDimitry Andric const GCNSubtarget &ST; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric SIMachineFunctionInfo &MFI; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric // Occupancy target at the beginning of function scheduling cycle. 900b57cec5SDimitry Andric unsigned StartingOccupancy; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // Minimal real occupancy recorder for the function. 930b57cec5SDimitry Andric unsigned MinOccupancy; 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric // Scheduling stage number. 960b57cec5SDimitry Andric unsigned Stage; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric // Current region index. 990b57cec5SDimitry Andric size_t RegionIdx; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric // Vector of regions recorder for later rescheduling 1020b57cec5SDimitry Andric SmallVector<std::pair<MachineBasicBlock::iterator, 1030b57cec5SDimitry Andric MachineBasicBlock::iterator>, 32> Regions; 1040b57cec5SDimitry Andric 1055ffd83dbSDimitry Andric // Records if a region is not yet scheduled, or schedule has been reverted, 1065ffd83dbSDimitry Andric // or we generally desire to reschedule it. 1075ffd83dbSDimitry Andric BitVector RescheduleRegions; 1085ffd83dbSDimitry Andric 109fe6060f1SDimitry Andric // Record regions which use clustered loads/stores. 110fe6060f1SDimitry Andric BitVector RegionsWithClusters; 111fe6060f1SDimitry Andric 112fe6060f1SDimitry Andric // Record regions with high register pressure. 113fe6060f1SDimitry Andric BitVector RegionsWithHighRP; 114fe6060f1SDimitry Andric 115*81ad6265SDimitry Andric // Regions that has the same occupancy as the latest MinOccupancy 116*81ad6265SDimitry Andric BitVector RegionsWithMinOcc; 117*81ad6265SDimitry Andric 1180b57cec5SDimitry Andric // Region live-in cache. 1190b57cec5SDimitry Andric SmallVector<GCNRPTracker::LiveRegSet, 32> LiveIns; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // Region pressure cache. 1220b57cec5SDimitry Andric SmallVector<GCNRegPressure, 32> Pressure; 1230b57cec5SDimitry Andric 124*81ad6265SDimitry Andric // Each region at MinOccupancy will have their own list of trivially 125*81ad6265SDimitry Andric // rematerializable instructions we can remat to reduce RP. The list maps an 126*81ad6265SDimitry Andric // instruction to the position we should remat before, usually the MI using 127*81ad6265SDimitry Andric // the rematerializable instruction. 128*81ad6265SDimitry Andric MapVector<unsigned, MapVector<MachineInstr *, MachineInstr *>> 129*81ad6265SDimitry Andric RematerializableInsts; 130*81ad6265SDimitry Andric 131*81ad6265SDimitry Andric // Map a trivially remateriazable def to a list of regions at MinOccupancy 132*81ad6265SDimitry Andric // that has the defined reg as a live-in. 133*81ad6265SDimitry Andric DenseMap<MachineInstr *, SmallVector<unsigned, 4>> RematDefToLiveInRegions; 134*81ad6265SDimitry Andric 1350b57cec5SDimitry Andric // Temporary basic block live-in cache. 1360b57cec5SDimitry Andric DenseMap<const MachineBasicBlock*, GCNRPTracker::LiveRegSet> MBBLiveIns; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> BBLiveInMap; 1390b57cec5SDimitry Andric DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> getBBLiveInMap() const; 1400b57cec5SDimitry Andric 141*81ad6265SDimitry Andric // Collect all trivially rematerializable VGPR instructions with a single def 142*81ad6265SDimitry Andric // and single use outside the defining block into RematerializableInsts. 143*81ad6265SDimitry Andric void collectRematerializableInstructions(); 144*81ad6265SDimitry Andric 145*81ad6265SDimitry Andric bool isTriviallyReMaterializable(const MachineInstr &MI, AAResults *AA); 146*81ad6265SDimitry Andric 147*81ad6265SDimitry Andric // TODO: Should also attempt to reduce RP of SGPRs and AGPRs 148*81ad6265SDimitry Andric // Attempt to reduce RP of VGPR by sinking trivially rematerializable 149*81ad6265SDimitry Andric // instructions. Returns true if we were able to sink instruction(s). 150*81ad6265SDimitry Andric bool sinkTriviallyRematInsts(const GCNSubtarget &ST, 151*81ad6265SDimitry Andric const TargetInstrInfo *TII); 152*81ad6265SDimitry Andric 1530b57cec5SDimitry Andric // Return current region pressure. 1540b57cec5SDimitry Andric GCNRegPressure getRealRegPressure() const; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric // Compute and cache live-ins and pressure for all regions in block. 1570b57cec5SDimitry Andric void computeBlockPressure(const MachineBasicBlock *MBB); 1580b57cec5SDimitry Andric 159*81ad6265SDimitry Andric // Update region boundaries when removing MI or inserting NewMI before MI. 160*81ad6265SDimitry Andric void updateRegionBoundaries( 161*81ad6265SDimitry Andric SmallVectorImpl<std::pair<MachineBasicBlock::iterator, 162*81ad6265SDimitry Andric MachineBasicBlock::iterator>> &RegionBoundaries, 163*81ad6265SDimitry Andric MachineBasicBlock::iterator MI, MachineInstr *NewMI, 164*81ad6265SDimitry Andric bool Removing = false); 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric public: 1670b57cec5SDimitry Andric GCNScheduleDAGMILive(MachineSchedContext *C, 1680b57cec5SDimitry Andric std::unique_ptr<MachineSchedStrategy> S); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric void schedule() override; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric void finalizeSchedule() override; 1730b57cec5SDimitry Andric }; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric } // End namespace llvm 1760b57cec5SDimitry Andric 17704eeddc0SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_GCNSCHEDSTRATEGY_H 178