20#define DEBUG_TYPE "machine-scheduler"
42#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
49 std::numeric_limits<unsigned>::max()) {
50 auto *BB = Begin->getParent();
52 << BB->getName() <<
":\n";
54 MaxInstNum = std::max(MaxInstNum, 1u);
55 for (;
I !=
End && MaxInstNum; ++
I, --MaxInstNum) {
56 if (!
I->isDebugInstr() && LIS)
63 if (!
I->isDebugInstr() && LIS)
67 if (
End != BB->end()) {
79 auto *
const BB = Begin->getParent();
80 const auto &
MRI = BB->getParent()->getRegInfo();
85 const auto BottomMI =
End == BB->end() ? std::prev(
End) :
End;
94 OS <<
"Region to schedule ";
97 OS <<
"Max RP: " <<
print(R->MaxPressure, &ST);
105 OS <<
"\nAfter scheduling ";
130 auto *
BB = R.Begin->getParent();
131 Sch.BaseClass::startBlock(
BB);
132 Sch.BaseClass::enterRegion(
BB, R.Begin, R.End, R.NumRegionInstrs);
141 Sch.BaseClass::exitRegion();
142 Sch.BaseClass::finishBlock();
156 std::unique_ptr<MachineSchedStrategy> SaveSchedImpl;
166 , SaveMaxRP(R.MaxPressure) {
168 auto *
BB = R.Begin->getParent();
169 Sch.BaseClass::startBlock(
BB);
170 Sch.BaseClass::enterRegion(
BB, R.Begin, R.End, R.NumRegionInstrs);
174 Sch.BaseClass::exitRegion();
175 Sch.BaseClass::finishBlock();
177 Sch.
SchedImpl = std::move(SaveSchedImpl);
184 Sch.BaseClass::schedule();
206 bool shouldTrackPressure()
const override {
return false; }
207 bool shouldTrackLaneMasks()
const override {
return false; }
209 SUnit *pickNode(
bool &IsTopNode)
override {
return nullptr; }
210 void schedNode(
SUnit *SU,
bool IsTopNode)
override {}
211 void releaseTopNode(
SUnit *SU)
override {}
212 void releaseBottomNode(
SUnit *SU)
override {}
233 auto const BBEnd = Begin->getParent()->end();
234 auto const BottomMI =
End == BBEnd ? std::prev(
End) :
End;
238 auto AfterBottomMI = std::next(BottomMI);
239 if (AfterBottomMI == BBEnd ||
246 for (
auto I = BottomMI;
I != Begin; --
I)
252 (
dbgs() <<
"Tracked region ",
260 Range &&Schedule)
const {
261 auto const BBEnd = R.Begin->getParent()->end();
263 if (R.End != BBEnd) {
272 for (
auto I = Schedule.end(),
B = Schedule.begin();
I !=
B;) {
275 return RPTracker.getMaxPressureAndReset();
281 unsigned NumRegionInstrs) {
285 new (
Alloc.Allocate())
286 Region { Begin, End, NumRegionInstrs,
287 getRegionPressure(Begin, End), nullptr });
296 << print(Regions.back()->MaxPressure,
297 &MF.getSubtarget<GCNSubtarget>());
315std::vector<MachineInstr*>
317 std::vector<MachineInstr*> Res;
318 Res.reserve(Schedule.
size() * 2);
324 for (
const auto *SU : Schedule) {
325 Res.push_back(SU->getInstr());
326 const auto &
D = std::find_if(DbgB, DbgE, [SU](
decltype(*DbgB) &
P) {
327 return P.second == SU->getInstr();
330 Res.push_back(
D->first);
338 R.BestSchedule.reset(
343 assert(R.BestSchedule.get() &&
"No schedule specified");
344 scheduleRegion(R, R.BestSchedule->Schedule, R.BestSchedule->MaxPressure);
345 R.BestSchedule.reset();
350template <
typename Range>
358 auto *
BB = R.Begin->getParent();
360 for (
const auto &
I : Schedule) {
365 if (!
MI->isDebugInstr())
368 if (!
MI->isDebugInstr()) {
370 for (
auto &
Op :
MI->all_defs())
371 Op.setIsUndef(
false);
380 Top = std::next(
MI->getIterator());
386 if (!std::is_same_v<
decltype(*Schedule.begin()),
MachineInstr*>) {
394 R.MaxPressure = MaxRP;
401 (SchedMaxRP == RegionMaxRP && (MaxRP.
empty() || SchedMaxRP == MaxRP)) ||
402 (
dbgs() <<
"Max RP mismatch!!!\n"
403 "RP for schedule (calculated): "
404 <<
print(SchedMaxRP, &ST)
405 <<
"RP for schedule (reported): " <<
print(MaxRP, &ST)
406 <<
"RP after scheduling: " <<
print(RegionMaxRP, &ST),
429 const auto Occ =
Regions.front()->MaxPressure.getOccupancy(ST);
430 LLVM_DEBUG(
dbgs() <<
"Trying to improve occupancy, target = " << TargetOcc
431 <<
", current = " << Occ <<
'\n');
433 auto NewOcc = TargetOcc;
435 if (R->MaxPressure.getOccupancy(ST) >= NewOcc)
447 NewOcc = std::min(NewOcc, MaxRP.getOccupancy(ST));
454 <<
", prev occupancy = " << Occ <<
'\n');
457 MFI->increaseOccupancy(
MF, NewOcc);
460 return std::max(NewOcc, Occ);
464 bool TryMaximizeOccupancy) {
467 auto TgtOcc =
MFI->getMinAllowedOccupancy();
470 auto Occ =
Regions.front()->MaxPressure.getOccupancy(ST);
472 if (TryMaximizeOccupancy && Occ < TgtOcc)
477 const int NumPasses = Occ < TgtOcc ? 2 : 1;
479 TgtOcc = std::min(Occ, TgtOcc);
481 "target occupancy = "
484 unsigned FinalOccupancy = std::min(Occ,
MFI->getOccupancy());
486 for (
int I = 0;
I < NumPasses; ++
I) {
497 if (RP.getOccupancy(ST) < TgtOcc) {
498 LLVM_DEBUG(
dbgs() <<
"Didn't fit into target occupancy O" << TgtOcc);
499 if (R->BestSchedule.get() &&
500 R->BestSchedule->MaxPressure.getOccupancy(ST) >= TgtOcc) {
506 assert(R->MaxPressure.getOccupancy(ST) >= TgtOcc);
509 FinalOccupancy = std::min(FinalOccupancy, RP.getOccupancy(ST));
512 MFI->limitOccupancy(FinalOccupancy);
520 const auto TgtOcc =
MFI->getOccupancy();
523 auto MaxPressure =
Regions.front()->MaxPressure;
525 if (!force && R->MaxPressure.less(
MF, MaxPressure, TgtOcc))
533 dbgs() <<
"\nWarning: Pressure becomes worse after minreg!";
534 printSchedRP(dbgs(), R->MaxPressure, RP);
537 if (!force && MaxPressure.less(
MF, RP, TgtOcc))
551 bool TryMaximizeOccupancy) {
554 auto TgtOcc =
MFI->getMinAllowedOccupancy();
557 auto Occ =
Regions.front()->MaxPressure.getOccupancy(ST);
559 if (TryMaximizeOccupancy && Occ < TgtOcc)
562 TgtOcc = std::min(Occ, TgtOcc);
564 "target occupancy = "
567 unsigned FinalOccupancy = std::min(Occ,
MFI->getOccupancy());
575 if (RP.getOccupancy(ST) < TgtOcc) {
576 LLVM_DEBUG(
dbgs() <<
"Didn't fit into target occupancy O" << TgtOcc);
577 if (R->BestSchedule.get() &&
578 R->BestSchedule->MaxPressure.getOccupancy(ST) >= TgtOcc) {
585 FinalOccupancy = std::min(FinalOccupancy, RP.getOccupancy(ST));
588 MFI->limitOccupancy(FinalOccupancy);
unsigned const MachineRegisterInfo * MRI
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#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))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringLiteral > StandardNames)
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)
~OverrideLegacyStrategy()
OverrideLegacyStrategy(Region &R, MachineSchedStrategy &OverrideStrategy, GCNIterativeScheduler &_Sch)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
This class represents an Operation in the Expression.
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
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
void sortRegionsByPressure(unsigned TargetOcc)
std::vector< Region * > Regions
void scheduleILP(bool TryMaximizeOccupancy=true)
GCNUpwardRPTracker UPTracker
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)
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
GCNRegPressure getSchedulePressure(const Region &R, Range &&Schedule) const
void scheduleMinReg(bool force=false)
GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End) const
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.
const MachineInstr * getLastTrackedMI() const
void setTargetOccupancy(unsigned Occ)
GCNRegPressure getMaxPressureAndReset()
void reset(const MachineRegisterInfo &MRI, SlotIndex SI)
reset tracker at the specified slot index SI.
void recede(const MachineInstr &MI)
Move to the state of RP just before the MI .
bool isValid() const
returns whether the tracker's state after receding MI corresponds to reported by LIS.
void handleMove(MachineInstr &MI, bool UpdateFlags=false)
Call this method to notify LiveIntervals that instruction MI has been moved within a basic block.
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
MachineInstr * remove(MachineInstr *I)
Remove the unbundled instruction from the instruction list without deleting it.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
MachineSchedStrategy - Interface to the scheduling algorithm used by ScheduleDAGMI.
void recede(SmallVectorImpl< RegisterMaskPair > *LiveUses=nullptr)
Recede across the previous instruction.
List of registers defined and used by a machine instruction.
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...
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...
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.
ScheduleDAGTopologicalSort Topo
Topo - A topological ordering for SUnits which permits fast IsReachable and similar queries.
void buildSchedGraph(AAResults *AA, RegPressureTracker *RPTracker=nullptr, PressureDiffs *PDiffs=nullptr, LiveIntervals *LIS=nullptr, bool TrackLaneMasks=false)
Builds SUnits for the current region.
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
unsigned NumRegionInstrs
Instructions in this region (distance(RegionBegin, RegionEnd)).
const MachineFrameInfo & MFI
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
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
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
std::unique_ptr< MachineSchedStrategy > SchedImpl
void findRootsAndBiasEdges(SmallVectorImpl< SUnit * > &TopRoots, SmallVectorImpl< SUnit * > &BotRoots)
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
void InitDAGTopologicalSorting()
Creates the initial topological ordering from the DAG to be scheduled.
MachineRegisterInfo & MRI
Virtual/real register map.
std::vector< SUnit > SUnits
The scheduling units.
const TargetRegisterInfo * TRI
Target processor register info.
MachineFunction & MF
Machine function.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
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.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI, Range &&LiveRegs)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI, const LiveIntervals &LIS)
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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)
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
Implement std::hash so that hash_code can be used in STL containers.
const MachineBasicBlock::iterator End
GCNRegPressure MaxPressure
MachineBasicBlock::iterator Begin
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...