23 #include "llvm/Config/llvm-config.h" 32 #include <type_traits> 37 #define DEBUG_TYPE "machine-scheduler" 59 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 67 auto BB = Begin->getParent();
69 << BB->getName() <<
":\n";
71 MaxInstNum =
std::max(MaxInstNum, 1u);
72 for (;
I != End && MaxInstNum; ++
I, --MaxInstNum) {
73 if (!
I->isDebugInstr() && LIS)
80 if (!
I->isDebugInstr() && LIS)
84 if (End != BB->end()) {
96 const auto BB = Begin->getParent();
97 const auto &
MRI = BB->getParent()->getRegInfo();
103 const auto BottomMI = End == BB->end() ? std::prev(End) : End;
113 OS <<
"Region to schedule ";
117 R->MaxPressure.print(OS, &
ST);
125 OS <<
"\nAfter scheduling ";
152 auto BB = R.
Begin->getParent();
153 Sch.BaseClass::startBlock(
BB);
163 Sch.BaseClass::exitRegion();
164 Sch.BaseClass::finishBlock();
178 std::unique_ptr<MachineSchedStrategy> SaveSchedImpl;
188 , SaveMaxRP(R.MaxPressure) {
190 auto BB = R.
Begin->getParent();
191 Sch.BaseClass::startBlock(
BB);
196 Sch.BaseClass::exitRegion();
197 Sch.BaseClass::finishBlock();
199 Sch.
SchedImpl = std::move(SaveSchedImpl);
206 Sch.BaseClass::schedule();
228 bool shouldTrackPressure()
const override {
return false; }
229 bool shouldTrackLaneMasks()
const override {
return false; }
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 {}
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 ||
268 for (
auto I = BottomMI;
I != Begin; --
I)
274 (
dbgs() <<
"Tracked region ",
282 Range &&Schedule)
const {
283 auto const BBEnd = R.
Begin->getParent()->end();
285 if (R.
End != BBEnd) {
292 RPTracker.
reset(*std::prev(BBEnd));
294 for (
auto I = Schedule.end(),
B = Schedule.begin();
I !=
B;) {
305 if (NumRegionInstrs > 2) {
307 new (
Alloc.Allocate())
317 dbgs() <<
"Max RP: ";
318 Regions.back()->MaxPressure.print(
337 std::vector<MachineInstr*>
339 std::vector<MachineInstr*> Res;
340 Res.reserve(Schedule.
size() * 2);
346 for (
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);
372 template <
typename Range>
380 auto BB = R.
Begin->getParent();
382 for (
const auto &
I : Schedule) {
387 if (!
MI->isDebugInstr())
390 if (!
MI->isDebugInstr()) {
392 for (
auto &
Op :
MI->operands())
393 if (
Op.isReg() &&
Op.isDef())
394 Op.setIsUndef(
false);
403 Top = std::next(
MI->getIterator());
409 if (!std::is_same<decltype(*Schedule.begin()),
MachineInstr*>::value) {
423 assert((SchedMaxRP == RegionMaxRP && (MaxRP.
empty() || SchedMaxRP == MaxRP))
424 || (
dbgs() <<
"Max RP mismatch!!!\n" 425 "RP for schedule (calculated): ",
426 SchedMaxRP.print(
dbgs(), &
ST),
427 dbgs() <<
"RP for schedule (reported): ",
429 dbgs() <<
"RP after scheduling: ",
430 RegionMaxRP.print(
dbgs(), &
ST),
454 const auto Occ =
Regions.front()->MaxPressure.getOccupancy(
ST);
455 LLVM_DEBUG(
dbgs() <<
"Trying to improve occupancy, target = " << TargetOcc
456 <<
", current = " << Occ <<
'\n');
458 auto NewOcc = TargetOcc;
460 if (R->MaxPressure.getOccupancy(
ST) >= NewOcc)
472 NewOcc = std::min(NewOcc, MaxRP.getOccupancy(
ST));
479 <<
", prev occupancy = " << Occ <<
'\n');
489 bool TryMaximizeOccupancy) {
495 auto Occ =
Regions.front()->MaxPressure.getOccupancy(
ST);
497 if (TryMaximizeOccupancy && Occ < TgtOcc)
502 const int NumPasses = Occ < TgtOcc ? 2 : 1;
504 TgtOcc = std::min(Occ, TgtOcc);
506 "target occupancy = " 509 unsigned FinalOccupancy = std::min(Occ, MFI->getOccupancy());
511 for (
int I = 0;
I < NumPasses; ++
I) {
522 if (
RP.getOccupancy(
ST) < TgtOcc) {
523 LLVM_DEBUG(
dbgs() <<
"Didn't fit into target occupancy O" << TgtOcc);
524 if (R->BestSchedule.get() &&
525 R->BestSchedule->MaxPressure.getOccupancy(
ST) >= TgtOcc) {
531 assert(R->MaxPressure.getOccupancy(
ST) >= TgtOcc);
534 FinalOccupancy = std::min(FinalOccupancy,
RP.getOccupancy(
ST));
537 MFI->limitOccupancy(FinalOccupancy);
549 auto MaxPressure =
Regions.front()->MaxPressure;
551 if (!force && R->MaxPressure.less(
ST, MaxPressure, TgtOcc))
559 dbgs() <<
"\nWarning: Pressure becomes worse after minreg!";
563 if (!force && MaxPressure.less(
ST, RP, TgtOcc))
577 bool TryMaximizeOccupancy) {
583 auto Occ =
Regions.front()->MaxPressure.getOccupancy(
ST);
585 if (TryMaximizeOccupancy && Occ < TgtOcc)
588 TgtOcc = std::min(Occ, TgtOcc);
590 "target occupancy = " 593 unsigned FinalOccupancy = std::min(Occ, MFI->getOccupancy());
601 if (RP.getOccupancy(
ST) < TgtOcc) {
602 LLVM_DEBUG(
dbgs() <<
"Didn't fit into target occupancy O" << TgtOcc);
603 if (R->BestSchedule.get() &&
604 R->BestSchedule->MaxPressure.getOccupancy(
ST) >= TgtOcc) {
611 FinalOccupancy = std::min(FinalOccupancy, RP.getOccupancy(
ST));
614 MFI->limitOccupancy(FinalOccupancy);
unsigned tryMaximizeOccupancy(unsigned TargetOcc=std::numeric_limits< unsigned >::max())
void enterRegion(MachineBasicBlock *BB, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned RegionInstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
GCNRegPressure getRegionPressure(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End) const
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
AMDGPU specific subclass of TargetSubtarget.
This class represents lattice values for constants.
This is a minimal scheduler strategy.
void sortRegionsByPressure(unsigned TargetOcc)
ScheduleDAGTopologicalSort Topo
Topo - A topological ordering for SUnits which permits fast IsReachable and similar queries...
decltype(MaxPressure) moveMaxPressure()
SpecificBumpPtrAllocator< Region > Alloc
GCNRegPressure MaxPressure
std::vector< Region * > Regions
void setTargetOccupancy(unsigned Occ)
std::vector< MachineInstr * > detachSchedule(ScheduleRef Schedule) const
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&... args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
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
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
MachineFunction & MF
Machine function.
void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker=nullptr, PressureDiffs *PDiffs=nullptr, LiveIntervals *LIS=nullptr, bool TrackLaneMasks=false)
Builds SUnits for the current region.
void printRegions(raw_ostream &OS) const
MachineBasicBlock::iterator RegionEnd
The end of the range to be scheduled.
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MachineBasicBlock::iterator Begin
void finalizeSchedule() override
Allow targets to perform final scheduling actions at the level of the whole MachineFunction.
MachineSchedContext * Context
DbgValueVector DbgValues
Remember instruction that precedes DBG_VALUE.
void InitDAGTopologicalSorting()
Creates the initial topological ordering from the DAG to be scheduled.
void scheduleLegacyMaxOccupancy(bool TryMaximizeOccupancy=true)
void scheduleBest(Region &R)
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def...
void increaseOccupancy(const MachineFunction &MF, unsigned Limit)
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
static LLVM_DUMP_METHOD void printLivenessInfo(raw_ostream &OS, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, const LiveIntervals *LIS)
std::vector< const SUnit * > makeMinRegSchedule(ArrayRef< const SUnit *> TopRoots, const ScheduleDAG &DAG)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI, const LiveIntervals &LIS)
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...
static MachineInstr * getMachineInstr(MachineInstr *MI)
List of registers defined and used by a machine instruction.
bool less(const GCNSubtarget &ST, const GCNRegPressure &O, unsigned MaxOccupancy=std::numeric_limits< unsigned >::max()) const
void printSchedRP(raw_ostream &OS, const GCNRegPressure &Before, const GCNRegPressure &After) const
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
unsigned getMinAllowedOccupancy() const
void reset(const MachineInstr &MI, const LiveRegSet *LiveRegs=nullptr)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
void setBestSchedule(Region &R, ScheduleRef Schedule, const GCNRegPressure &MaxRP=GCNRegPressure())
unsigned const MachineRegisterInfo * MRI
const MachineInstr * getLastTrackedMI() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
unsigned getOccupancy() const
size_t size() const
size - Get the array size.
~OverrideLegacyStrategy()
const unsigned NumRegionInstrs
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
const MachineFrameInfo & MFI
GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI, const LiveIntervals &LIS)
void sort(IteratorTy Start, IteratorTy End)
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...
GCNRegPressure getSchedulePressure(const Region &R, Range &&Schedule) const
ArrayRef< SUnit * > getBottomRoots() const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
OverrideLegacyStrategy(Region &R, MachineSchedStrategy &OverrideStrategy, GCNIterativeScheduler &_Sch)
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
MachineInstr * remove(MachineInstr *I)
Remove the unbundled instruction from the instruction list without deleting it.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
GCNUpwardRPTracker UPTracker
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringRef > StandardNames)
Initialize the set of available library functions based on the specified target triple.
const MachineBasicBlock::iterator End
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())
ArrayRef< const SUnit * > getTopRoots() const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI, Range &&LiveRegs)
Representation of each machine instruction.
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
BuildDAG(const Region &R, GCNIterativeScheduler &_Sch)
const TargetRegisterInfo * TRI
Target processor register info.
void findRootsAndBiasEdges(SmallVectorImpl< SUnit *> &TopRoots, SmallVectorImpl< SUnit *> &BotRoots)
void printSchedResult(raw_ostream &OS, const Region *R, const GCNRegPressure &RP) const
const StrategyKind Strategy
GCNIterativeScheduler(MachineSchedContext *C, StrategyKind S)
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
MachineSchedStrategy - Interface to the scheduling algorithm used by ScheduleDAGMI.
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
void scheduleRegion(Region &R, Range &&Schedule, const GCNRegPressure &MaxRP=GCNRegPressure())
std::vector< const SUnit * > makeGCNILPScheduler(ArrayRef< const SUnit *> BotRoots, const ScheduleDAG &DAG)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void print(raw_ostream &OS, const GCNSubtarget *ST=nullptr) const
void scheduleMinReg(bool force=false)
This class implements an extremely fast bulk output stream that can only output to a stream...
MachineInstr * FirstDbgValue
MachineBasicBlock * BB
The block in which to insert instructions.
void scheduleILP(bool TryMaximizeOccupancy=true)
MachineRegisterInfo & MRI
Virtual/real register map.
std::vector< SUnit > SUnits
The scheduling units.
void recede(const MachineInstr &MI)
RegPressureTracker RPTracker
std::unique_ptr< TentativeSchedule > BestSchedule
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.