41 #include "llvm/Config/llvm-config.h" 48 #define DEBUG_TYPE "post-RA-sched" 50 STATISTIC(NumNoops,
"Number of noops inserted");
51 STATISTIC(NumStalls,
"Number of pipeline stalls");
52 STATISTIC(NumFixedAnti,
"Number of fixed anti-dependencies");
59 cl::desc(
"Enable scheduling after register allocation"),
63 cl::desc(
"Break post-RA scheduling anti-dependencies: " 64 "\"critical\", \"all\", or \"none\""),
70 cl::desc(
"Debug control MBBs that are scheduled"),
74 cl::desc(
"Debug control MBBs that are scheduled"),
107 bool enablePostRAScheduler(
123 std::vector<SUnit*> PendingQueue;
138 std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
147 SchedulePostRATDList(
153 ~SchedulePostRATDList()
override;
161 void setEndIndex(
unsigned EndIdx) { EndIndex = EndIdx; }
167 unsigned regioninstrs)
override;
170 void exitRegion()
override;
174 void schedule()
override;
185 void finishBlock()
override;
189 void postprocessDAG();
191 void ReleaseSucc(
SUnit *SU,
SDep *SuccEdge);
192 void ReleaseSuccessors(
SUnit *SU);
193 void ScheduleNodeTopDown(
SUnit *SU,
unsigned CurCycle);
194 void ListScheduleTopDown();
196 void dumpSchedule()
const;
197 void emitNoop(
unsigned CurCycle);
204 "Post RA top-down list latency scheduler",
false,
false)
206 SchedulePostRATDList::SchedulePostRATDList(
214 MF.getSubtarget().getInstrItineraryData();
216 MF.getSubtarget().getInstrInfo()->CreateTargetPostRAHazardRecognizer(
218 MF.getSubtarget().getPostRAMutations(Mutations);
220 assert((AntiDepMode == TargetSubtargetInfo::ANTIDEP_NONE ||
221 MRI.tracksLiveness()) &&
222 "Live-ins must be accurate for anti-dependency breaking");
224 ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_ALL) ?
226 ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_CRITICAL) ?
230 SchedulePostRATDList::~SchedulePostRATDList() {
239 unsigned regioninstrs) {
245 void SchedulePostRATDList::exitRegion() {
247 dbgs() <<
"*** Final schedule ***\n";
254 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 257 for (
unsigned i = 0, e =
Sequence.size(); i != e; i++) {
261 dbgs() <<
"**** NOOP ****\n";
266 bool PostRAScheduler::enablePostRAScheduler(
288 AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
291 RegClassInfo.runOnMachineFunction(Fn);
294 TargetSubtargetInfo::ANTIDEP_NONE;
300 AntiDepMode, CriticalPathRCs))
306 ? TargetSubtargetInfo::ANTIDEP_ALL
308 ? TargetSubtargetInfo::ANTIDEP_CRITICAL
309 : TargetSubtargetInfo::ANTIDEP_NONE);
314 SchedulePostRATDList
Scheduler(Fn, MLI, AA, RegClassInfo, AntiDepMode,
318 for (
auto &MBB : Fn) {
322 static int bbcnt = 0;
325 dbgs() <<
"*** DEBUG scheduling " << Fn.getName() <<
":" 331 Scheduler.startBlock(&MBB);
336 unsigned Count = MBB.size(), CurrentCount = Count;
344 Scheduler.enterRegion(&MBB,
I, Current, CurrentCount - Count);
345 Scheduler.setEndIndex(CurrentCount);
346 Scheduler.schedule();
347 Scheduler.exitRegion();
348 Scheduler.EmitSchedule();
350 CurrentCount = Count;
351 Scheduler.Observe(MI, CurrentCount);
357 assert(Count == 0 &&
"Instruction count mismatch!");
358 assert((MBB.begin() == Current || CurrentCount != 0) &&
359 "Instruction count mismatch!");
360 Scheduler.enterRegion(&MBB, MBB.begin(), Current, CurrentCount);
361 Scheduler.setEndIndex(CurrentCount);
362 Scheduler.schedule();
363 Scheduler.exitRegion();
364 Scheduler.EmitSchedule();
367 Scheduler.finishBlock();
370 Scheduler.fixupKills(MBB);
386 AntiDepBreak->StartBlock(BB);
391 void SchedulePostRATDList::schedule() {
397 AntiDepBreak->BreakAntiDependencies(SUnits, RegionBegin, RegionEnd,
398 EndIndex, DbgValues);
410 NumFixedAnti += Broken;
419 AvailableQueue.initNodes(SUnits);
420 ListScheduleTopDown();
421 AvailableQueue.releaseState();
427 void SchedulePostRATDList::Observe(
MachineInstr &
MI,
unsigned Count) {
429 AntiDepBreak->Observe(MI, Count, EndIndex);
434 void SchedulePostRATDList::finishBlock() {
436 AntiDepBreak->FinishBlock();
443 void SchedulePostRATDList::postprocessDAG() {
444 for (
auto &M : Mutations)
454 void SchedulePostRATDList::ReleaseSucc(
SUnit *SU,
SDep *SuccEdge) {
463 dbgs() <<
"*** Scheduling failed! ***\n";
465 dbgs() <<
" has been released too many times!\n";
485 PendingQueue.push_back(SuccSU);
489 void SchedulePostRATDList::ReleaseSuccessors(
SUnit *SU) {
492 ReleaseSucc(SU, &*
I);
499 void SchedulePostRATDList::ScheduleNodeTopDown(
SUnit *SU,
unsigned CurCycle) {
505 "Node scheduled above its depth!");
508 ReleaseSuccessors(SU);
510 AvailableQueue.scheduledNode(SU);
514 void SchedulePostRATDList::emitNoop(
unsigned CurCycle) {
515 LLVM_DEBUG(
dbgs() <<
"*** Emitting noop in cycle " << CurCycle <<
'\n');
516 HazardRec->EmitNoop();
523 void SchedulePostRATDList::ListScheduleTopDown() {
524 unsigned CurCycle = 0;
533 ReleaseSuccessors(&EntrySU);
536 for (
unsigned i = 0, e = SUnits.size(); i != e; ++i) {
538 if (!SUnits[i].NumPredsLeft && !SUnits[i].
isAvailable) {
539 AvailableQueue.push(&SUnits[i]);
540 SUnits[i].isAvailable =
true;
546 bool CycleHasInsts =
false;
550 std::vector<SUnit*> NotReady;
552 while (!AvailableQueue.empty() || !PendingQueue.empty()) {
555 unsigned MinDepth = ~0u;
556 for (
unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
557 if (PendingQueue[i]->getDepth() <= CurCycle) {
558 AvailableQueue.push(PendingQueue[i]);
559 PendingQueue[i]->isAvailable =
true;
560 PendingQueue[i] = PendingQueue.back();
561 PendingQueue.pop_back();
563 }
else if (PendingQueue[i]->getDepth() < MinDepth)
564 MinDepth = PendingQueue[i]->getDepth();
568 AvailableQueue.dump(
this));
570 SUnit *FoundSUnit =
nullptr, *NotPreferredSUnit =
nullptr;
571 bool HasNoopHazards =
false;
572 while (!AvailableQueue.empty()) {
573 SUnit *CurSUnit = AvailableQueue.pop();
576 HazardRec->getHazardType(CurSUnit, 0);
578 if (HazardRec->ShouldPreferAnother(CurSUnit)) {
579 if (!NotPreferredSUnit) {
584 NotPreferredSUnit = CurSUnit;
588 FoundSUnit = CurSUnit;
596 NotReady.push_back(CurSUnit);
602 if (NotPreferredSUnit) {
605 dbgs() <<
"*** Will schedule a non-preferred instruction...\n");
606 FoundSUnit = NotPreferredSUnit;
608 AvailableQueue.push(NotPreferredSUnit);
611 NotPreferredSUnit =
nullptr;
615 if (!NotReady.empty()) {
616 AvailableQueue.push_all(NotReady);
623 unsigned NumPreNoops = HazardRec->PreEmitNoops(FoundSUnit);
624 for (
unsigned i = 0; i != NumPreNoops; ++i)
628 ScheduleNodeTopDown(FoundSUnit, CurCycle);
629 HazardRec->EmitInstruction(FoundSUnit);
630 CycleHasInsts =
true;
631 if (HazardRec->atIssueLimit()) {
632 LLVM_DEBUG(
dbgs() <<
"*** Max instructions per cycle " << CurCycle
634 HazardRec->AdvanceCycle();
636 CycleHasInsts =
false;
641 HazardRec->AdvanceCycle();
642 }
else if (!HasNoopHazards) {
646 HazardRec->AdvanceCycle();
656 CycleHasInsts =
false;
661 unsigned ScheduledNodes = VerifyScheduledDAG(
false);
663 for (
unsigned i = 0, e =
Sequence.size(); i != e; ++i)
667 "The number of nodes scheduled doesn't match the expected number!");
672 void SchedulePostRATDList::EmitSchedule() {
673 RegionBegin = RegionEnd;
677 BB->
splice(RegionEnd, BB, FirstDbgValue);
680 for (
unsigned i = 0, e =
Sequence.size(); i != e; i++) {
690 RegionBegin = std::prev(RegionEnd);
694 for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
695 DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
696 std::pair<MachineInstr *, MachineInstr *>
P = *std::prev(DI);
699 BB->
splice(++OrigPrivMI, BB, DbgValue);
702 FirstDbgValue =
nullptr;
virtual void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const
const_iterator end(StringRef path)
Get end iterator over path.
virtual void finishBlock()
Cleans up after scheduling in the given block.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
bool isCall(QueryType Type=AnyInBundle) const
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
This class represents lattice values for constants.
unsigned getDepth() const
Returns the depth of this node, which is the length of the maximum path up to any node which has no p...
static cl::opt< int > DebugDiv("postra-sched-debugdiv", cl::desc("Debug control MBBs that are scheduled"), cl::init(0), cl::Hidden)
STATISTIC(NumFunctions, "Total number of functions")
SmallVectorImpl< SDep >::iterator succ_iterator
CodeGenOpt::Level getOptLevel() const
virtual void startBlock(MachineBasicBlock *BB)
Prepares to perform scheduling in the given block.
bool isScheduled
True once scheduled.
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
Insert a noop into the instruction stream at the specified point.
AnalysisUsage & addRequired()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
This class works in conjunction with the post-RA scheduler to rename registers to break register anti...
static cl::opt< bool > EnablePostRAScheduler("post-RA-scheduler", cl::desc("Enable scheduling after register allocation"), cl::init(false), cl::Hidden)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Target-Independent Code Generator Pass Configuration Options.
virtual AntiDepBreakMode getAntiDepBreakMode() const
Itinerary data supplied by a subtarget to be used by a target.
unsigned NumPredsLeft
of preds not scheduled.
virtual const TargetInstrInfo * getInstrInfo() const
virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs)
Initialize the DAG and common scheduler state for a new scheduling region.
TargetInstrInfo - Interface to description of machine instruction set.
void setDepthToAtLeast(unsigned NewDepth)
If NewDepth is greater than this node's depth value, sets it to be the new depth value.
initializer< Ty > init(const Ty &Val)
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
unsigned const MachineRegisterInfo * MRI
void clearDAG()
Clears the DAG state (between regions).
HazardRecognizer - This determines whether or not an instruction can be issued this cycle...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
INITIALIZE_PASS(PostRAScheduler, DEBUG_TYPE, "Post RA top-down list latency scheduler", false, false) SchedulePostRATDList
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode
Represent the analysis usage information of a pass.
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
unsigned getBundleSize() const
Return the number of instructions inside the MI bundle, excluding the bundle header.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned WeakPredsLeft
of weak preds not scheduled.
char & PostRASchedulerID
createPostRAScheduler - This pass performs post register allocation scheduling.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
void setPreservesCFG()
This function should be called by the pass, iff they do not:
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
Test if the given instruction should be considered a scheduling boundary.
virtual void Observe(MachineInstr &MI, unsigned Count, unsigned InsertPosIndex)=0
Update liveness information to account for the current instruction, which will not be scheduled...
MachineFunctionProperties & set(Property P)
TargetSubtargetInfo - Generic base class for all target subtargets.
static cl::opt< int > DebugMod("postra-sched-debugmod", cl::desc("Debug control MBBs that are scheduled"), cl::init(0), cl::Hidden)
A ScheduleDAG for scheduling lists of MachineInstr.
Representation of each machine instruction.
virtual ~AntiDepBreaker()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
static cl::opt< std::string > EnableAntiDepBreaking("break-anti-dependencies", cl::desc("Break post-RA scheduling anti-dependencies: " "\ritical\ \ll\ or \one\), cl::init("none"), cl::Hidden)
virtual bool enablePostRAScheduler() const
True if the subtarget should run a scheduler after register allocation.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SmallVector< SDep, 4 > Succs
All sunit successors.
bool isWeak() const
Tests if this a weak dependence.
Machine Instruction Scheduler
virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
Properties which a MachineFunction may have at a given point in time.
Scheduling unit. This is a node in the scheduling DAG.
This file describes how to lower LLVM code to machine code.