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 {
89 :
TII(MF.getSubtarget().getInstrInfo()), MLI(MLI),
AA(
AA), TM(TM),
90 RegClassInfo(RegClassInfo) {}
91 bool run(MachineFunction &MF);
97 PostRASchedulerLegacy() : MachineFunctionPass(ID) {}
99 void getAnalysisUsage(AnalysisUsage &AU)
const override {
107 AU.
addRequired<MachineRegisterClassInfoWrapperPass>();
112 MachineFunctionProperties getRequiredProperties()
const override {
113 return MachineFunctionProperties().setNoVRegs();
116 bool runOnMachineFunction(MachineFunction &Fn)
override;
118char PostRASchedulerLegacy::ID = 0;
123 LatencyPriorityQueue AvailableQueue;
129 std::vector<SUnit *> PendingQueue;
132 ScheduleHazardRecognizer *HazardRec;
135 AntiDepBreaker *AntiDepBreak;
141 std::vector<SUnit *> Sequence;
144 std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
150 unsigned EndIndex = 0;
153 SchedulePostRATDList(
154 MachineFunction &MF, MachineLoopInfo &MLI,
AliasAnalysis *AA,
155 const RegisterClassInfo &,
157 SmallVectorImpl<const TargetRegisterClass *> &CriticalPathRCs);
159 ~SchedulePostRATDList()
override;
164 void startBlock(MachineBasicBlock *BB)
override;
167 void setEndIndex(
unsigned EndIdx) { EndIndex = EndIdx; }
172 unsigned regioninstrs)
override;
175 void exitRegion()
override;
179 void schedule()
override;
186 void Observe(MachineInstr &
MI,
unsigned Count);
190 void finishBlock()
override;
194 void postProcessDAG();
196 void ReleaseSucc(SUnit *SU, SDep *SuccEdge);
197 void ReleaseSuccessors(SUnit *SU);
198 void ScheduleNodeTopDown(SUnit *SU,
unsigned CurCycle);
199 void ListScheduleTopDown();
201 void dumpSchedule()
const;
202 void emitNoop(
unsigned CurCycle);
209 "Post RA top-down list latency scheduler",
false,
false)
214SchedulePostRATDList::SchedulePostRATDList(
222 MF.getSubtarget().getInstrItineraryData();
224 MF.getSubtarget().getInstrInfo()->CreateTargetPostRAHazardRecognizer(
226 MF.getSubtarget().getPostRAMutations(Mutations);
228 assert((AntiDepMode == TargetSubtargetInfo::ANTIDEP_NONE ||
229 MRI.tracksLiveness()) &&
230 "Live-ins must be accurate for anti-dependency breaking");
231 AntiDepBreak = ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_ALL)
233 : ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_CRITICAL)
238SchedulePostRATDList::~SchedulePostRATDList() {
244void SchedulePostRATDList::enterRegion(MachineBasicBlock *bb,
247 unsigned regioninstrs) {
253void SchedulePostRATDList::exitRegion() {
255 dbgs() <<
"*** Final schedule ***\n";
262#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
265 for (
const SUnit *SU : Sequence) {
269 dbgs() <<
"**** NOOP ****\n";
280 return ST.enablePostRAScheduler() &&
281 OptLevel >= ST.getOptLevelToEnablePostRAScheduler();
284bool PostRAScheduler::run(MachineFunction &MF) {
294 ? TargetSubtargetInfo::ANTIDEP_ALL
296 ? TargetSubtargetInfo::ANTIDEP_CRITICAL
297 : TargetSubtargetInfo::ANTIDEP_NONE);
300 Subtarget.getCriticalPathRCs(CriticalPathRCs);
304 SchedulePostRATDList
Scheduler(MF, *MLI, AA, *RegClassInfo, AntiDepMode,
308 for (
auto &
MBB : MF) {
312 static int bbcnt = 0;
315 dbgs() <<
"*** DEBUG scheduling " << MF.getName() <<
":"
328 MachineInstr &
MI = *std::prev(
I);
340 CurrentCount =
Count;
347 assert(
Count == 0 &&
"Instruction count mismatch!");
349 "Instruction count mismatch!");
366bool PostRASchedulerLegacy::runOnMachineFunction(MachineFunction &MF) {
370 MachineLoopInfo *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
371 AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
372 const TargetMachine *TM =
373 &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
374 RegisterClassInfo *RegClassInfo =
375 &getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
376 PostRAScheduler Impl(MF, MLI, AA, TM, RegClassInfo);
391 PostRAScheduler Impl(MF, MLI,
AA, TM, &RegClassInfo);
418void SchedulePostRATDList::schedule() {
425 EndIndex, DbgValues);
437 NumFixedAnti += Broken;
447 ListScheduleTopDown();
454void SchedulePostRATDList::Observe(MachineInstr &
MI,
unsigned Count) {
461void SchedulePostRATDList::finishBlock() {
470void SchedulePostRATDList::postProcessDAG() {
471 for (
auto &M : Mutations)
481void SchedulePostRATDList::ReleaseSucc(SUnit *SU, SDep *SuccEdge) {
482 SUnit *SuccSU = SuccEdge->
getSUnit();
490 dbgs() <<
"*** Scheduling failed! ***\n";
492 dbgs() <<
" has been released too many times!\n";
512 PendingQueue.push_back(SuccSU);
516void SchedulePostRATDList::ReleaseSuccessors(SUnit *SU) {
519 ReleaseSucc(SU, &*
I);
526void SchedulePostRATDList::ScheduleNodeTopDown(SUnit *SU,
unsigned CurCycle) {
532 "Node scheduled above its depth!");
535 ReleaseSuccessors(SU);
541void SchedulePostRATDList::emitNoop(
unsigned CurCycle) {
542 LLVM_DEBUG(
dbgs() <<
"*** Emitting noop in cycle " << CurCycle <<
'\n');
550void SchedulePostRATDList::ListScheduleTopDown() {
551 unsigned CurCycle = 0;
560 ReleaseSuccessors(&EntrySU);
563 for (SUnit &SUnit : SUnits) {
565 if (!SUnit.NumPredsLeft && !SUnit.isAvailable) {
566 AvailableQueue.
push(&SUnit);
567 SUnit.isAvailable =
true;
573 bool CycleHasInsts =
false;
577 std::vector<SUnit*> NotReady;
579 while (!AvailableQueue.
empty() || !PendingQueue.empty()) {
582 unsigned MinDepth = ~0
u;
583 for (
unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
584 if (PendingQueue[i]->getDepth() <= CurCycle) {
585 AvailableQueue.
push(PendingQueue[i]);
586 PendingQueue[i]->isAvailable =
true;
587 PendingQueue[i] = PendingQueue.back();
588 PendingQueue.pop_back();
590 }
else if (PendingQueue[i]->getDepth() < MinDepth)
591 MinDepth = PendingQueue[i]->getDepth();
595 AvailableQueue.
dump(
this));
597 SUnit *FoundSUnit =
nullptr, *NotPreferredSUnit =
nullptr;
598 bool HasNoopHazards =
false;
599 while (!AvailableQueue.
empty()) {
600 SUnit *CurSUnit = AvailableQueue.
pop();
606 if (!NotPreferredSUnit) {
611 NotPreferredSUnit = CurSUnit;
615 FoundSUnit = CurSUnit;
623 NotReady.push_back(CurSUnit);
629 if (NotPreferredSUnit) {
632 dbgs() <<
"*** Will schedule a non-preferred instruction...\n");
633 FoundSUnit = NotPreferredSUnit;
635 AvailableQueue.
push(NotPreferredSUnit);
638 NotPreferredSUnit =
nullptr;
642 if (!NotReady.empty()) {
650 unsigned NumPreNoops = HazardRec->
PreEmitNoops(FoundSUnit);
651 for (
unsigned i = 0; i != NumPreNoops; ++i)
655 ScheduleNodeTopDown(FoundSUnit, CurCycle);
657 CycleHasInsts =
true;
659 LLVM_DEBUG(
dbgs() <<
"*** Max instructions per cycle " << CurCycle
663 CycleHasInsts =
false;
669 }
else if (!HasNoopHazards) {
683 CycleHasInsts =
false;
688 unsigned ScheduledNodes = VerifyScheduledDAG(
false);
691 "The number of nodes scheduled doesn't match the expected number!");
696void SchedulePostRATDList::EmitSchedule() {
697 RegionBegin = RegionEnd;
701 BB->
splice(RegionEnd, BB, FirstDbgValue);
704 for (
unsigned i = 0, e =
Sequence.size(); i != e; i++) {
705 if (SUnit *SU = Sequence[i])
714 RegionBegin = std::prev(RegionEnd);
718 for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
719 DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
720 std::pair<MachineInstr *, MachineInstr *>
P = *std::prev(DI);
721 MachineInstr *DbgValue =
P.first;
723 BB->
splice(++OrigPrivMI, BB, DbgValue);
726 FirstDbgValue =
nullptr;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< int > DebugDiv("agg-antidep-debugdiv", cl::desc("Debug control for aggressive anti-dep breaker"), cl::init(0), cl::Hidden)
static cl::opt< int > DebugMod("agg-antidep-debugmod", cl::desc("Debug control for aggressive anti-dep breaker"), cl::init(0), cl::Hidden)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
const HexagonInstrInfo * TII
PostRA Machine Instruction Scheduler
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(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.
A manager for alias analyses.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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:
virtual void FinishBlock()=0
Finish anti-dep breaking for a basic block.
virtual unsigned BreakAntiDependencies(const std::vector< SUnit > &SUnits, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned InsertPosIndex, DbgValueVector &DbgValues)=0
Identifiy anti-dependencies within a basic-block region and break them by renaming registers.
virtual void Observe(MachineInstr &MI, unsigned Count, unsigned InsertPosIndex)=0
Update liveness information to account for the current instruction, which will not be scheduled.
virtual ~AntiDepBreaker()
virtual void StartBlock(MachineBasicBlock *BB)=0
Initialize anti-dep breaking for a new basic block.
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.
void releaseState() override
void push(SUnit *U) override
LLVM_DUMP_METHOD void dump(ScheduleDAG *DAG) const override
void scheduledNode(SUnit *SU) override
As each node is scheduled, this method is invoked.
void initNodes(std::vector< SUnit > &sunits) override
bool empty() const override
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 '...
MachineInstrBundleIterator< MachineInstr > iterator
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.
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.
Analysis pass that exposes the MachineLoopInfo for a machine function.
LLVM_ABI 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.
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.
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 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).
virtual void Reset()
Reset - This callback is invoked when a new block of instructions is about to be schedule.
virtual void EmitInstruction(SUnit *)
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
virtual bool atIssueLimit() const
atIssueLimit - Return true if no more instructions may be issued in this cycle.
virtual bool ShouldPreferAnother(SUnit *) const
ShouldPreferAnother - This callback may be invoked if getHazardType returns NoHazard.
virtual void EmitNoop()
EmitNoop - This callback is invoked when a noop was added to the instruction stream.
virtual void AdvanceCycle()
AdvanceCycle - This callback is invoked whenever the next top-down instruction to be scheduled cannot...
virtual HazardType getHazardType(SUnit *, int Stalls=0)
getHazardType - Return the hazard type of emitting this node.
virtual unsigned PreEmitNoops(SUnit *)
PreEmitNoops - This callback is invoked prior to emitting an instruction.
void push_all(const std::vector< SUnit * > &Nodes)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
TargetInstrInfo - Interface to description of machine instruction set.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
TargetSubtargetInfo - Generic base class for all target subtargets.
enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode
virtual AntiDepBreakMode getAntiDepBreakMode() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(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)
LLVM_ABI AntiDepBreaker * createAggressiveAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI, TargetSubtargetInfo::RegClassVector &CriticalPathRCs)
LLVM_ABI char & PostRASchedulerID
PostRAScheduler - This pass performs post register allocation scheduling.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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...
LLVM_ABI AntiDepBreaker * createCriticalAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI)
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MCRegisterClass TargetRegisterClass