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 530b57cec5SDimitry Andric MachineFunction *MF; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric public: 560b57cec5SDimitry Andric GCNMaxOccupancySchedStrategy(const MachineSchedContext *C); 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric SUnit *pickNode(bool &IsTopNode) override; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric void initialize(ScheduleDAGMI *DAG) override; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric void setTargetOccupancy(unsigned Occ) { TargetOccupancy = Occ; } 630b57cec5SDimitry Andric }; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric class GCNScheduleDAGMILive final : public ScheduleDAGMILive { 660b57cec5SDimitry Andric 67*5ffd83dbSDimitry Andric enum : unsigned { 68*5ffd83dbSDimitry Andric Collect, 69*5ffd83dbSDimitry Andric InitialSchedule, 70*5ffd83dbSDimitry Andric UnclusteredReschedule, 71*5ffd83dbSDimitry Andric ClusteredLowOccupancyReschedule, 72*5ffd83dbSDimitry Andric LastStage = ClusteredLowOccupancyReschedule 73*5ffd83dbSDimitry Andric }; 74*5ffd83dbSDimitry Andric 750b57cec5SDimitry Andric const GCNSubtarget &ST; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric SIMachineFunctionInfo &MFI; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric // Occupancy target at the beginning of function scheduling cycle. 800b57cec5SDimitry Andric unsigned StartingOccupancy; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric // Minimal real occupancy recorder for the function. 830b57cec5SDimitry Andric unsigned MinOccupancy; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric // Scheduling stage number. 860b57cec5SDimitry Andric unsigned Stage; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric // Current region index. 890b57cec5SDimitry Andric size_t RegionIdx; 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric // Vector of regions recorder for later rescheduling 920b57cec5SDimitry Andric SmallVector<std::pair<MachineBasicBlock::iterator, 930b57cec5SDimitry Andric MachineBasicBlock::iterator>, 32> Regions; 940b57cec5SDimitry Andric 95*5ffd83dbSDimitry Andric // Records if a region is not yet scheduled, or schedule has been reverted, 96*5ffd83dbSDimitry Andric // or we generally desire to reschedule it. 97*5ffd83dbSDimitry Andric BitVector RescheduleRegions; 98*5ffd83dbSDimitry Andric 990b57cec5SDimitry Andric // Region live-in cache. 1000b57cec5SDimitry Andric SmallVector<GCNRPTracker::LiveRegSet, 32> LiveIns; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // Region pressure cache. 1030b57cec5SDimitry Andric SmallVector<GCNRegPressure, 32> Pressure; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // Temporary basic block live-in cache. 1060b57cec5SDimitry Andric DenseMap<const MachineBasicBlock*, GCNRPTracker::LiveRegSet> MBBLiveIns; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> BBLiveInMap; 1090b57cec5SDimitry Andric DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> getBBLiveInMap() const; 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric // Return current region pressure. 1120b57cec5SDimitry Andric GCNRegPressure getRealRegPressure() const; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric // Compute and cache live-ins and pressure for all regions in block. 1150b57cec5SDimitry Andric void computeBlockPressure(const MachineBasicBlock *MBB); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric public: 1190b57cec5SDimitry Andric GCNScheduleDAGMILive(MachineSchedContext *C, 1200b57cec5SDimitry Andric std::unique_ptr<MachineSchedStrategy> S); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric void schedule() override; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric void finalizeSchedule() override; 1250b57cec5SDimitry Andric }; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric } // End namespace llvm 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric #endif // GCNSCHEDSTRATEGY_H 130