10b57cec5SDimitry Andric //===- GCNIterativeScheduler.h - GCN Scheduler ------------------*- 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 //===----------------------------------------------------------------------===// 8*5ffd83dbSDimitry Andric /// 9*5ffd83dbSDimitry Andric /// \file 10*5ffd83dbSDimitry Andric /// This file defines the class GCNIterativeScheduler, which uses an iterative 11*5ffd83dbSDimitry Andric /// approach to find a best schedule for GCN architecture. It basically makes 12*5ffd83dbSDimitry Andric /// use of various lightweight schedules, scores them, chooses best one based on 13*5ffd83dbSDimitry Andric /// their scores, and finally implements the chosen one. 14*5ffd83dbSDimitry Andric /// 15*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H 180b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "GCNRegPressure.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace llvm { 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric class MachineInstr; 260b57cec5SDimitry Andric class SUnit; 270b57cec5SDimitry Andric class raw_ostream; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric class GCNIterativeScheduler : public ScheduleDAGMILive { 300b57cec5SDimitry Andric using BaseClass = ScheduleDAGMILive; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric public: 330b57cec5SDimitry Andric enum StrategyKind { 340b57cec5SDimitry Andric SCHEDULE_MINREGONLY, 350b57cec5SDimitry Andric SCHEDULE_MINREGFORCED, 360b57cec5SDimitry Andric SCHEDULE_LEGACYMAXOCCUPANCY, 370b57cec5SDimitry Andric SCHEDULE_ILP 380b57cec5SDimitry Andric }; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric GCNIterativeScheduler(MachineSchedContext *C, 410b57cec5SDimitry Andric StrategyKind S); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric void schedule() override; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric void enterRegion(MachineBasicBlock *BB, 460b57cec5SDimitry Andric MachineBasicBlock::iterator Begin, 470b57cec5SDimitry Andric MachineBasicBlock::iterator End, 480b57cec5SDimitry Andric unsigned RegionInstrs) override; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric void finalizeSchedule() override; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric protected: 530b57cec5SDimitry Andric using ScheduleRef = ArrayRef<const SUnit *>; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric struct TentativeSchedule { 560b57cec5SDimitry Andric std::vector<MachineInstr *> Schedule; 570b57cec5SDimitry Andric GCNRegPressure MaxPressure; 580b57cec5SDimitry Andric }; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric struct Region { 610b57cec5SDimitry Andric // Fields except for BestSchedule are supposed to reflect current IR state 620b57cec5SDimitry Andric // `const` fields are to emphasize they shouldn't change for any schedule. 630b57cec5SDimitry Andric MachineBasicBlock::iterator Begin; 640b57cec5SDimitry Andric // End is either a boundary instruction or end of basic block 650b57cec5SDimitry Andric const MachineBasicBlock::iterator End; 660b57cec5SDimitry Andric const unsigned NumRegionInstrs; 670b57cec5SDimitry Andric GCNRegPressure MaxPressure; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric // best schedule for the region so far (not scheduled yet) 700b57cec5SDimitry Andric std::unique_ptr<TentativeSchedule> BestSchedule; 710b57cec5SDimitry Andric }; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric SpecificBumpPtrAllocator<Region> Alloc; 740b57cec5SDimitry Andric std::vector<Region*> Regions; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric MachineSchedContext *Context; 770b57cec5SDimitry Andric const StrategyKind Strategy; 780b57cec5SDimitry Andric mutable GCNUpwardRPTracker UPTracker; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric class BuildDAG; 810b57cec5SDimitry Andric class OverrideLegacyStrategy; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric template <typename Range> 840b57cec5SDimitry Andric GCNRegPressure getSchedulePressure(const Region &R, 850b57cec5SDimitry Andric Range &&Schedule) const; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin, 880b57cec5SDimitry Andric MachineBasicBlock::iterator End) const; 890b57cec5SDimitry Andric getRegionPressure(const Region & R)900b57cec5SDimitry Andric GCNRegPressure getRegionPressure(const Region &R) const { 910b57cec5SDimitry Andric return getRegionPressure(R.Begin, R.End); 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric void setBestSchedule(Region &R, 950b57cec5SDimitry Andric ScheduleRef Schedule, 960b57cec5SDimitry Andric const GCNRegPressure &MaxRP = GCNRegPressure()); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric void scheduleBest(Region &R); 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric std::vector<MachineInstr*> detachSchedule(ScheduleRef Schedule) const; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric void sortRegionsByPressure(unsigned TargetOcc); 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric template <typename Range> 1050b57cec5SDimitry Andric void scheduleRegion(Region &R, Range &&Schedule, 1060b57cec5SDimitry Andric const GCNRegPressure &MaxRP = GCNRegPressure()); 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric unsigned tryMaximizeOccupancy(unsigned TargetOcc = 1090b57cec5SDimitry Andric std::numeric_limits<unsigned>::max()); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric void scheduleLegacyMaxOccupancy(bool TryMaximizeOccupancy = true); 1120b57cec5SDimitry Andric void scheduleMinReg(bool force = false); 1130b57cec5SDimitry Andric void scheduleILP(bool TryMaximizeOccupancy = true); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric void printRegions(raw_ostream &OS) const; 1160b57cec5SDimitry Andric void printSchedResult(raw_ostream &OS, 1170b57cec5SDimitry Andric const Region *R, 1180b57cec5SDimitry Andric const GCNRegPressure &RP) const; 1190b57cec5SDimitry Andric void printSchedRP(raw_ostream &OS, 1200b57cec5SDimitry Andric const GCNRegPressure &Before, 1210b57cec5SDimitry Andric const GCNRegPressure &After) const; 1220b57cec5SDimitry Andric }; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric } // end namespace llvm 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H 127