xref: /src/contrib/llvm-project/llvm/lib/CodeGen/PostRASchedulerList.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1009b1c42SEd Schouten //===----- SchedulePostRAList.cpp - list scheduler ------------------------===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // This implements a top-down list scheduler, using standard algorithms.
10009b1c42SEd Schouten // The basic approach uses a priority queue of available nodes to schedule.
11009b1c42SEd Schouten // One at a time, nodes are taken from the priority queue (thus in priority
12009b1c42SEd Schouten // order), checked for legality to schedule, and emitted if legal.
13009b1c42SEd Schouten //
14009b1c42SEd Schouten // Nodes may not be legal to schedule either due to structural hazards (e.g.
15009b1c42SEd Schouten // pipeline or resource constraints) or because an input to the instruction has
16009b1c42SEd Schouten // not completed execution.
17009b1c42SEd Schouten //
18009b1c42SEd Schouten //===----------------------------------------------------------------------===//
19009b1c42SEd Schouten 
204a16efa3SDimitry Andric #include "llvm/ADT/Statistic.h"
214a16efa3SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
22cfca06d7SDimitry Andric #include "llvm/CodeGen/AntiDepBreaker.h"
23009b1c42SEd Schouten #include "llvm/CodeGen/LatencyPriorityQueue.h"
24009b1c42SEd Schouten #include "llvm/CodeGen/MachineDominators.h"
25009b1c42SEd Schouten #include "llvm/CodeGen/MachineFunctionPass.h"
26009b1c42SEd Schouten #include "llvm/CodeGen/MachineLoopInfo.h"
27009b1c42SEd Schouten #include "llvm/CodeGen/MachineRegisterInfo.h"
2858b69754SDimitry Andric #include "llvm/CodeGen/RegisterClassInfo.h"
2963faed5bSDimitry Andric #include "llvm/CodeGen/ScheduleDAGInstrs.h"
30145449b1SDimitry Andric #include "llvm/CodeGen/ScheduleDAGMutation.h"
31009b1c42SEd Schouten #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
32044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
3301095a5dSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
34044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
35eb11fae6SDimitry Andric #include "llvm/Config/llvm-config.h"
36706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
37145449b1SDimitry Andric #include "llvm/Pass.h"
3836bf506aSRoman Divacky #include "llvm/Support/CommandLine.h"
39009b1c42SEd Schouten #include "llvm/Support/Debug.h"
4059850d08SRoman Divacky #include "llvm/Support/ErrorHandling.h"
4159850d08SRoman Divacky #include "llvm/Support/raw_ostream.h"
42009b1c42SEd Schouten using namespace llvm;
43009b1c42SEd Schouten 
445ca98fd9SDimitry Andric #define DEBUG_TYPE "post-RA-sched"
455ca98fd9SDimitry Andric 
46009b1c42SEd Schouten STATISTIC(NumNoops, "Number of noops inserted");
47009b1c42SEd Schouten STATISTIC(NumStalls, "Number of pipeline stalls");
4836bf506aSRoman Divacky STATISTIC(NumFixedAnti, "Number of fixed anti-dependencies");
49009b1c42SEd Schouten 
5059850d08SRoman Divacky // Post-RA scheduling is enabled with
51411bd29eSDimitry Andric // TargetSubtargetInfo.enablePostRAScheduler(). This flag can be used to
5259850d08SRoman Divacky // override the target.
5359850d08SRoman Divacky static cl::opt<bool>
5459850d08SRoman Divacky EnablePostRAScheduler("post-RA-scheduler",
5559850d08SRoman Divacky                        cl::desc("Enable scheduling after register allocation"),
5659850d08SRoman Divacky                        cl::init(false), cl::Hidden);
5736bf506aSRoman Divacky static cl::opt<std::string>
58009b1c42SEd Schouten EnableAntiDepBreaking("break-anti-dependencies",
5936bf506aSRoman Divacky                       cl::desc("Break post-RA scheduling anti-dependencies: "
6036bf506aSRoman Divacky                                "\"critical\", \"all\", or \"none\""),
6136bf506aSRoman Divacky                       cl::init("none"), cl::Hidden);
62009b1c42SEd Schouten 
6359850d08SRoman Divacky // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod
6459850d08SRoman Divacky static cl::opt<int>
6559850d08SRoman Divacky DebugDiv("postra-sched-debugdiv",
6659850d08SRoman Divacky                       cl::desc("Debug control MBBs that are scheduled"),
6759850d08SRoman Divacky                       cl::init(0), cl::Hidden);
6859850d08SRoman Divacky static cl::opt<int>
6959850d08SRoman Divacky DebugMod("postra-sched-debugmod",
7059850d08SRoman Divacky                       cl::desc("Debug control MBBs that are scheduled"),
7159850d08SRoman Divacky                       cl::init(0), cl::Hidden);
7259850d08SRoman Divacky 
73145449b1SDimitry Andric AntiDepBreaker::~AntiDepBreaker() = default;
7436bf506aSRoman Divacky 
75009b1c42SEd Schouten namespace {
7636bf506aSRoman Divacky   class PostRAScheduler : public MachineFunctionPass {
77706b4fc4SDimitry Andric     const TargetInstrInfo *TII = nullptr;
78411bd29eSDimitry Andric     RegisterClassInfo RegClassInfo;
7959850d08SRoman Divacky 
80009b1c42SEd Schouten   public:
81009b1c42SEd Schouten     static char ID;
PostRAScheduler()8263faed5bSDimitry Andric     PostRAScheduler() : MachineFunctionPass(ID) {}
83009b1c42SEd Schouten 
getAnalysisUsage(AnalysisUsage & AU) const845ca98fd9SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
8559850d08SRoman Divacky       AU.setPreservesCFG();
86dd58ef01SDimitry Andric       AU.addRequired<AAResultsWrapperPass>();
8763faed5bSDimitry Andric       AU.addRequired<TargetPassConfig>();
88ac9a064cSDimitry Andric       AU.addRequired<MachineDominatorTreeWrapperPass>();
89ac9a064cSDimitry Andric       AU.addPreserved<MachineDominatorTreeWrapperPass>();
90ac9a064cSDimitry Andric       AU.addRequired<MachineLoopInfoWrapperPass>();
91ac9a064cSDimitry Andric       AU.addPreserved<MachineLoopInfoWrapperPass>();
92009b1c42SEd Schouten       MachineFunctionPass::getAnalysisUsage(AU);
93009b1c42SEd Schouten     }
94009b1c42SEd Schouten 
getRequiredProperties() const9501095a5dSDimitry Andric     MachineFunctionProperties getRequiredProperties() const override {
9601095a5dSDimitry Andric       return MachineFunctionProperties().set(
97b915e9e0SDimitry Andric           MachineFunctionProperties::Property::NoVRegs);
9801095a5dSDimitry Andric     }
9901095a5dSDimitry Andric 
1005ca98fd9SDimitry Andric     bool runOnMachineFunction(MachineFunction &Fn) override;
1015ca98fd9SDimitry Andric 
10201095a5dSDimitry Andric   private:
1035ca98fd9SDimitry Andric     bool enablePostRAScheduler(
104b1c73532SDimitry Andric         const TargetSubtargetInfo &ST, CodeGenOptLevel OptLevel,
1055ca98fd9SDimitry Andric         TargetSubtargetInfo::AntiDepBreakMode &Mode,
1065ca98fd9SDimitry Andric         TargetSubtargetInfo::RegClassVector &CriticalPathRCs) const;
107009b1c42SEd Schouten   };
108009b1c42SEd Schouten   char PostRAScheduler::ID = 0;
109009b1c42SEd Schouten 
11036bf506aSRoman Divacky   class SchedulePostRATDList : public ScheduleDAGInstrs {
111009b1c42SEd Schouten     /// AvailableQueue - The priority queue to use for the available SUnits.
112009b1c42SEd Schouten     ///
113009b1c42SEd Schouten     LatencyPriorityQueue AvailableQueue;
114009b1c42SEd Schouten 
115009b1c42SEd Schouten     /// PendingQueue - This contains all of the instructions whose operands have
116009b1c42SEd Schouten     /// been issued, but their results are not ready yet (due to the latency of
117009b1c42SEd Schouten     /// the operation).  Once the operands becomes available, the instruction is
118009b1c42SEd Schouten     /// added to the AvailableQueue.
119009b1c42SEd Schouten     std::vector<SUnit*> PendingQueue;
120009b1c42SEd Schouten 
121009b1c42SEd Schouten     /// HazardRec - The hazard recognizer to use.
122009b1c42SEd Schouten     ScheduleHazardRecognizer *HazardRec;
123009b1c42SEd Schouten 
12436bf506aSRoman Divacky     /// AntiDepBreak - Anti-dependence breaking object, or NULL if none
12536bf506aSRoman Divacky     AntiDepBreaker *AntiDepBreak;
12636bf506aSRoman Divacky 
12759850d08SRoman Divacky     /// AA - AliasAnalysis for making memory reference queries.
12859850d08SRoman Divacky     AliasAnalysis *AA;
12959850d08SRoman Divacky 
13063faed5bSDimitry Andric     /// The schedule. Null SUnit*'s represent noop instructions.
13163faed5bSDimitry Andric     std::vector<SUnit*> Sequence;
132009b1c42SEd Schouten 
13301095a5dSDimitry Andric     /// Ordered list of DAG postprocessing steps.
13401095a5dSDimitry Andric     std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
13501095a5dSDimitry Andric 
136f8af5cf6SDimitry Andric     /// The index in BB of RegionEnd.
137f8af5cf6SDimitry Andric     ///
138f8af5cf6SDimitry Andric     /// This is the instruction number from the top of the current block, not
139f8af5cf6SDimitry Andric     /// the SlotIndex. It is only used by the AntiDepBreaker.
140ecbca9f5SDimitry Andric     unsigned EndIndex = 0;
141f8af5cf6SDimitry Andric 
142009b1c42SEd Schouten   public:
143cf099d11SDimitry Andric     SchedulePostRATDList(
14467c32a98SDimitry Andric         MachineFunction &MF, MachineLoopInfo &MLI, AliasAnalysis *AA,
14567c32a98SDimitry Andric         const RegisterClassInfo &,
146411bd29eSDimitry Andric         TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,
14763faed5bSDimitry Andric         SmallVectorImpl<const TargetRegisterClass *> &CriticalPathRCs);
148009b1c42SEd Schouten 
1495a5ac124SDimitry Andric     ~SchedulePostRATDList() override;
150009b1c42SEd Schouten 
15163faed5bSDimitry Andric     /// startBlock - Initialize register live-range state for scheduling in
152009b1c42SEd Schouten     /// this block.
153009b1c42SEd Schouten     ///
1545ca98fd9SDimitry Andric     void startBlock(MachineBasicBlock *BB) override;
15563faed5bSDimitry Andric 
156f8af5cf6SDimitry Andric     // Set the index of RegionEnd within the current BB.
setEndIndex(unsigned EndIdx)157f8af5cf6SDimitry Andric     void setEndIndex(unsigned EndIdx) { EndIndex = EndIdx; }
158f8af5cf6SDimitry Andric 
15963faed5bSDimitry Andric     /// Initialize the scheduler state for the next scheduling region.
1605ca98fd9SDimitry Andric     void enterRegion(MachineBasicBlock *bb,
16163faed5bSDimitry Andric                      MachineBasicBlock::iterator begin,
16263faed5bSDimitry Andric                      MachineBasicBlock::iterator end,
1635ca98fd9SDimitry Andric                      unsigned regioninstrs) override;
16463faed5bSDimitry Andric 
16563faed5bSDimitry Andric     /// Notify that the scheduler has finished scheduling the current region.
1665ca98fd9SDimitry Andric     void exitRegion() override;
167009b1c42SEd Schouten 
168009b1c42SEd Schouten     /// Schedule - Schedule the instruction range using list scheduling.
169009b1c42SEd Schouten     ///
1705ca98fd9SDimitry Andric     void schedule() override;
17163faed5bSDimitry Andric 
17263faed5bSDimitry Andric     void EmitSchedule();
173009b1c42SEd Schouten 
174009b1c42SEd Schouten     /// Observe - Update liveness information to account for the current
175009b1c42SEd Schouten     /// instruction, which will not be scheduled.
176009b1c42SEd Schouten     ///
17701095a5dSDimitry Andric     void Observe(MachineInstr &MI, unsigned Count);
178009b1c42SEd Schouten 
17963faed5bSDimitry Andric     /// finishBlock - Clean up register live-range state.
180009b1c42SEd Schouten     ///
1815ca98fd9SDimitry Andric     void finishBlock() override;
18236bf506aSRoman Divacky 
183009b1c42SEd Schouten   private:
18401095a5dSDimitry Andric     /// Apply each ScheduleDAGMutation step in order.
1857fa27ce4SDimitry Andric     void postProcessDAG();
18601095a5dSDimitry Andric 
18706f9d401SRoman Divacky     void ReleaseSucc(SUnit *SU, SDep *SuccEdge);
18806f9d401SRoman Divacky     void ReleaseSuccessors(SUnit *SU);
18906f9d401SRoman Divacky     void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle);
19006f9d401SRoman Divacky     void ListScheduleTopDown();
19163faed5bSDimitry Andric 
19263faed5bSDimitry Andric     void dumpSchedule() const;
1935ca98fd9SDimitry Andric     void emitNoop(unsigned CurCycle);
194009b1c42SEd Schouten   };
1951a82d4c0SDimitry Andric }
196009b1c42SEd Schouten 
19763faed5bSDimitry Andric char &llvm::PostRASchedulerID = PostRAScheduler::ID;
19863faed5bSDimitry Andric 
199ab44ce3dSDimitry Andric INITIALIZE_PASS(PostRAScheduler, DEBUG_TYPE,
20063faed5bSDimitry Andric                 "Post RA top-down list latency scheduler", false, false)
20163faed5bSDimitry Andric 
SchedulePostRATDList(MachineFunction & MF,MachineLoopInfo & MLI,AliasAnalysis * AA,const RegisterClassInfo & RCI,TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,SmallVectorImpl<const TargetRegisterClass * > & CriticalPathRCs)202cf099d11SDimitry Andric SchedulePostRATDList::SchedulePostRATDList(
20367c32a98SDimitry Andric     MachineFunction &MF, MachineLoopInfo &MLI, AliasAnalysis *AA,
20467c32a98SDimitry Andric     const RegisterClassInfo &RCI,
205411bd29eSDimitry Andric     TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,
20663faed5bSDimitry Andric     SmallVectorImpl<const TargetRegisterClass *> &CriticalPathRCs)
207ecbca9f5SDimitry Andric     : ScheduleDAGInstrs(MF, &MLI), AA(AA) {
2085ca98fd9SDimitry Andric 
20967c32a98SDimitry Andric   const InstrItineraryData *InstrItins =
21067c32a98SDimitry Andric       MF.getSubtarget().getInstrItineraryData();
211cf099d11SDimitry Andric   HazardRec =
21267c32a98SDimitry Andric       MF.getSubtarget().getInstrInfo()->CreateTargetPostRAHazardRecognizer(
21367c32a98SDimitry Andric           InstrItins, this);
21401095a5dSDimitry Andric   MF.getSubtarget().getPostRAMutations(Mutations);
21558b69754SDimitry Andric 
21658b69754SDimitry Andric   assert((AntiDepMode == TargetSubtargetInfo::ANTIDEP_NONE ||
21758b69754SDimitry Andric           MRI.tracksLiveness()) &&
21858b69754SDimitry Andric          "Live-ins must be accurate for anti-dependency breaking");
219cfca06d7SDimitry Andric   AntiDepBreak = ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_ALL)
220cfca06d7SDimitry Andric                       ? createAggressiveAntiDepBreaker(MF, RCI, CriticalPathRCs)
221cfca06d7SDimitry Andric                       : ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_CRITICAL)
222cfca06d7SDimitry Andric                              ? createCriticalAntiDepBreaker(MF, RCI)
223cfca06d7SDimitry Andric                              : nullptr));
224cf099d11SDimitry Andric }
225cf099d11SDimitry Andric 
~SchedulePostRATDList()226cf099d11SDimitry Andric SchedulePostRATDList::~SchedulePostRATDList() {
227cf099d11SDimitry Andric   delete HazardRec;
228cf099d11SDimitry Andric   delete AntiDepBreak;
229cf099d11SDimitry Andric }
230cf099d11SDimitry Andric 
23163faed5bSDimitry Andric /// Initialize state associated with the next scheduling region.
enterRegion(MachineBasicBlock * bb,MachineBasicBlock::iterator begin,MachineBasicBlock::iterator end,unsigned regioninstrs)23263faed5bSDimitry Andric void SchedulePostRATDList::enterRegion(MachineBasicBlock *bb,
23363faed5bSDimitry Andric                  MachineBasicBlock::iterator begin,
23463faed5bSDimitry Andric                  MachineBasicBlock::iterator end,
235f8af5cf6SDimitry Andric                  unsigned regioninstrs) {
236f8af5cf6SDimitry Andric   ScheduleDAGInstrs::enterRegion(bb, begin, end, regioninstrs);
23763faed5bSDimitry Andric   Sequence.clear();
23863faed5bSDimitry Andric }
23963faed5bSDimitry Andric 
24063faed5bSDimitry Andric /// Print the schedule before exiting the region.
exitRegion()24163faed5bSDimitry Andric void SchedulePostRATDList::exitRegion() {
242eb11fae6SDimitry Andric   LLVM_DEBUG({
24363faed5bSDimitry Andric     dbgs() << "*** Final schedule ***\n";
24463faed5bSDimitry Andric     dumpSchedule();
24563faed5bSDimitry Andric     dbgs() << '\n';
24663faed5bSDimitry Andric   });
24763faed5bSDimitry Andric   ScheduleDAGInstrs::exitRegion();
24863faed5bSDimitry Andric }
24963faed5bSDimitry Andric 
250522600a2SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
25163faed5bSDimitry Andric /// dumpSchedule - dump the scheduled Sequence.
dumpSchedule() const25271d5a254SDimitry Andric LLVM_DUMP_METHOD void SchedulePostRATDList::dumpSchedule() const {
25377fc4c14SDimitry Andric   for (const SUnit *SU : Sequence) {
25477fc4c14SDimitry Andric     if (SU)
255d8e91e46SDimitry Andric       dumpNode(*SU);
25663faed5bSDimitry Andric     else
25763faed5bSDimitry Andric       dbgs() << "**** NOOP ****\n";
25863faed5bSDimitry Andric   }
25963faed5bSDimitry Andric }
260522600a2SDimitry Andric #endif
26163faed5bSDimitry Andric 
enablePostRAScheduler(const TargetSubtargetInfo & ST,CodeGenOptLevel OptLevel,TargetSubtargetInfo::AntiDepBreakMode & Mode,TargetSubtargetInfo::RegClassVector & CriticalPathRCs) const2625ca98fd9SDimitry Andric bool PostRAScheduler::enablePostRAScheduler(
263b1c73532SDimitry Andric     const TargetSubtargetInfo &ST, CodeGenOptLevel OptLevel,
2645ca98fd9SDimitry Andric     TargetSubtargetInfo::AntiDepBreakMode &Mode,
2655ca98fd9SDimitry Andric     TargetSubtargetInfo::RegClassVector &CriticalPathRCs) const {
2665ca98fd9SDimitry Andric   Mode = ST.getAntiDepBreakMode();
2675ca98fd9SDimitry Andric   ST.getCriticalPathRCs(CriticalPathRCs);
26801095a5dSDimitry Andric 
26901095a5dSDimitry Andric   // Check for explicit enable/disable of post-ra scheduling.
27001095a5dSDimitry Andric   if (EnablePostRAScheduler.getPosition() > 0)
27101095a5dSDimitry Andric     return EnablePostRAScheduler;
27201095a5dSDimitry Andric 
2733a0822f0SDimitry Andric   return ST.enablePostRAScheduler() &&
2745ca98fd9SDimitry Andric          OptLevel >= ST.getOptLevelToEnablePostRAScheduler();
2755ca98fd9SDimitry Andric }
2765ca98fd9SDimitry Andric 
runOnMachineFunction(MachineFunction & Fn)277009b1c42SEd Schouten bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
278044eb2f6SDimitry Andric   if (skipFunction(Fn.getFunction()))
2795ca98fd9SDimitry Andric     return false;
2805ca98fd9SDimitry Andric 
28167c32a98SDimitry Andric   TII = Fn.getSubtarget().getInstrInfo();
282ac9a064cSDimitry Andric   MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
283dd58ef01SDimitry Andric   AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
28463faed5bSDimitry Andric   TargetPassConfig *PassConfig = &getAnalysis<TargetPassConfig>();
28563faed5bSDimitry Andric 
286411bd29eSDimitry Andric   RegClassInfo.runOnMachineFunction(Fn);
28759850d08SRoman Divacky 
28863faed5bSDimitry Andric   TargetSubtargetInfo::AntiDepBreakMode AntiDepMode =
28963faed5bSDimitry Andric     TargetSubtargetInfo::ANTIDEP_NONE;
29063faed5bSDimitry Andric   SmallVector<const TargetRegisterClass*, 4> CriticalPathRCs;
29101095a5dSDimitry Andric 
2924a142eb2SRoman Divacky   // Check that post-RA scheduling is enabled for this target.
293cf099d11SDimitry Andric   // This may upgrade the AntiDepMode.
2945a5ac124SDimitry Andric   if (!enablePostRAScheduler(Fn.getSubtarget(), PassConfig->getOptLevel(),
2955ca98fd9SDimitry Andric                              AntiDepMode, CriticalPathRCs))
2964a142eb2SRoman Divacky     return false;
2974a142eb2SRoman Divacky 
2984a142eb2SRoman Divacky   // Check for antidep breaking override...
2994a142eb2SRoman Divacky   if (EnableAntiDepBreaking.getPosition() > 0) {
300411bd29eSDimitry Andric     AntiDepMode = (EnableAntiDepBreaking == "all")
301411bd29eSDimitry Andric       ? TargetSubtargetInfo::ANTIDEP_ALL
302411bd29eSDimitry Andric       : ((EnableAntiDepBreaking == "critical")
303411bd29eSDimitry Andric          ? TargetSubtargetInfo::ANTIDEP_CRITICAL
304411bd29eSDimitry Andric          : TargetSubtargetInfo::ANTIDEP_NONE);
30559850d08SRoman Divacky   }
30659850d08SRoman Divacky 
307eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "PostRAScheduler\n");
308009b1c42SEd Schouten 
30967c32a98SDimitry Andric   SchedulePostRATDList Scheduler(Fn, MLI, AA, RegClassInfo, AntiDepMode,
310cf099d11SDimitry Andric                                  CriticalPathRCs);
311009b1c42SEd Schouten 
312009b1c42SEd Schouten   // Loop over all of the basic blocks
313dd58ef01SDimitry Andric   for (auto &MBB : Fn) {
31459850d08SRoman Divacky #ifndef NDEBUG
31559850d08SRoman Divacky     // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod
31659850d08SRoman Divacky     if (DebugDiv > 0) {
31759850d08SRoman Divacky       static int bbcnt = 0;
31859850d08SRoman Divacky       if (bbcnt++ % DebugDiv != DebugMod)
31959850d08SRoman Divacky         continue;
320044eb2f6SDimitry Andric       dbgs() << "*** DEBUG scheduling " << Fn.getName() << ":"
321044eb2f6SDimitry Andric              << printMBBReference(MBB) << " ***\n";
32259850d08SRoman Divacky     }
32359850d08SRoman Divacky #endif
32459850d08SRoman Divacky 
325009b1c42SEd Schouten     // Initialize register live-range state for scheduling in this block.
326dd58ef01SDimitry Andric     Scheduler.startBlock(&MBB);
327009b1c42SEd Schouten 
328009b1c42SEd Schouten     // Schedule each sequence of instructions not interrupted by a label
329009b1c42SEd Schouten     // or anything else that effectively needs to shut down scheduling.
330dd58ef01SDimitry Andric     MachineBasicBlock::iterator Current = MBB.end();
331dd58ef01SDimitry Andric     unsigned Count = MBB.size(), CurrentCount = Count;
332dd58ef01SDimitry Andric     for (MachineBasicBlock::iterator I = Current; I != MBB.begin();) {
33301095a5dSDimitry Andric       MachineInstr &MI = *std::prev(I);
334f8af5cf6SDimitry Andric       --Count;
33563faed5bSDimitry Andric       // Calls are not scheduling boundaries before register allocation, but
33663faed5bSDimitry Andric       // post-ra we don't gain anything by scheduling across calls since we
33763faed5bSDimitry Andric       // don't need to worry about register pressure.
33801095a5dSDimitry Andric       if (MI.isCall() || TII->isSchedulingBoundary(MI, &MBB, Fn)) {
339dd58ef01SDimitry Andric         Scheduler.enterRegion(&MBB, I, Current, CurrentCount - Count);
340f8af5cf6SDimitry Andric         Scheduler.setEndIndex(CurrentCount);
34163faed5bSDimitry Andric         Scheduler.schedule();
34263faed5bSDimitry Andric         Scheduler.exitRegion();
343d7f7719eSRoman Divacky         Scheduler.EmitSchedule();
34401095a5dSDimitry Andric         Current = &MI;
345f8af5cf6SDimitry Andric         CurrentCount = Count;
346009b1c42SEd Schouten         Scheduler.Observe(MI, CurrentCount);
347009b1c42SEd Schouten       }
348009b1c42SEd Schouten       I = MI;
34901095a5dSDimitry Andric       if (MI.isBundle())
35001095a5dSDimitry Andric         Count -= MI.getBundleSize();
351009b1c42SEd Schouten     }
352009b1c42SEd Schouten     assert(Count == 0 && "Instruction count mismatch!");
353dd58ef01SDimitry Andric     assert((MBB.begin() == Current || CurrentCount != 0) &&
354009b1c42SEd Schouten            "Instruction count mismatch!");
355dd58ef01SDimitry Andric     Scheduler.enterRegion(&MBB, MBB.begin(), Current, CurrentCount);
356f8af5cf6SDimitry Andric     Scheduler.setEndIndex(CurrentCount);
35763faed5bSDimitry Andric     Scheduler.schedule();
35863faed5bSDimitry Andric     Scheduler.exitRegion();
359d7f7719eSRoman Divacky     Scheduler.EmitSchedule();
360009b1c42SEd Schouten 
361009b1c42SEd Schouten     // Clean up register live-range state.
36263faed5bSDimitry Andric     Scheduler.finishBlock();
36359850d08SRoman Divacky 
36459850d08SRoman Divacky     // Update register kills
365ab44ce3dSDimitry Andric     Scheduler.fixupKills(MBB);
366009b1c42SEd Schouten   }
367009b1c42SEd Schouten 
368009b1c42SEd Schouten   return true;
369009b1c42SEd Schouten }
370009b1c42SEd Schouten 
371009b1c42SEd Schouten /// StartBlock - Initialize register live-range state for scheduling in
372009b1c42SEd Schouten /// this block.
373009b1c42SEd Schouten ///
startBlock(MachineBasicBlock * BB)37463faed5bSDimitry Andric void SchedulePostRATDList::startBlock(MachineBasicBlock *BB) {
375009b1c42SEd Schouten   // Call the superclass.
37663faed5bSDimitry Andric   ScheduleDAGInstrs::startBlock(BB);
377009b1c42SEd Schouten 
37836bf506aSRoman Divacky   // Reset the hazard recognizer and anti-dep breaker.
37959850d08SRoman Divacky   HazardRec->Reset();
3805ca98fd9SDimitry Andric   if (AntiDepBreak)
38136bf506aSRoman Divacky     AntiDepBreak->StartBlock(BB);
382009b1c42SEd Schouten }
383009b1c42SEd Schouten 
384009b1c42SEd Schouten /// Schedule - Schedule the instruction range using list scheduling.
385009b1c42SEd Schouten ///
schedule()38663faed5bSDimitry Andric void SchedulePostRATDList::schedule() {
387009b1c42SEd Schouten   // Build the scheduling graph.
38863faed5bSDimitry Andric   buildSchedGraph(AA);
389009b1c42SEd Schouten 
3905ca98fd9SDimitry Andric   if (AntiDepBreak) {
39136bf506aSRoman Divacky     unsigned Broken =
39263faed5bSDimitry Andric       AntiDepBreak->BreakAntiDependencies(SUnits, RegionBegin, RegionEnd,
39363faed5bSDimitry Andric                                           EndIndex, DbgValues);
39436bf506aSRoman Divacky 
39506f9d401SRoman Divacky     if (Broken != 0) {
396009b1c42SEd Schouten       // We made changes. Update the dependency graph.
397009b1c42SEd Schouten       // Theoretically we could update the graph in place:
398009b1c42SEd Schouten       // When a live range is changed to use a different register, remove
399009b1c42SEd Schouten       // the def's anti-dependence *and* output-dependence edges due to
400009b1c42SEd Schouten       // that register, and add new anti-dependence and output-dependence
401009b1c42SEd Schouten       // edges based on the next live range of the register.
40263faed5bSDimitry Andric       ScheduleDAG::clearDAG();
40363faed5bSDimitry Andric       buildSchedGraph(AA);
40436bf506aSRoman Divacky 
40536bf506aSRoman Divacky       NumFixedAnti += Broken;
40636bf506aSRoman Divacky     }
407009b1c42SEd Schouten   }
408009b1c42SEd Schouten 
4097fa27ce4SDimitry Andric   postProcessDAG();
41001095a5dSDimitry Andric 
411eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "********** List Scheduling **********\n");
412d8e91e46SDimitry Andric   LLVM_DEBUG(dump());
41359850d08SRoman Divacky 
414009b1c42SEd Schouten   AvailableQueue.initNodes(SUnits);
41506f9d401SRoman Divacky   ListScheduleTopDown();
416009b1c42SEd Schouten   AvailableQueue.releaseState();
417009b1c42SEd Schouten }
418009b1c42SEd Schouten 
419009b1c42SEd Schouten /// Observe - Update liveness information to account for the current
420009b1c42SEd Schouten /// instruction, which will not be scheduled.
421009b1c42SEd Schouten ///
Observe(MachineInstr & MI,unsigned Count)42201095a5dSDimitry Andric void SchedulePostRATDList::Observe(MachineInstr &MI, unsigned Count) {
4235ca98fd9SDimitry Andric   if (AntiDepBreak)
42463faed5bSDimitry Andric     AntiDepBreak->Observe(MI, Count, EndIndex);
425009b1c42SEd Schouten }
426009b1c42SEd Schouten 
427009b1c42SEd Schouten /// FinishBlock - Clean up register live-range state.
428009b1c42SEd Schouten ///
finishBlock()42963faed5bSDimitry Andric void SchedulePostRATDList::finishBlock() {
4305ca98fd9SDimitry Andric   if (AntiDepBreak)
43136bf506aSRoman Divacky     AntiDepBreak->FinishBlock();
432009b1c42SEd Schouten 
433009b1c42SEd Schouten   // Call the superclass.
43463faed5bSDimitry Andric   ScheduleDAGInstrs::finishBlock();
435009b1c42SEd Schouten }
436009b1c42SEd Schouten 
43701095a5dSDimitry Andric /// Apply each ScheduleDAGMutation step in order.
postProcessDAG()4387fa27ce4SDimitry Andric void SchedulePostRATDList::postProcessDAG() {
43901095a5dSDimitry Andric   for (auto &M : Mutations)
44001095a5dSDimitry Andric     M->apply(this);
44101095a5dSDimitry Andric }
44201095a5dSDimitry Andric 
443009b1c42SEd Schouten //===----------------------------------------------------------------------===//
444009b1c42SEd Schouten //  Top-Down Scheduling
445009b1c42SEd Schouten //===----------------------------------------------------------------------===//
446009b1c42SEd Schouten 
447009b1c42SEd Schouten /// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
4484a16efa3SDimitry Andric /// the PendingQueue if the count reaches zero.
ReleaseSucc(SUnit * SU,SDep * SuccEdge)44906f9d401SRoman Divacky void SchedulePostRATDList::ReleaseSucc(SUnit *SU, SDep *SuccEdge) {
450009b1c42SEd Schouten   SUnit *SuccSU = SuccEdge->getSUnit();
451009b1c42SEd Schouten 
4524a16efa3SDimitry Andric   if (SuccEdge->isWeak()) {
4534a16efa3SDimitry Andric     --SuccSU->WeakPredsLeft;
4544a16efa3SDimitry Andric     return;
4554a16efa3SDimitry Andric   }
456009b1c42SEd Schouten #ifndef NDEBUG
45759850d08SRoman Divacky   if (SuccSU->NumPredsLeft == 0) {
458829000e0SRoman Divacky     dbgs() << "*** Scheduling failed! ***\n";
459d8e91e46SDimitry Andric     dumpNode(*SuccSU);
460829000e0SRoman Divacky     dbgs() << " has been released too many times!\n";
4615ca98fd9SDimitry Andric     llvm_unreachable(nullptr);
462009b1c42SEd Schouten   }
463009b1c42SEd Schouten #endif
46459850d08SRoman Divacky   --SuccSU->NumPredsLeft;
465009b1c42SEd Schouten 
46656fe8f14SDimitry Andric   // Standard scheduler algorithms will recompute the depth of the successor
46756fe8f14SDimitry Andric   // here as such:
46856fe8f14SDimitry Andric   //   SuccSU->setDepthToAtLeast(SU->getDepth() + SuccEdge->getLatency());
46956fe8f14SDimitry Andric   //
47056fe8f14SDimitry Andric   // However, we lazily compute node depth instead. Note that
47156fe8f14SDimitry Andric   // ScheduleNodeTopDown has already updated the depth of this node which causes
47256fe8f14SDimitry Andric   // all descendents to be marked dirty. Setting the successor depth explicitly
47356fe8f14SDimitry Andric   // here would cause depth to be recomputed for all its ancestors. If the
47456fe8f14SDimitry Andric   // successor is not yet ready (because of a transitively redundant edge) then
47556fe8f14SDimitry Andric   // this causes depth computation to be quadratic in the size of the DAG.
476009b1c42SEd Schouten 
477009b1c42SEd Schouten   // If all the node's predecessors are scheduled, this node is ready
478009b1c42SEd Schouten   // to be scheduled. Ignore the special ExitSU node.
479009b1c42SEd Schouten   if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU)
480009b1c42SEd Schouten     PendingQueue.push_back(SuccSU);
481009b1c42SEd Schouten }
482009b1c42SEd Schouten 
483009b1c42SEd Schouten /// ReleaseSuccessors - Call ReleaseSucc on each of SU's successors.
ReleaseSuccessors(SUnit * SU)48406f9d401SRoman Divacky void SchedulePostRATDList::ReleaseSuccessors(SUnit *SU) {
485009b1c42SEd Schouten   for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
48636bf506aSRoman Divacky        I != E; ++I) {
48706f9d401SRoman Divacky     ReleaseSucc(SU, &*I);
48836bf506aSRoman Divacky   }
489009b1c42SEd Schouten }
490009b1c42SEd Schouten 
491009b1c42SEd Schouten /// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
492009b1c42SEd Schouten /// count of its successors. If a successor pending count is zero, add it to
493009b1c42SEd Schouten /// the Available queue.
ScheduleNodeTopDown(SUnit * SU,unsigned CurCycle)49406f9d401SRoman Divacky void SchedulePostRATDList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
495eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: ");
496d8e91e46SDimitry Andric   LLVM_DEBUG(dumpNode(*SU));
497009b1c42SEd Schouten 
498009b1c42SEd Schouten   Sequence.push_back(SU);
49906f9d401SRoman Divacky   assert(CurCycle >= SU->getDepth() &&
50036bf506aSRoman Divacky          "Node scheduled above its depth!");
50106f9d401SRoman Divacky   SU->setDepthToAtLeast(CurCycle);
502009b1c42SEd Schouten 
50306f9d401SRoman Divacky   ReleaseSuccessors(SU);
504009b1c42SEd Schouten   SU->isScheduled = true;
50563faed5bSDimitry Andric   AvailableQueue.scheduledNode(SU);
506009b1c42SEd Schouten }
507009b1c42SEd Schouten 
5085ca98fd9SDimitry Andric /// emitNoop - Add a noop to the current instruction sequence.
emitNoop(unsigned CurCycle)5095ca98fd9SDimitry Andric void SchedulePostRATDList::emitNoop(unsigned CurCycle) {
510eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "*** Emitting noop in cycle " << CurCycle << '\n');
5115ca98fd9SDimitry Andric   HazardRec->EmitNoop();
5125ca98fd9SDimitry Andric   Sequence.push_back(nullptr);   // NULL here means noop
5135ca98fd9SDimitry Andric   ++NumNoops;
5145ca98fd9SDimitry Andric }
5155ca98fd9SDimitry Andric 
516009b1c42SEd Schouten /// ListScheduleTopDown - The main loop of list scheduling for top-down
517009b1c42SEd Schouten /// schedulers.
ListScheduleTopDown()51806f9d401SRoman Divacky void SchedulePostRATDList::ListScheduleTopDown() {
519009b1c42SEd Schouten   unsigned CurCycle = 0;
52036bf506aSRoman Divacky 
52136bf506aSRoman Divacky   // We're scheduling top-down but we're visiting the regions in
52236bf506aSRoman Divacky   // bottom-up order, so we don't know the hazards at the start of a
52336bf506aSRoman Divacky   // region. So assume no hazards (this should usually be ok as most
52436bf506aSRoman Divacky   // blocks are a single region).
52536bf506aSRoman Divacky   HazardRec->Reset();
52636bf506aSRoman Divacky 
527009b1c42SEd Schouten   // Release any successors of the special Entry node.
52806f9d401SRoman Divacky   ReleaseSuccessors(&EntrySU);
529009b1c42SEd Schouten 
53006f9d401SRoman Divacky   // Add all leaves to Available queue.
53177fc4c14SDimitry Andric   for (SUnit &SUnit : SUnits) {
532009b1c42SEd Schouten     // It is available if it has no predecessors.
53377fc4c14SDimitry Andric     if (!SUnit.NumPredsLeft && !SUnit.isAvailable) {
53477fc4c14SDimitry Andric       AvailableQueue.push(&SUnit);
53577fc4c14SDimitry Andric       SUnit.isAvailable = true;
536009b1c42SEd Schouten     }
537009b1c42SEd Schouten   }
538009b1c42SEd Schouten 
53959850d08SRoman Divacky   // In any cycle where we can't schedule any instructions, we must
54059850d08SRoman Divacky   // stall or emit a noop, depending on the target.
54159850d08SRoman Divacky   bool CycleHasInsts = false;
54259850d08SRoman Divacky 
543009b1c42SEd Schouten   // While Available queue is not empty, grab the node with the highest
544009b1c42SEd Schouten   // priority. If it is not ready put it back.  Schedule the node.
545009b1c42SEd Schouten   std::vector<SUnit*> NotReady;
546009b1c42SEd Schouten   Sequence.reserve(SUnits.size());
547009b1c42SEd Schouten   while (!AvailableQueue.empty() || !PendingQueue.empty()) {
548009b1c42SEd Schouten     // Check to see if any of the pending instructions are ready to issue.  If
549009b1c42SEd Schouten     // so, add them to the available queue.
550009b1c42SEd Schouten     unsigned MinDepth = ~0u;
551009b1c42SEd Schouten     for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
55206f9d401SRoman Divacky       if (PendingQueue[i]->getDepth() <= CurCycle) {
553009b1c42SEd Schouten         AvailableQueue.push(PendingQueue[i]);
554009b1c42SEd Schouten         PendingQueue[i]->isAvailable = true;
555009b1c42SEd Schouten         PendingQueue[i] = PendingQueue.back();
556009b1c42SEd Schouten         PendingQueue.pop_back();
557009b1c42SEd Schouten         --i; --e;
55806f9d401SRoman Divacky       } else if (PendingQueue[i]->getDepth() < MinDepth)
55906f9d401SRoman Divacky         MinDepth = PendingQueue[i]->getDepth();
560009b1c42SEd Schouten     }
561009b1c42SEd Schouten 
562eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "\n*** Examining Available\n";
563eb11fae6SDimitry Andric                AvailableQueue.dump(this));
564009b1c42SEd Schouten 
5655ca98fd9SDimitry Andric     SUnit *FoundSUnit = nullptr, *NotPreferredSUnit = nullptr;
566009b1c42SEd Schouten     bool HasNoopHazards = false;
567009b1c42SEd Schouten     while (!AvailableQueue.empty()) {
568009b1c42SEd Schouten       SUnit *CurSUnit = AvailableQueue.pop();
569009b1c42SEd Schouten 
570009b1c42SEd Schouten       ScheduleHazardRecognizer::HazardType HT =
571cf099d11SDimitry Andric         HazardRec->getHazardType(CurSUnit, 0/*no stalls*/);
572009b1c42SEd Schouten       if (HT == ScheduleHazardRecognizer::NoHazard) {
5735ca98fd9SDimitry Andric         if (HazardRec->ShouldPreferAnother(CurSUnit)) {
5745ca98fd9SDimitry Andric           if (!NotPreferredSUnit) {
5755ca98fd9SDimitry Andric             // If this is the first non-preferred node for this cycle, then
5765ca98fd9SDimitry Andric             // record it and continue searching for a preferred node. If this
5775ca98fd9SDimitry Andric             // is not the first non-preferred node, then treat it as though
5785ca98fd9SDimitry Andric             // there had been a hazard.
5795ca98fd9SDimitry Andric             NotPreferredSUnit = CurSUnit;
5805ca98fd9SDimitry Andric             continue;
5815ca98fd9SDimitry Andric           }
5825ca98fd9SDimitry Andric         } else {
583009b1c42SEd Schouten           FoundSUnit = CurSUnit;
584009b1c42SEd Schouten           break;
585009b1c42SEd Schouten         }
5865ca98fd9SDimitry Andric       }
587009b1c42SEd Schouten 
588009b1c42SEd Schouten       // Remember if this is a noop hazard.
589009b1c42SEd Schouten       HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard;
590009b1c42SEd Schouten 
591009b1c42SEd Schouten       NotReady.push_back(CurSUnit);
592009b1c42SEd Schouten     }
593009b1c42SEd Schouten 
5945ca98fd9SDimitry Andric     // If we have a non-preferred node, push it back onto the available list.
5955ca98fd9SDimitry Andric     // If we did not find a preferred node, then schedule this first
5965ca98fd9SDimitry Andric     // non-preferred node.
5975ca98fd9SDimitry Andric     if (NotPreferredSUnit) {
5985ca98fd9SDimitry Andric       if (!FoundSUnit) {
599eb11fae6SDimitry Andric         LLVM_DEBUG(
600eb11fae6SDimitry Andric             dbgs() << "*** Will schedule a non-preferred instruction...\n");
6015ca98fd9SDimitry Andric         FoundSUnit = NotPreferredSUnit;
6025ca98fd9SDimitry Andric       } else {
6035ca98fd9SDimitry Andric         AvailableQueue.push(NotPreferredSUnit);
6045ca98fd9SDimitry Andric       }
6055ca98fd9SDimitry Andric 
6065ca98fd9SDimitry Andric       NotPreferredSUnit = nullptr;
6075ca98fd9SDimitry Andric     }
6085ca98fd9SDimitry Andric 
609009b1c42SEd Schouten     // Add the nodes that aren't ready back onto the available list.
610009b1c42SEd Schouten     if (!NotReady.empty()) {
611009b1c42SEd Schouten       AvailableQueue.push_all(NotReady);
612009b1c42SEd Schouten       NotReady.clear();
613009b1c42SEd Schouten     }
614009b1c42SEd Schouten 
61536bf506aSRoman Divacky     // If we found a node to schedule...
616009b1c42SEd Schouten     if (FoundSUnit) {
6175ca98fd9SDimitry Andric       // If we need to emit noops prior to this instruction, then do so.
6185ca98fd9SDimitry Andric       unsigned NumPreNoops = HazardRec->PreEmitNoops(FoundSUnit);
6195ca98fd9SDimitry Andric       for (unsigned i = 0; i != NumPreNoops; ++i)
6205ca98fd9SDimitry Andric         emitNoop(CurCycle);
6215ca98fd9SDimitry Andric 
62236bf506aSRoman Divacky       // ... schedule the node...
62306f9d401SRoman Divacky       ScheduleNodeTopDown(FoundSUnit, CurCycle);
624009b1c42SEd Schouten       HazardRec->EmitInstruction(FoundSUnit);
62559850d08SRoman Divacky       CycleHasInsts = true;
62656fe8f14SDimitry Andric       if (HazardRec->atIssueLimit()) {
627eb11fae6SDimitry Andric         LLVM_DEBUG(dbgs() << "*** Max instructions per cycle " << CurCycle
628eb11fae6SDimitry Andric                           << '\n');
62956fe8f14SDimitry Andric         HazardRec->AdvanceCycle();
63056fe8f14SDimitry Andric         ++CurCycle;
63156fe8f14SDimitry Andric         CycleHasInsts = false;
63256fe8f14SDimitry Andric       }
63359850d08SRoman Divacky     } else {
63459850d08SRoman Divacky       if (CycleHasInsts) {
635eb11fae6SDimitry Andric         LLVM_DEBUG(dbgs() << "*** Finished cycle " << CurCycle << '\n');
63659850d08SRoman Divacky         HazardRec->AdvanceCycle();
637009b1c42SEd Schouten       } else if (!HasNoopHazards) {
63859850d08SRoman Divacky         // Otherwise, we have a pipeline stall, but no other problem,
63959850d08SRoman Divacky         // just advance the current cycle and try again.
640eb11fae6SDimitry Andric         LLVM_DEBUG(dbgs() << "*** Stall in cycle " << CurCycle << '\n');
641009b1c42SEd Schouten         HazardRec->AdvanceCycle();
642009b1c42SEd Schouten         ++NumStalls;
643009b1c42SEd Schouten       } else {
644009b1c42SEd Schouten         // Otherwise, we have no instructions to issue and we have instructions
645009b1c42SEd Schouten         // that will fault if we don't do this right.  This is the case for
646009b1c42SEd Schouten         // processors without pipeline interlocks and other cases.
6475ca98fd9SDimitry Andric         emitNoop(CurCycle);
64859850d08SRoman Divacky       }
64959850d08SRoman Divacky 
650009b1c42SEd Schouten       ++CurCycle;
65159850d08SRoman Divacky       CycleHasInsts = false;
652009b1c42SEd Schouten     }
653009b1c42SEd Schouten   }
654009b1c42SEd Schouten 
655009b1c42SEd Schouten #ifndef NDEBUG
65663faed5bSDimitry Andric   unsigned ScheduledNodes = VerifyScheduledDAG(/*isBottomUp=*/false);
65777fc4c14SDimitry Andric   unsigned Noops = llvm::count(Sequence, nullptr);
65863faed5bSDimitry Andric   assert(Sequence.size() - Noops == ScheduledNodes &&
65963faed5bSDimitry Andric          "The number of nodes scheduled doesn't match the expected number!");
66063faed5bSDimitry Andric #endif // NDEBUG
661009b1c42SEd Schouten }
662009b1c42SEd Schouten 
66363faed5bSDimitry Andric // EmitSchedule - Emit the machine code in scheduled order.
EmitSchedule()66463faed5bSDimitry Andric void SchedulePostRATDList::EmitSchedule() {
66563faed5bSDimitry Andric   RegionBegin = RegionEnd;
666009b1c42SEd Schouten 
66763faed5bSDimitry Andric   // If first instruction was a DBG_VALUE then put it back.
66863faed5bSDimitry Andric   if (FirstDbgValue)
66963faed5bSDimitry Andric     BB->splice(RegionEnd, BB, FirstDbgValue);
67063faed5bSDimitry Andric 
67163faed5bSDimitry Andric   // Then re-insert them according to the given schedule.
67263faed5bSDimitry Andric   for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
67363faed5bSDimitry Andric     if (SUnit *SU = Sequence[i])
67463faed5bSDimitry Andric       BB->splice(RegionEnd, BB, SU->getInstr());
67563faed5bSDimitry Andric     else
67663faed5bSDimitry Andric       // Null SUnit* is a noop.
67763faed5bSDimitry Andric       TII->insertNoop(*BB, RegionEnd);
67863faed5bSDimitry Andric 
67963faed5bSDimitry Andric     // Update the Begin iterator, as the first instruction in the block
68063faed5bSDimitry Andric     // may have been scheduled later.
68163faed5bSDimitry Andric     if (i == 0)
6825ca98fd9SDimitry Andric       RegionBegin = std::prev(RegionEnd);
68363faed5bSDimitry Andric   }
68463faed5bSDimitry Andric 
68563faed5bSDimitry Andric   // Reinsert any remaining debug_values.
68663faed5bSDimitry Andric   for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
68763faed5bSDimitry Andric          DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
6885ca98fd9SDimitry Andric     std::pair<MachineInstr *, MachineInstr *> P = *std::prev(DI);
68963faed5bSDimitry Andric     MachineInstr *DbgValue = P.first;
69063faed5bSDimitry Andric     MachineBasicBlock::iterator OrigPrivMI = P.second;
69163faed5bSDimitry Andric     BB->splice(++OrigPrivMI, BB, DbgValue);
69263faed5bSDimitry Andric   }
69363faed5bSDimitry Andric   DbgValues.clear();
6945ca98fd9SDimitry Andric   FirstDbgValue = nullptr;
695009b1c42SEd Schouten }
696