21#define DEBUG_TYPE "machine-scheduler"
43#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
50 std::numeric_limits<unsigned>::max()) {
51 auto *BB = Begin->getParent();
53 << BB->getName() <<
":\n";
55 MaxInstNum = std::max(MaxInstNum, 1u);
56 for (;
I != End && MaxInstNum; ++
I, --MaxInstNum) {
57 if (!
I->isDebugInstr() && LIS)
64 if (!
I->isDebugInstr() && LIS)
68 if (End != BB->end()) {
80 auto *
const BB = Begin->getParent();
81 const auto &MRI = BB->getParent()->getRegInfo();
86 const auto BottomMI = End == BB->end() ? std::prev(End) : End;
95 OS <<
"Region to schedule ";
98 OS <<
"Max RP: " <<
print(R->MaxPressure, &ST);
106 OS <<
"\nAfter scheduling ";
117 OS <<
"RP before: " <<
print(Before, &ST)
118 <<
"RP after: " <<
print(After, &ST);
123 bool HasIGLPInstrs =
false;
127 HasIGLPInstrs =
true;
151 auto *
BB = R.Begin->getParent();
152 Sch.BaseClass::startBlock(
BB);
153 Sch.BaseClass::enterRegion(
BB, R.Begin, R.End, R.NumRegionInstrs);
154 Sch.swapIGLPMutations(R, IsReentry);
155 Sch.buildSchedGraph(Sch.AA,
nullptr,
nullptr,
nullptr,
157 Sch.postProcessDAG();
158 Sch.Topo.InitDAGTopologicalSorting();
159 Sch.findRootsAndBiasEdges(TopRoots, BotRoots);
163 Sch.BaseClass::exitRegion();
164 Sch.BaseClass::finishBlock();
178 std::unique_ptr<MachineSchedStrategy> SaveSchedImpl;
188 , SaveMaxRP(R.MaxPressure) {
189 Sch.SchedImpl.reset(&OverrideStrategy);
190 auto *
BB = R.Begin->getParent();
191 Sch.BaseClass::startBlock(
BB);
192 Sch.BaseClass::enterRegion(
BB, R.Begin, R.End, R.NumRegionInstrs);
196 Sch.BaseClass::exitRegion();
197 Sch.BaseClass::finishBlock();
198 Sch.SchedImpl.release();
199 Sch.SchedImpl = std::move(SaveSchedImpl);
203 assert(Sch.RegionBegin == Rgn.Begin && Sch.RegionEnd == Rgn.End);
206 Sch.BaseClass::schedule();
209 Sch.RegionEnd = Rgn.End;
211 Rgn.Begin = Sch.RegionBegin;
212 Rgn.MaxPressure.clear();
216 assert(Sch.RegionBegin == Rgn.Begin && Sch.RegionEnd == Rgn.End);
219 Sch.scheduleRegion(Rgn, Sch.SUnits, SaveMaxRP);
228 bool shouldTrackPressure()
const override {
return false; }
229 bool shouldTrackLaneMasks()
const override {
return false; }
230 void initialize(ScheduleDAGMI *DAG)
override {}
231 SUnit *pickNode(
bool &IsTopNode)
override {
return nullptr; }
232 void schedNode(SUnit *SU,
bool IsTopNode)
override {}
233 void releaseTopNode(SUnit *SU)
override {}
234 void releaseBottomNode(SUnit *SU)
override {}
241 : BaseClass(
C,
std::make_unique<SchedStrategyStub>())
255 auto const BBEnd = Begin->getParent()->end();
256 auto const BottomMI = End == BBEnd ? std::prev(End) : End;
260 auto AfterBottomMI = std::next(BottomMI);
261 if (AfterBottomMI == BBEnd ||
262 &*AfterBottomMI !=
UPTracker.getLastTrackedMI()) {
268 for (
auto I = BottomMI;
I != Begin; --
I)
274 (
dbgs() <<
"Tracked region ",
276 return UPTracker.getMaxPressureAndReset();
282 Range &&Schedule)
const {
283 auto const BBEnd = R.Begin->getParent()->end();
285 if (R.End != BBEnd) {
294 for (
auto I = Schedule.end(),
B = Schedule.begin();
I !=
B;) {
297 return RPTracker.getMaxPressureAndReset();
307 new (
Alloc.Allocate())
308 Region { Begin, End, NumRegionInstrs,
309 getRegionPressure(Begin, End), nullptr });
318 << print(Regions.back()->MaxPressure,
319 &MF.getSubtarget<GCNSubtarget>());
337std::vector<MachineInstr*>
339 std::vector<MachineInstr*> Res;
340 Res.reserve(Schedule.
size() * 2);
346 for (
const auto *SU : Schedule) {
347 Res.push_back(SU->getInstr());
348 const auto &
D = std::find_if(DbgB, DbgE, [SU](
decltype(*DbgB) &
P) {
349 return P.second == SU->getInstr();
352 Res.push_back(
D->first);
360 R.BestSchedule.reset(
365 assert(R.BestSchedule.get() &&
"No schedule specified");
366 scheduleRegion(R, R.BestSchedule->Schedule, R.BestSchedule->MaxPressure);
367 R.BestSchedule.reset();
374 Op.setIsUndef(
false);
384 if (!
I->isDebugInstr())
391template <
typename Range>
399 auto *
BB = R.Begin->getParent();
401 for (
const auto &
I : Schedule) {
406 bool NonDebugReordered =
410 if (NonDebugReordered)
411 LIS->handleMove(*
MI,
true);
413 if (!
MI->isDebugInstr())
415 Top = std::next(
MI->getIterator());
421 if (!std::is_same_v<
decltype(*Schedule.begin()),
MachineInstr*>) {
429 R.MaxPressure = MaxRP;
436 (SchedMaxRP == RegionMaxRP && (MaxRP.
empty() || SchedMaxRP == MaxRP)) ||
437 (
dbgs() <<
"Max RP mismatch!!!\n"
438 "RP for schedule (calculated): "
439 <<
print(SchedMaxRP, &ST)
440 <<
"RP for schedule (reported): " <<
print(MaxRP, &ST)
441 <<
"RP after scheduling: " <<
print(RegionMaxRP, &ST),
464 const unsigned DynamicVGPRBlockSize =
467 Regions.front()->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize);
468 LLVM_DEBUG(
dbgs() <<
"Trying to improve occupancy, target = " << TargetOcc
469 <<
", current = " << Occ <<
'\n');
471 auto NewOcc = TargetOcc;
476 if (R->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize) >= NewOcc)
487 NewOcc = std::min(NewOcc, MaxRP.getOccupancy(ST, DynamicVGPRBlockSize));
494 <<
", prev occupancy = " << Occ <<
'\n');
497 MFI->increaseOccupancy(
MF, NewOcc);
500 return std::max(NewOcc, Occ);
504 bool TryMaximizeOccupancy) {
507 auto TgtOcc =
MFI->getMinAllowedOccupancy();
508 unsigned DynamicVGPRBlockSize =
MFI->getDynamicVGPRBlockSize();
512 Regions.front()->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize);
514 bool IsReentry =
false;
515 if (TryMaximizeOccupancy && Occ < TgtOcc) {
522 const int NumPasses = Occ < TgtOcc ? 2 : 1;
524 TgtOcc = std::min(Occ, TgtOcc);
526 "target occupancy = "
529 unsigned FinalOccupancy = std::min(Occ,
MFI->getOccupancy());
531 for (
int I = 0;
I < NumPasses; ++
I) {
543 if (RP.getOccupancy(ST, DynamicVGPRBlockSize) < TgtOcc) {
544 LLVM_DEBUG(
dbgs() <<
"Didn't fit into target occupancy O" << TgtOcc);
545 if (R->BestSchedule.get() && R->BestSchedule->MaxPressure.getOccupancy(
546 ST, DynamicVGPRBlockSize) >= TgtOcc) {
552 assert(R->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize) >=
557 std::min(FinalOccupancy, RP.getOccupancy(ST, DynamicVGPRBlockSize));
560 MFI->limitOccupancy(FinalOccupancy);
568 const auto TgtOcc =
MFI->getOccupancy();
571 auto MaxPressure =
Regions.front()->MaxPressure;
573 if (!force && R->MaxPressure.less(
MF, MaxPressure, TgtOcc))
581 dbgs() <<
"\nWarning: Pressure becomes worse after minreg!";
582 printSchedRP(dbgs(), R->MaxPressure, RP);
585 if (!force && MaxPressure.less(
MF, RP, TgtOcc))
599 bool TryMaximizeOccupancy) {
602 auto TgtOcc =
MFI->getMinAllowedOccupancy();
603 unsigned DynamicVGPRBlockSize =
MFI->getDynamicVGPRBlockSize();
607 Regions.front()->MaxPressure.getOccupancy(ST, DynamicVGPRBlockSize);
609 bool IsReentry =
false;
610 if (TryMaximizeOccupancy && Occ < TgtOcc) {
615 TgtOcc = std::min(Occ, TgtOcc);
617 "target occupancy = "
620 unsigned FinalOccupancy = std::min(Occ,
MFI->getOccupancy());
628 if (RP.getOccupancy(ST, DynamicVGPRBlockSize) < TgtOcc) {
629 LLVM_DEBUG(
dbgs() <<
"Didn't fit into target occupancy O" << TgtOcc);
630 if (R->BestSchedule.get() && R->BestSchedule->MaxPressure.getOccupancy(
631 ST, DynamicVGPRBlockSize) >= TgtOcc) {
641 std::min(FinalOccupancy, RP.getOccupancy(ST, DynamicVGPRBlockSize));
644 MFI->limitOccupancy(FinalOccupancy);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static LLVM_DUMP_METHOD void printLivenessInfo(raw_ostream &OS, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, const LiveIntervals *LIS)
static MachineInstr * getMachineInstr(MachineInstr *MI)
static LLVM_DUMP_METHOD void printRegion(raw_ostream &OS, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, const LiveIntervals *LIS, unsigned MaxInstNum=std::numeric_limits< unsigned >::max())
This file defines the class GCNIterativeScheduler, which uses an iterative approach to find a best sc...
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
ArrayRef< SUnit * > getBottomRoots() const
ArrayRef< const SUnit * > getTopRoots() const
BuildDAG(const Region &R, GCNIterativeScheduler &_Sch, bool IsReentry=false)
~OverrideLegacyStrategy()
OverrideLegacyStrategy(Region &R, MachineSchedStrategy &OverrideStrategy, GCNIterativeScheduler &_Sch)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
SpecificBumpPtrAllocator< Region > Alloc
void printSchedRP(raw_ostream &OS, const GCNRegPressure &Before, const GCNRegPressure &After) const
void enterRegion(MachineBasicBlock *BB, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned RegionInstrs) override
Initialize the DAG and common scheduler state for a new scheduling region.
void sortRegionsByPressure(unsigned TargetOcc)
std::vector< Region * > Regions
void restoreLivenessFlags(MachineInstr &MI)
void scheduleILP(bool TryMaximizeOccupancy=true)
GCNUpwardRPTracker UPTracker
void swapIGLPMutations(const Region &R, bool IsReentry)
void scheduleBest(Region &R)
MachineSchedContext * Context
GCNIterativeScheduler(MachineSchedContext *C, StrategyKind S)
void printSchedResult(raw_ostream &OS, const Region *R, const GCNRegPressure &RP) const
unsigned tryMaximizeOccupancy(unsigned TargetOcc=std::numeric_limits< unsigned >::max())
void printRegions(raw_ostream &OS) const
@ SCHEDULE_LEGACYMAXOCCUPANCY
void setBestSchedule(Region &R, ScheduleRef Schedule, const GCNRegPressure &MaxRP=GCNRegPressure())
void finalizeSchedule() override
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
void scheduleLegacyMaxOccupancy(bool TryMaximizeOccupancy=true)
std::vector< std::unique_ptr< ScheduleDAGMutation > > SavedMutations
void restoreRegionLivenessFlags(const Region &R)
void schedule() override
Orders nodes according to selected style.
GCNRegPressure getSchedulePressure(const Region &R, Range &&Schedule) const
void scheduleMinReg(bool force=false)
GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End) const
ArrayRef< const SUnit * > ScheduleRef
void scheduleRegion(Region &R, Range &&Schedule, const GCNRegPressure &MaxRP=GCNRegPressure())
const StrategyKind Strategy
std::vector< MachineInstr * > detachSchedule(ScheduleRef Schedule) const
The goal of this scheduling strategy is to maximize kernel occupancy (i.e.
void setTargetOccupancy(unsigned Occ)
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
MachineInstrBundleIterator< MachineInstr > iterator
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
MachineSchedStrategy - Interface to the scheduling algorithm used by ScheduleDAGMI.
List of registers defined and used by a machine instruction.
LLVM_ABI void adjustLaneLiveness(const LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos)
Use liveness information to find out which uses/defs are partially undefined/dead at Pos and adjust t...
LLVM_ABI 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...
bool isIGLPMutationOnly(unsigned Opcode) const
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Scheduling unit. This is a node in the scheduling DAG.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
MachineBasicBlock * BB
The block in which to insert instructions.
MachineInstr * FirstDbgValue
MachineBasicBlock::iterator RegionEnd
The end of the range to be scheduled.
DbgValueVector DbgValues
Remember instruction that precedes DBG_VALUE.
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
unsigned NumRegionInstrs
Instructions in this region (distance(RegionBegin, RegionEnd)).
const MachineFrameInfo & MFI
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
RegPressureTracker RPTracker
std::unique_ptr< MachineSchedStrategy > SchedImpl
void addMutation(std::unique_ptr< ScheduleDAGMutation > Mutation)
Add a postprocessing step to the DAG builder.
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
std::vector< std::unique_ptr< ScheduleDAGMutation > > Mutations
Ordered list of DAG postprocessing steps.
MachineRegisterInfo & MRI
Virtual/real register map.
const TargetInstrInfo * TII
Target instruction information.
const TargetRegisterInfo * TRI
Target processor register info.
MachineFunction & MF
Machine function.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class implements an extremely fast bulk output stream that can only output to a stream.
This is an optimization pass for GlobalISel generic memory operations.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI, Range &&LiveRegs)
std::unique_ptr< ScheduleDAGMutation > createIGroupLPDAGMutation(AMDGPU::SchedulingPhase Phase)
Phase specifes whether or not this is a reentry into the IGroupLPDAGMutation.
IterT skipDebugInstructionsForward(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It until it points to a non-debug instruction or to End and return the resulting iterator.
GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI, const LiveIntervals &LIS)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DWARFExpression::Operation Op
std::vector< const SUnit * > makeGCNILPScheduler(ArrayRef< const SUnit * > BotRoots, const ScheduleDAG &DAG)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
std::vector< const SUnit * > makeMinRegSchedule(ArrayRef< const SUnit * > TopRoots, const ScheduleDAG &DAG)
GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI, const LiveIntervals &LIS)
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
Implement std::hash so that hash_code can be used in STL containers.
GCNRegPressure MaxPressure
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...