23 #define DEBUG_TYPE "machine-scheduler" 42 const int ErrorMargin = 3;
48 if (TargetOccupancy) {
58 SGPRCriticalLimit -= ErrorMargin;
59 VGPRCriticalLimit -= ErrorMargin;
65 unsigned SGPRPressure,
66 unsigned VGPRPressure) {
75 std::vector<unsigned> Pressure;
76 std::vector<unsigned> MaxPressure;
97 const unsigned MaxVGPRPressureInc = 16;
98 bool ShouldTrackVGPRs = VGPRPressure + MaxVGPRPressureInc >= VGPRExcessLimit;
99 bool ShouldTrackSGPRs = !ShouldTrackVGPRs && SGPRPressure >= SGPRExcessLimit;
111 if (ShouldTrackVGPRs && NewVGPRPressure >= VGPRExcessLimit) {
116 if (ShouldTrackSGPRs && NewSGPRPressure >= SGPRExcessLimit) {
126 int SGPRDelta = NewSGPRPressure - SGPRCriticalLimit;
127 int VGPRDelta = NewVGPRPressure - VGPRCriticalLimit;
129 if (SGPRDelta >= 0 || VGPRDelta >= 0) {
130 if (SGPRDelta > VGPRDelta) {
142 void GCNMaxOccupancySchedStrategy::pickNodeFromQueue(
SchedBoundary &Zone,
151 for (
SUnit *SU : Q) {
154 initCandidate(TryCand, SU, Zone.
isTop(), RPTracker, SRI,
155 SGPRPressure, VGPRPressure);
170 SUnit *GCNMaxOccupancySchedStrategy::pickNodeBidirectional(
bool &IsTopNode) {
245 IsTopNode = Cand.AtTop;
280 SU = pickNodeBidirectional(IsTopNode);
295 std::unique_ptr<MachineSchedStrategy> S) :
299 StartingOccupancy(MFI.getOccupancy()),
300 MinOccupancy(StartingOccupancy), Stage(0), RegionIdx(0) {
302 LLVM_DEBUG(
dbgs() <<
"Starting occupancy is " << StartingOccupancy <<
".\n");
312 std::vector<MachineInstr*> Unsched;
314 for (
auto &
I : *
this) {
315 Unsched.push_back(&
I);
320 PressureBefore = Pressure[RegionIdx];
322 LLVM_DEBUG(
dbgs() <<
"Pressure before scheduling:\nRegion live-ins:";
324 dbgs() <<
"Region live-in pressure: ";
326 dbgs() <<
"Region register pressure: ";
338 auto PressureAfter = getRealRegPressure();
341 PressureAfter.print(
dbgs()));
343 if (PressureAfter.getSGPRNum() <= S.SGPRCriticalLimit &&
344 PressureAfter.getVGPRNum() <= S.VGPRCriticalLimit) {
345 Pressure[RegionIdx] = PressureAfter;
350 unsigned WavesAfter = std::min(Occ, PressureAfter.getOccupancy(ST));
351 unsigned WavesBefore = std::min(Occ, PressureBefore.
getOccupancy(ST));
352 LLVM_DEBUG(
dbgs() <<
"Occupancy before scheduling: " << WavesBefore
353 <<
", after " << WavesAfter <<
".\n");
357 unsigned NewOccupancy =
std::max(WavesAfter, WavesBefore);
360 if (WavesAfter < WavesBefore && WavesAfter < MinOccupancy &&
362 LLVM_DEBUG(
dbgs() <<
"Function is memory bound, allow occupancy drop up to " 364 NewOccupancy = WavesAfter;
366 if (NewOccupancy < MinOccupancy) {
367 MinOccupancy = NewOccupancy;
370 << MinOccupancy <<
".\n");
373 if (WavesAfter >= MinOccupancy) {
374 Pressure[RegionIdx] = PressureAfter;
381 if (
MI->isDebugInstr())
387 if (!
MI->isDebugInstr())
391 for (
auto &
Op :
MI->operands())
392 if (
Op.isReg() &&
Op.isDef())
393 Op.setIsUndef(
false);
396 if (!
MI->isDebugInstr()) {
436 size_t CurRegion = RegionIdx;
437 for (
size_t E = Regions.size(); CurRegion !=
E; ++CurRegion)
438 if (Regions[CurRegion].
first->getParent() != MBB)
443 auto LiveInIt = MBBLiveIns.find(MBB);
444 if (LiveInIt != MBBLiveIns.end()) {
445 auto LiveIn = std::move(LiveInIt->second);
447 MBBLiveIns.erase(LiveInIt);
449 I = Regions[CurRegion].first;
456 if (Regions[CurRegion].
first ==
I) {
461 if (Regions[CurRegion].
second ==
I) {
463 if (CurRegion-- == RegionIdx)
471 if (
I != MBB->
end()) {
483 LLVM_DEBUG(
dbgs() <<
"All regions recorded, starting actual scheduling.\n");
485 LiveIns.resize(Regions.size());
486 Pressure.resize(Regions.size());
499 if (!
LIS || StartingOccupancy <= MinOccupancy)
504 <<
"Retrying function scheduling with lowest recorded occupancy " 505 << MinOccupancy <<
".\n");
510 for (
auto Region : Regions) {
519 computeBlockPressure(MBB);
536 else dbgs() <<
"End";
537 dbgs() <<
" RegionInstrs: " << NumRegionInstrs <<
'\n');
Interface definition for SIRegisterInfo.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
SUnit * pickNode(bool &IsTopNode) override
Pick the best node to balance the schedule. Implements MachineSchedStrategy.
AMDGPU specific subclass of TargetSubtarget.
void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS)
Use liveness information to find dead defs not marked with a dead flag and move them to the DeadDefs ...
Each Scheduling boundary is associated with ready queues.
static void printLiveRegs(raw_ostream &OS, const LiveRegSet &LiveRegs, const MachineRegisterInfo &MRI)
This class represents lattice values for constants.
const MachineSchedContext * Context
This is a minimal scheduler strategy.
decltype(MaxPressure) moveMaxPressure()
void startBlock(MachineBasicBlock *bb) override
Prepares to perform scheduling in the given block.
bool reset(const MachineInstr &MI, const LiveRegSet *LiveRegs=nullptr)
void traceCandidate(const SchedCandidate &Cand)
void setTargetOccupancy(unsigned Occ)
void reset(const CandPolicy &NewPolicy)
bool isBottomReady() const
unsigned NumRegionInstrs
Instructions in this region (distance(RegionBegin, RegionEnd)).
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
std::unique_ptr< MachineSchedStrategy > SchedImpl
decltype(LiveRegs) moveLiveRegs()
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
MachineFunction & MF
Machine function.
bool isScheduled
True once scheduled.
const RegPressureTracker & getBotRPTracker() const
decltype(LiveRegs) const & getLiveRegs() const
MachineBasicBlock::iterator RegionEnd
The end of the range to be scheduled.
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
unsigned getOccupancy(const GCNSubtarget &ST) const
bool ShouldTrackLaneMasks
void limitOccupancy(const MachineFunction &MF)
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def...
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
MachineBasicBlock::iterator top() const
MachineSchedPolicy RegionPolicy
MachineBasicBlock::iterator begin() const
Returns an iterator to the top of the current scheduling region.
void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, bool TrackLaneMasks, bool IgnoreDead)
Analyze the given instruction MI and fill in the Uses, Defs and DeadDefs list based on the MachineOpe...
List of registers defined and used by a machine instruction.
const MachineBasicBlock::const_iterator getNext() const
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
unsigned getMinAllowedOccupancy() const
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
RegisterClassInfo * RegClassInfo
unsigned getMaxNumSGPRs(unsigned WavesPerEU, bool Addressable) const
CandReason
Represent the type of SchedCandidate found within a single queue.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
Helpers for implementing custom MachineSchedStrategy classes.
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
GCNScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S)
unsigned getOccupancy() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void removeReady(SUnit *SU)
Remove SU from the ready set for this boundary.
SlotIndex getMBBStartIdx(unsigned Num) const
Returns the first index in the given basic block number.
Store the state used by GenericScheduler heuristics, required for the lifetime of one invocation of p...
Track the current register pressure at some position in the instruction stream, and remember the high...
unsigned getSGPRPressureSet() const
Policy for scheduling the next instruction in the candidate's zone.
unsigned getNumAllocatableRegs(const TargetRegisterClass *RC) const
getNumAllocatableRegs - Returns the number of actually allocatable registers in RC in the current fun...
const TargetSchedModel * SchedModel
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
SchedResourceDelta ResDelta
const TargetRegisterInfo * TRI
succ_iterator succ_begin()
void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone, SchedBoundary *OtherZone)
Set the CandPolicy given a scheduling zone given the current resources and latencies inside and outsi...
unsigned getVGPRPressureSet() const
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
const std::vector< unsigned > & getRegSetPressureAtPos() const
Get the register set pressure at the current position, which may be less than the pressure across the...
void adjustLaneLiveness(const LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos, MachineInstr *AddFlagsMI=nullptr)
Use liveness information to find out which uses/defs are partially undefined/dead and adjust the Regi...
GenericScheduler shrinks the unscheduled zone using heuristics to balance the schedule.
unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const override
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
const RegPressureTracker & getTopRPTracker() const
MachineInstr * remove(MachineInstr *I)
Remove the unbundled instruction from the instruction list without deleting it.
void initResourceDelta(const ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
PressureChange CriticalMax
unsigned succ_size() const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI, Range &&LiveRegs)
void initialize(ScheduleDAGMI *dag) override
Initialize the strategy after building the DAG for a new region.
virtual void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const
Apply a set of heuristics to a new candidate.
Representation of each machine instruction.
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Interface definition for SIInstrInfo.
const TargetRegisterInfo * TRI
Target processor register info.
SUnit * pickOnlyChoice()
Call this before applying any other heuristics to the Available queue.
Status of an instruction's critical resource consumption.
SchedCandidate BotCand
Candidate last picked from Bot boundary.
MachineBasicBlock::iterator bottom() const
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
Capture a change in pressure for a single pressure set.
void getUpwardPressure(const MachineInstr *MI, std::vector< unsigned > &PressureResult, std::vector< unsigned > &MaxPressureResult)
Get the pressure of each PSet after traversing this instruction bottom-up.
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
SlotIndexes * getSlotIndexes() const
unsigned NodeNum
Entry # of node in the node vector.
unsigned getMaxNumVGPRs(unsigned WavesPerEU) const
MachineBasicBlock::iterator end() const
Returns an iterator to the bottom of the current scheduling region.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void print(raw_ostream &OS, const GCNSubtarget *ST=nullptr) const
GCNMaxOccupancySchedStrategy(const MachineSchedContext *C)
SchedCandidate TopCand
Candidate last picked from Top boundary.
void finalizeSchedule() override
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
void getDownwardPressure(const MachineInstr *MI, std::vector< unsigned > &PressureResult, std::vector< unsigned > &MaxPressureResult)
Get the pressure of each PSet after traversing this instruction top-down.
MachineBasicBlock * BB
The block in which to insert instructions.
MachineRegisterInfo & MRI
Virtual/real register map.
SlotIndex - An opaque wrapper around machine indexes.
void initialize(ScheduleDAGMI *DAG) override
Initialize the strategy after building the DAG for a new region.
void finishBlock() override
Cleans up after scheduling in the given block.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
RegPressureTracker RPTracker
void setBest(SchedCandidate &Best)
void handleMove(MachineInstr &MI, bool UpdateFlags=false)
Call this method to notify LiveIntervals that instruction MI has been moved within a basic block...
Scheduling unit. This is a node in the scheduling DAG.