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"),
101 bool enablePostRAScheduler(
117 std::vector<SUnit*> PendingQueue;
138 SchedulePostRATDList(
144 ~SchedulePostRATDList()
override;
152 void setEndIndex(
unsigned EndIdx) { EndIndex = EndIdx; }
158 unsigned regioninstrs)
override;
161 void exitRegion()
override;
165 void schedule()
override;
176 void finishBlock()
override;
179 void ReleaseSucc(
SUnit *SU,
SDep *SuccEdge);
180 void ReleaseSuccessors(
SUnit *SU);
181 void ScheduleNodeTopDown(
SUnit *SU,
unsigned CurCycle);
182 void ListScheduleTopDown();
184 void dumpSchedule()
const;
185 void emitNoop(
unsigned CurCycle);
192 "Post RA top-down list latency scheduler",
false,
false)
194 SchedulePostRATDList::SchedulePostRATDList(
202 MF.getSubtarget().getInstrItineraryData();
204 MF.getSubtarget().getInstrInfo()->CreateTargetPostRAHazardRecognizer(
208 MRI.tracksLiveness()) &&
209 "Live-ins must be accurate for anti-dependency breaking");
217 SchedulePostRATDList::~SchedulePostRATDList() {
226 unsigned regioninstrs) {
232 void SchedulePostRATDList::exitRegion() {
234 dbgs() <<
"*** Final schedule ***\n";
241 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
243 void SchedulePostRATDList::dumpSchedule()
const {
244 for (
unsigned i = 0, e =
Sequence.size(); i != e; i++) {
248 dbgs() <<
"**** NOOP ****\n";
253 bool PostRAScheduler::enablePostRAScheduler(
273 RegClassInfo.runOnMachineFunction(Fn);
285 if (!enablePostRAScheduler(Fn.
getSubtarget(), PassConfig->getOptLevel(),
286 AntiDepMode, CriticalPathRCs))
301 SchedulePostRATDList
Scheduler(Fn, MLI, AA, RegClassInfo, AntiDepMode,
306 MBB != MBBe; ++MBB) {
310 static int bbcnt = 0;
314 <<
":BB#" << MBB->getNumber() <<
" ***\n";
324 unsigned Count = MBB->size(), CurrentCount = Count;
332 Scheduler.enterRegion(MBB,
I, Current, CurrentCount - Count);
338 CurrentCount = Count;
345 assert(Count == 0 &&
"Instruction count mismatch!");
346 assert((MBB->begin() == Current || CurrentCount != 0) &&
347 "Instruction count mismatch!");
348 Scheduler.enterRegion(MBB, MBB->begin(), Current, CurrentCount);
374 AntiDepBreak->StartBlock(BB);
379 void SchedulePostRATDList::schedule() {
385 AntiDepBreak->BreakAntiDependencies(SUnits, RegionBegin, RegionEnd,
386 EndIndex, DbgValues);
398 NumFixedAnti += Broken;
402 DEBUG(
dbgs() <<
"********** List Scheduling **********\n");
403 DEBUG(
for (
unsigned su = 0, e = SUnits.size(); su != e; ++su)
404 SUnits[su].dumpAll(
this));
406 AvailableQueue.initNodes(SUnits);
407 ListScheduleTopDown();
408 AvailableQueue.releaseState();
414 void SchedulePostRATDList::Observe(
MachineInstr *MI,
unsigned Count) {
416 AntiDepBreak->Observe(MI, Count, EndIndex);
421 void SchedulePostRATDList::finishBlock() {
423 AntiDepBreak->FinishBlock();
435 void SchedulePostRATDList::ReleaseSucc(
SUnit *SU,
SDep *SuccEdge) {
444 dbgs() <<
"*** Scheduling failed! ***\n";
446 dbgs() <<
" has been released too many times!\n";
466 PendingQueue.push_back(SuccSU);
470 void SchedulePostRATDList::ReleaseSuccessors(
SUnit *SU) {
473 ReleaseSucc(SU, &*
I);
480 void SchedulePostRATDList::ScheduleNodeTopDown(
SUnit *SU,
unsigned CurCycle) {
481 DEBUG(
dbgs() <<
"*** Scheduling [" << CurCycle <<
"]: ");
485 assert(CurCycle >= SU->
getDepth() &&
486 "Node scheduled above its depth!");
489 ReleaseSuccessors(SU);
491 AvailableQueue.scheduledNode(SU);
495 void SchedulePostRATDList::emitNoop(
unsigned CurCycle) {
496 DEBUG(
dbgs() <<
"*** Emitting noop in cycle " << CurCycle <<
'\n');
497 HazardRec->EmitNoop();
504 void SchedulePostRATDList::ListScheduleTopDown() {
505 unsigned CurCycle = 0;
514 ReleaseSuccessors(&EntrySU);
517 for (
unsigned i = 0, e = SUnits.size(); i != e; ++i) {
519 if (!SUnits[i].NumPredsLeft && !SUnits[i].
isAvailable) {
520 AvailableQueue.push(&SUnits[i]);
521 SUnits[i].isAvailable =
true;
527 bool CycleHasInsts =
false;
531 std::vector<SUnit*> NotReady;
533 while (!AvailableQueue.empty() || !PendingQueue.empty()) {
536 unsigned MinDepth = ~0u;
537 for (
unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
538 if (PendingQueue[i]->getDepth() <= CurCycle) {
539 AvailableQueue.push(PendingQueue[i]);
540 PendingQueue[i]->isAvailable =
true;
541 PendingQueue[i] = PendingQueue.back();
542 PendingQueue.pop_back();
544 }
else if (PendingQueue[i]->getDepth() < MinDepth)
545 MinDepth = PendingQueue[i]->getDepth();
548 DEBUG(
dbgs() <<
"\n*** Examining Available\n"; AvailableQueue.dump(
this));
550 SUnit *FoundSUnit =
nullptr, *NotPreferredSUnit =
nullptr;
551 bool HasNoopHazards =
false;
552 while (!AvailableQueue.empty()) {
553 SUnit *CurSUnit = AvailableQueue.pop();
556 HazardRec->getHazardType(CurSUnit, 0);
558 if (HazardRec->ShouldPreferAnother(CurSUnit)) {
559 if (!NotPreferredSUnit) {
564 NotPreferredSUnit = CurSUnit;
568 FoundSUnit = CurSUnit;
576 NotReady.push_back(CurSUnit);
582 if (NotPreferredSUnit) {
584 DEBUG(
dbgs() <<
"*** Will schedule a non-preferred instruction...\n");
585 FoundSUnit = NotPreferredSUnit;
587 AvailableQueue.push(NotPreferredSUnit);
590 NotPreferredSUnit =
nullptr;
594 if (!NotReady.empty()) {
595 AvailableQueue.push_all(NotReady);
602 unsigned NumPreNoops = HazardRec->PreEmitNoops(FoundSUnit);
603 for (
unsigned i = 0; i != NumPreNoops; ++i)
607 ScheduleNodeTopDown(FoundSUnit, CurCycle);
608 HazardRec->EmitInstruction(FoundSUnit);
609 CycleHasInsts =
true;
610 if (HazardRec->atIssueLimit()) {
611 DEBUG(
dbgs() <<
"*** Max instructions per cycle " << CurCycle <<
'\n');
612 HazardRec->AdvanceCycle();
614 CycleHasInsts =
false;
618 DEBUG(
dbgs() <<
"*** Finished cycle " << CurCycle <<
'\n');
619 HazardRec->AdvanceCycle();
620 }
else if (!HasNoopHazards) {
623 DEBUG(
dbgs() <<
"*** Stall in cycle " << CurCycle <<
'\n');
624 HazardRec->AdvanceCycle();
634 CycleHasInsts =
false;
639 unsigned ScheduledNodes = VerifyScheduledDAG(
false);
641 for (
unsigned i = 0, e =
Sequence.size(); i != e; ++i)
644 assert(
Sequence.size() - Noops == ScheduledNodes &&
645 "The number of nodes scheduled doesn't match the expected number!");
650 void SchedulePostRATDList::EmitSchedule() {
651 RegionBegin = RegionEnd;
655 BB->
splice(RegionEnd, BB, FirstDbgValue);
658 for (
unsigned i = 0, e =
Sequence.size(); i != e; i++) {
663 TII->insertNoop(*BB, RegionEnd);
668 RegionBegin = std::prev(RegionEnd);
672 for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
673 DI = DbgValues.end(), DE = DbgValues.begin();
DI != DE; --
DI) {
674 std::pair<MachineInstr *, MachineInstr *>
P = *std::prev(DI);
677 BB->
splice(++OrigPrivMI, BB, DbgValue);
680 FirstDbgValue =
nullptr;
const_iterator end(StringRef path)
Get end iterator over path.
virtual void finishBlock()
finishBlock - Clean up after scheduling in the given block.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
STATISTIC(NumFunctions,"Total number of functions")
MachineInstr * getInstr() const
getInstr - Return the representative MachineInstr for this SUnit.
const_iterator begin(StringRef path)
Get begin iterator over path.
static cl::opt< int > DebugDiv("postra-sched-debugdiv", cl::desc("Debug control MBBs that are scheduled"), cl::init(0), cl::Hidden)
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
virtual bool enablePostRAScheduler() const
True if the subtarget should run a scheduler after register allocation.
virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const
virtual void startBlock(MachineBasicBlock *BB)
startBlock - Prepare to perform scheduling in the given block.
virtual AntiDepBreakMode getAntiDepBreakMode() const
AnalysisUsage & addRequired()
bool isSchedulingBoundary(const MachineInstr *MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
unsigned getBundleSize() const
Return the number of instructions inside the MI bundle, excluding the bundle header.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
bool isWeak() const
isWeak - Test if this a weak dependence.
const HexagonInstrInfo * TII
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)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
INITIALIZE_PASS(PostRAScheduler,"post-RA-sched","Post RA top-down list latency scheduler", false, false) SchedulePostRATDList
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Target-Independent Code Generator Pass Configuration Options.
Itinerary data supplied by a subtarget to be used by a target.
virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs)
Initialize the scheduler state for the next scheduling region.
TargetInstrInfo - Interface to description of machine instruction set.
void setDepthToAtLeast(unsigned NewDepth)
setDepthToAtLeast - If NewDepth is greater than this node's depth value, set it to be the new depth v...
SDep - Scheduling dependency.
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
void clearDAG()
clearDAG - clear the DAG state (between regions).
HazardRecognizer - This determines whether or not an instruction can be issued this cycle...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Represent the analysis usage information of a pass.
virtual void exitRegion()
Notify that the scheduler has finished scheduling the current region.
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:
static cl::opt< std::string > EnableAntiDepBreaking("break-anti-dependencies", cl::desc("Break post-RA scheduling anti-dependencies: ""\"critical\", \"all\", or \"none\""), cl::init("none"), cl::Hidden)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
machine Machine Instruction Scheduler
unsigned getDepth() const
getDepth - Return the depth of this node, which is the length of the maximum path up to any node whic...
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)
ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of MachineInstrs. ...
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 '...
bool isCall(QueryType Type=AnyInBundle) const
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
virtual void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const
virtual const TargetInstrInfo * getInstrInfo() const
SmallVector< SDep, 4 > Succs
BasicBlockListType::iterator iterator
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
void dump(const ScheduleDAG *G) const
SUnit - Scheduling unit.
SUnit - Scheduling unit. This is a node in the scheduling DAG.
This file describes how to lower LLVM code to machine code.