//===- GCNIterativeScheduler.h - GCN Scheduler ------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file defines the class GCNIterativeScheduler, which uses an iterative /// approach to find a best schedule for GCN architecture. It basically makes /// use of various lightweight schedules, scores them, chooses best one based on /// their scores, and finally implements the chosen one. /// //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H #define LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H #include "GCNRegPressure.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineScheduler.h" #include "llvm/Support/Allocator.h" #include #include #include namespace llvm { class MachineInstr; class SUnit; class raw_ostream; class GCNIterativeScheduler : public ScheduleDAGMILive { using BaseClass = ScheduleDAGMILive; public: enum StrategyKind { SCHEDULE_MINREGONLY, SCHEDULE_MINREGFORCED, SCHEDULE_LEGACYMAXOCCUPANCY, SCHEDULE_ILP }; GCNIterativeScheduler(MachineSchedContext *C, StrategyKind S); void schedule() override; void enterRegion(MachineBasicBlock *BB, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned RegionInstrs) override; void finalizeSchedule() override; protected: using ScheduleRef = ArrayRef; struct TentativeSchedule { std::vector Schedule; GCNRegPressure MaxPressure; }; struct Region { // Fields except for BestSchedule are supposed to reflect current IR state // `const` fields are to emphasize they shouldn't change for any schedule. MachineBasicBlock::iterator Begin; // End is either a boundary instruction or end of basic block const MachineBasicBlock::iterator End; const unsigned NumRegionInstrs; GCNRegPressure MaxPressure; // best schedule for the region so far (not scheduled yet) std::unique_ptr BestSchedule; }; SpecificBumpPtrAllocator Alloc; std::vector Regions; MachineSchedContext *Context; const StrategyKind Strategy; mutable GCNUpwardRPTracker UPTracker; class BuildDAG; class OverrideLegacyStrategy; template GCNRegPressure getSchedulePressure(const Region &R, Range &&Schedule) const; GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End) const; GCNRegPressure getRegionPressure(const Region &R) const { return getRegionPressure(R.Begin, R.End); } void setBestSchedule(Region &R, ScheduleRef Schedule, const GCNRegPressure &MaxRP = GCNRegPressure()); void scheduleBest(Region &R); std::vector detachSchedule(ScheduleRef Schedule) const; void sortRegionsByPressure(unsigned TargetOcc); template void scheduleRegion(Region &R, Range &&Schedule, const GCNRegPressure &MaxRP = GCNRegPressure()); unsigned tryMaximizeOccupancy(unsigned TargetOcc = std::numeric_limits::max()); void scheduleLegacyMaxOccupancy(bool TryMaximizeOccupancy = true); void scheduleMinReg(bool force = false); void scheduleILP(bool TryMaximizeOccupancy = true); void printRegions(raw_ostream &OS) const; void printSchedResult(raw_ostream &OS, const Region *R, const GCNRegPressure &RP) const; void printSchedRP(raw_ostream &OS, const GCNRegPressure &Before, const GCNRegPressure &After) const; }; } // end namespace llvm #endif // LLVM_LIB_TARGET_AMDGPU_GCNITERATIVESCHEDULER_H