36#include "llvm/Config/llvm-config.h"
46#define DEBUG_TYPE "post-RA-sched"
50STATISTIC(NumFixedAnti,
"Number of fixed anti-dependencies");
57 cl::desc(
"Enable scheduling after register allocation"),
61 cl::desc(
"Break post-RA scheduling anti-dependencies: "
62 "\"critical\", \"all\", or \"none\""),
68 cl::desc(
"Debug control MBBs that are scheduled"),
72 cl::desc(
"Debug control MBBs that are scheduled"),
78class PostRAScheduler {
88 :
TII(MF.getSubtarget().getInstrInfo()), MLI(MLI), AA(AA), TM(TM) {}
114char PostRASchedulerLegacy::ID = 0;
125 std::vector<SUnit *> PendingQueue;
140 std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
146 unsigned EndIndex = 0;
149 SchedulePostRATDList(
155 ~SchedulePostRATDList()
override;
163 void setEndIndex(
unsigned EndIdx) { EndIndex = EndIdx; }
168 unsigned regioninstrs)
override;
190 void postProcessDAG();
192 void ReleaseSucc(
SUnit *SU,
SDep *SuccEdge);
193 void ReleaseSuccessors(
SUnit *SU);
194 void ScheduleNodeTopDown(
SUnit *SU,
unsigned CurCycle);
195 void ListScheduleTopDown();
197 void dumpSchedule()
const;
198 void emitNoop(
unsigned CurCycle);
205 "Post RA top-down list latency scheduler",
false,
false)
207SchedulePostRATDList::SchedulePostRATDList(
215 MF.getSubtarget().getInstrItineraryData();
217 MF.getSubtarget().getInstrInfo()->CreateTargetPostRAHazardRecognizer(
219 MF.getSubtarget().getPostRAMutations(Mutations);
221 assert((AntiDepMode == TargetSubtargetInfo::ANTIDEP_NONE ||
222 MRI.tracksLiveness()) &&
223 "Live-ins must be accurate for anti-dependency breaking");
224 AntiDepBreak = ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_ALL)
226 : ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_CRITICAL)
231SchedulePostRATDList::~SchedulePostRATDList() {
240 unsigned regioninstrs) {
246void SchedulePostRATDList::exitRegion() {
248 dbgs() <<
"*** Final schedule ***\n";
255#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
258 for (
const SUnit *SU : Sequence) {
262 dbgs() <<
"**** NOOP ****\n";
273 return ST.enablePostRAScheduler() &&
274 OptLevel >= ST.getOptLevelToEnablePostRAScheduler();
287 ? TargetSubtargetInfo::ANTIDEP_ALL
289 ? TargetSubtargetInfo::ANTIDEP_CRITICAL
290 : TargetSubtargetInfo::ANTIDEP_NONE);
293 Subtarget.getCriticalPathRCs(CriticalPathRCs);
294 RegClassInfo.runOnMachineFunction(MF);
298 SchedulePostRATDList
Scheduler(MF, *MLI, AA, RegClassInfo, AntiDepMode,
302 for (
auto &
MBB : MF) {
306 static int bbcnt = 0;
309 dbgs() <<
"*** DEBUG scheduling " << MF.getName() <<
":"
320 unsigned Count =
MBB.
size(), CurrentCount = Count;
328 Scheduler.enterRegion(&
MBB,
I, Current, CurrentCount - Count);
334 CurrentCount = Count;
339 Count -=
MI.getBundleSize();
341 assert(Count == 0 &&
"Instruction count mismatch!");
343 "Instruction count mismatch!");
364 MachineLoopInfo *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
365 AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
368 PostRAScheduler Impl(MF, MLI, AA, TM);
381 PostRAScheduler Impl(MF, MLI, AA, TM);
382 bool Changed = Impl.run(MF);
403 AntiDepBreak->StartBlock(BB);
408void SchedulePostRATDList::schedule() {
414 AntiDepBreak->BreakAntiDependencies(SUnits, RegionBegin, RegionEnd,
415 EndIndex, DbgValues);
427 NumFixedAnti += Broken;
436 AvailableQueue.initNodes(SUnits);
437 ListScheduleTopDown();
438 AvailableQueue.releaseState();
444void SchedulePostRATDList::Observe(
MachineInstr &
MI,
unsigned Count) {
446 AntiDepBreak->Observe(
MI, Count, EndIndex);
451void SchedulePostRATDList::finishBlock() {
453 AntiDepBreak->FinishBlock();
460void SchedulePostRATDList::postProcessDAG() {
461 for (
auto &M : Mutations)
471void SchedulePostRATDList::ReleaseSucc(
SUnit *SU,
SDep *SuccEdge) {
480 dbgs() <<
"*** Scheduling failed! ***\n";
482 dbgs() <<
" has been released too many times!\n";
502 PendingQueue.push_back(SuccSU);
506void SchedulePostRATDList::ReleaseSuccessors(
SUnit *SU) {
509 ReleaseSucc(SU, &*
I);
516void SchedulePostRATDList::ScheduleNodeTopDown(
SUnit *SU,
unsigned CurCycle) {
522 "Node scheduled above its depth!");
525 ReleaseSuccessors(SU);
527 AvailableQueue.scheduledNode(SU);
531void SchedulePostRATDList::emitNoop(
unsigned CurCycle) {
532 LLVM_DEBUG(
dbgs() <<
"*** Emitting noop in cycle " << CurCycle <<
'\n');
533 HazardRec->EmitNoop();
540void SchedulePostRATDList::ListScheduleTopDown() {
541 unsigned CurCycle = 0;
550 ReleaseSuccessors(&EntrySU);
556 AvailableQueue.push(&
SUnit);
563 bool CycleHasInsts =
false;
567 std::vector<SUnit*> NotReady;
569 while (!AvailableQueue.empty() || !PendingQueue.empty()) {
572 unsigned MinDepth = ~0
u;
573 for (
unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
574 if (PendingQueue[i]->getDepth() <= CurCycle) {
575 AvailableQueue.push(PendingQueue[i]);
576 PendingQueue[i]->isAvailable =
true;
577 PendingQueue[i] = PendingQueue.back();
578 PendingQueue.pop_back();
580 }
else if (PendingQueue[i]->getDepth() < MinDepth)
581 MinDepth = PendingQueue[i]->getDepth();
585 AvailableQueue.dump(
this));
587 SUnit *FoundSUnit =
nullptr, *NotPreferredSUnit =
nullptr;
588 bool HasNoopHazards =
false;
589 while (!AvailableQueue.empty()) {
590 SUnit *CurSUnit = AvailableQueue.pop();
593 HazardRec->getHazardType(CurSUnit, 0);
595 if (HazardRec->ShouldPreferAnother(CurSUnit)) {
596 if (!NotPreferredSUnit) {
601 NotPreferredSUnit = CurSUnit;
605 FoundSUnit = CurSUnit;
613 NotReady.push_back(CurSUnit);
619 if (NotPreferredSUnit) {
622 dbgs() <<
"*** Will schedule a non-preferred instruction...\n");
623 FoundSUnit = NotPreferredSUnit;
625 AvailableQueue.push(NotPreferredSUnit);
628 NotPreferredSUnit =
nullptr;
632 if (!NotReady.empty()) {
633 AvailableQueue.push_all(NotReady);
640 unsigned NumPreNoops = HazardRec->PreEmitNoops(FoundSUnit);
641 for (
unsigned i = 0; i != NumPreNoops; ++i)
645 ScheduleNodeTopDown(FoundSUnit, CurCycle);
646 HazardRec->EmitInstruction(FoundSUnit);
647 CycleHasInsts =
true;
648 if (HazardRec->atIssueLimit()) {
649 LLVM_DEBUG(
dbgs() <<
"*** Max instructions per cycle " << CurCycle
651 HazardRec->AdvanceCycle();
653 CycleHasInsts =
false;
658 HazardRec->AdvanceCycle();
659 }
else if (!HasNoopHazards) {
663 HazardRec->AdvanceCycle();
673 CycleHasInsts =
false;
678 unsigned ScheduledNodes = VerifyScheduledDAG(
false);
681 "The number of nodes scheduled doesn't match the expected number!");
686void SchedulePostRATDList::EmitSchedule() {
687 RegionBegin = RegionEnd;
691 BB->
splice(RegionEnd, BB, FirstDbgValue);
694 for (
unsigned i = 0, e =
Sequence.size(); i != e; i++) {
695 if (
SUnit *SU = Sequence[i])
704 RegionBegin = std::prev(RegionEnd);
708 for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
709 DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
710 std::pair<MachineInstr *, MachineInstr *>
P = *std::prev(DI);
716 FirstDbgValue =
nullptr;
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
const HexagonInstrInfo * TII
Machine Instruction Scheduler
FunctionAnalysisManager FAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static cl::opt< int > DebugDiv("postra-sched-debugdiv", cl::desc("Debug control MBBs that are scheduled"), cl::init(0), cl::Hidden)
static cl::opt< bool > EnablePostRAScheduler("post-RA-scheduler", cl::desc("Enable scheduling after register allocation"), cl::init(false), cl::Hidden)
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)
static bool enablePostRAScheduler(const TargetSubtargetInfo &ST, CodeGenOptLevel OptLevel)
static cl::opt< int > DebugMod("postra-sched-debugmod", cl::desc("Debug control MBBs that are scheduled"), cl::init(0), cl::Hidden)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Target-Independent Code Generator Pass Configuration Options pass.
Class recording the (high level) value of a variable.
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
A private abstract base class describing the concept of an individual alias analysis implementation.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
This class works in conjunction with the post-RA scheduler to rename registers to break register anti...
virtual ~AntiDepBreaker()
Represents analyses that only rely on functions' control flow.
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
Insert a noop into the instruction stream at the specified point.
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
Test if the given instruction should be considered a scheduling boundary.
Itinerary data supplied by a subtarget to be used by a target.
An RAII based helper class to modify MachineFunctionProperties when running pass.
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 '...
Analysis pass which computes a MachineDominatorTree.
Analysis pass which computes a MachineDominatorTree.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Analysis pass that exposes the MachineLoopInfo for a machine function.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
bool isWeak() const
Tests if this a weak dependence.
Scheduling unit. This is a node in the scheduling DAG.
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...
bool isScheduled
True once scheduled.
bool isAvailable
True once available.
SmallVector< SDep, 4 > Succs
All sunit successors.
SmallVectorImpl< SDep >::iterator succ_iterator
LLVM_ABI void setDepthToAtLeast(unsigned NewDepth)
If NewDepth is greater than this node's depth value, sets it to be the new depth value.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
A ScheduleDAG for scheduling lists of MachineInstr.
virtual void finishBlock()
Cleans up after scheduling in the given block.
virtual void startBlock(MachineBasicBlock *BB)
Prepares to perform scheduling in the given block.
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
virtual void schedule()=0
Orders nodes according to selected style.
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.
void clearDAG()
Clears the DAG state (between regions).
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
Primary interface to the complete machine description for the target machine.
Target-Independent Code Generator Pass Configuration Options.
TargetSubtargetInfo - Generic base class for all target subtargets.
enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode
virtual AntiDepBreakMode getAntiDepBreakMode() const
unsigned getPosition() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
AntiDepBreaker * createAggressiveAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI, TargetSubtargetInfo::RegClassVector &CriticalPathRCs)
LLVM_ABI char & PostRASchedulerID
PostRAScheduler - This pass performs post register allocation scheduling.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CodeGenOptLevel
Code generation optimization level.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
AntiDepBreaker * createCriticalAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI)
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.