#include "GCNSchedStrategy.h"
#include "AMDGPUIGroupLP.h"
#include "SIMachineFunctionInfo.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#define DEBUG_TYPE …
usingnamespacellvm;
static cl::opt<bool> DisableUnclusterHighRP(
"amdgpu-disable-unclustered-high-rp-reschedule", cl::Hidden,
cl::desc("Disable unclustered high register pressure "
"reduction scheduling stage."),
cl::init(false));
static cl::opt<bool> DisableClusteredLowOccupancy(
"amdgpu-disable-clustered-low-occupancy-reschedule", cl::Hidden,
cl::desc("Disable clustered low occupancy "
"rescheduling for ILP scheduling stage."),
cl::init(false));
static cl::opt<unsigned> ScheduleMetricBias(
"amdgpu-schedule-metric-bias", cl::Hidden,
cl::desc(
"Sets the bias which adds weight to occupancy vs latency. Set it to "
"100 to chase the occupancy only."),
cl::init(10));
static cl::opt<bool>
RelaxedOcc("amdgpu-schedule-relaxed-occupancy", cl::Hidden,
cl::desc("Relax occupancy targets for kernels which are memory "
"bound (amdgpu-membound-threshold), or "
"Wave Limited (amdgpu-limit-wave-threshold)."),
cl::init(false));
const unsigned ScheduleMetrics::ScaleFactor = …;
GCNSchedStrategy::GCNSchedStrategy(const MachineSchedContext *C)
: … { … }
void GCNSchedStrategy::initialize(ScheduleDAGMI *DAG) { … }
static bool canUsePressureDiffs(const SUnit &SU) { … }
static void getRegisterPressures(bool AtTop,
const RegPressureTracker &RPTracker, SUnit *SU,
std::vector<unsigned> &Pressure,
std::vector<unsigned> &MaxPressure) { … }
void GCNSchedStrategy::initCandidate(SchedCandidate &Cand, SUnit *SU,
bool AtTop,
const RegPressureTracker &RPTracker,
const SIRegisterInfo *SRI,
unsigned SGPRPressure,
unsigned VGPRPressure, bool IsBottomUp) { … }
void GCNSchedStrategy::pickNodeFromQueue(SchedBoundary &Zone,
const CandPolicy &ZonePolicy,
const RegPressureTracker &RPTracker,
SchedCandidate &Cand,
bool IsBottomUp) { … }
SUnit *GCNSchedStrategy::pickNodeBidirectional(bool &IsTopNode) { … }
SUnit *GCNSchedStrategy::pickNode(bool &IsTopNode) { … }
GCNSchedStageID GCNSchedStrategy::getCurrentStage() { … }
bool GCNSchedStrategy::advanceStage() { … }
bool GCNSchedStrategy::hasNextStage() const { … }
GCNSchedStageID GCNSchedStrategy::getNextStage() const { … }
GCNMaxOccupancySchedStrategy::GCNMaxOccupancySchedStrategy(
const MachineSchedContext *C)
: … { … }
GCNMaxILPSchedStrategy::GCNMaxILPSchedStrategy(const MachineSchedContext *C)
: … { … }
bool GCNMaxILPSchedStrategy::tryCandidate(SchedCandidate &Cand,
SchedCandidate &TryCand,
SchedBoundary *Zone) const { … }
GCNScheduleDAGMILive::GCNScheduleDAGMILive(
MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S)
: … { … }
std::unique_ptr<GCNSchedStage>
GCNScheduleDAGMILive::createSchedStage(GCNSchedStageID SchedStageID) { … }
void GCNScheduleDAGMILive::schedule() { … }
GCNRegPressure
GCNScheduleDAGMILive::getRealRegPressure(unsigned RegionIdx) const { … }
void GCNScheduleDAGMILive::computeBlockPressure(unsigned RegionIdx,
const MachineBasicBlock *MBB) { … }
DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet>
GCNScheduleDAGMILive::getBBLiveInMap() const { … }
void GCNScheduleDAGMILive::finalizeSchedule() { … }
void GCNScheduleDAGMILive::runSchedStages() { … }
#ifndef NDEBUG
raw_ostream &llvm::operator<<(raw_ostream &OS, const GCNSchedStageID &StageID) {
switch (StageID) {
case GCNSchedStageID::OccInitialSchedule:
OS << "Max Occupancy Initial Schedule";
break;
case GCNSchedStageID::UnclusteredHighRPReschedule:
OS << "Unclustered High Register Pressure Reschedule";
break;
case GCNSchedStageID::ClusteredLowOccupancyReschedule:
OS << "Clustered Low Occupancy Reschedule";
break;
case GCNSchedStageID::PreRARematerialize:
OS << "Pre-RA Rematerialize";
break;
case GCNSchedStageID::ILPInitialSchedule:
OS << "Max ILP Initial Schedule";
break;
}
return OS;
}
#endif
GCNSchedStage::GCNSchedStage(GCNSchedStageID StageID, GCNScheduleDAGMILive &DAG)
: … { … }
bool GCNSchedStage::initGCNSchedStage() { … }
bool UnclusteredHighRPStage::initGCNSchedStage() { … }
bool ClusteredLowOccStage::initGCNSchedStage() { … }
bool PreRARematStage::initGCNSchedStage() { … }
void GCNSchedStage::finalizeGCNSchedStage() { … }
void UnclusteredHighRPStage::finalizeGCNSchedStage() { … }
bool GCNSchedStage::initGCNRegion() { … }
bool UnclusteredHighRPStage::initGCNRegion() { … }
bool ClusteredLowOccStage::initGCNRegion() { … }
bool PreRARematStage::initGCNRegion() { … }
void GCNSchedStage::setupNewBlock() { … }
void GCNSchedStage::finalizeGCNRegion() { … }
void GCNSchedStage::checkScheduling() { … }
unsigned
GCNSchedStage::computeSUnitReadyCycle(const SUnit &SU, unsigned CurrCycle,
DenseMap<unsigned, unsigned> &ReadyCycles,
const TargetSchedModel &SM) { … }
#ifndef NDEBUG
struct EarlierIssuingCycle {
bool operator()(std::pair<MachineInstr *, unsigned> A,
std::pair<MachineInstr *, unsigned> B) const {
return A.second < B.second;
}
};
static void printScheduleModel(std::set<std::pair<MachineInstr *, unsigned>,
EarlierIssuingCycle> &ReadyCycles) {
if (ReadyCycles.empty())
return;
unsigned BBNum = ReadyCycles.begin()->first->getParent()->getNumber();
dbgs() << "\n################## Schedule time ReadyCycles for MBB : " << BBNum
<< " ##################\n# Cycle #\t\t\tInstruction "
" "
" \n";
unsigned IPrev = 1;
for (auto &I : ReadyCycles) {
if (I.second > IPrev + 1)
dbgs() << "****************************** BUBBLE OF " << I.second - IPrev
<< " CYCLES DETECTED ******************************\n\n";
dbgs() << "[ " << I.second << " ] : " << *I.first << "\n";
IPrev = I.second;
}
}
#endif
ScheduleMetrics
GCNSchedStage::getScheduleMetrics(const std::vector<SUnit> &InputSchedule) { … }
ScheduleMetrics
GCNSchedStage::getScheduleMetrics(const GCNScheduleDAGMILive &DAG) { … }
bool GCNSchedStage::shouldRevertScheduling(unsigned WavesAfter) { … }
bool OccInitialScheduleStage::shouldRevertScheduling(unsigned WavesAfter) { … }
bool UnclusteredHighRPStage::shouldRevertScheduling(unsigned WavesAfter) { … }
bool ClusteredLowOccStage::shouldRevertScheduling(unsigned WavesAfter) { … }
bool PreRARematStage::shouldRevertScheduling(unsigned WavesAfter) { … }
bool ILPInitialScheduleStage::shouldRevertScheduling(unsigned WavesAfter) { … }
bool GCNSchedStage::mayCauseSpilling(unsigned WavesAfter) { … }
void GCNSchedStage::revertScheduling() { … }
void PreRARematStage::collectRematerializableInstructions() { … }
bool PreRARematStage::sinkTriviallyRematInsts(const GCNSubtarget &ST,
const TargetInstrInfo *TII) { … }
bool PreRARematStage::isTriviallyReMaterializable(const MachineInstr &MI) { … }
void GCNScheduleDAGMILive::updateRegionBoundaries(
SmallVectorImpl<std::pair<MachineBasicBlock::iterator,
MachineBasicBlock::iterator>> &RegionBoundaries,
MachineBasicBlock::iterator MI, MachineInstr *NewMI, bool Removing) { … }
static bool hasIGLPInstrs(ScheduleDAGInstrs *DAG) { … }
GCNPostScheduleDAGMILive::GCNPostScheduleDAGMILive(
MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S,
bool RemoveKillFlags)
: … { … }
void GCNPostScheduleDAGMILive::schedule() { … }
void GCNPostScheduleDAGMILive::finalizeSchedule() { … }