xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/PostRASchedulerList.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===----- SchedulePostRAList.cpp - list scheduler ------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This implements a top-down list scheduler, using standard algorithms.
100b57cec5SDimitry Andric // The basic approach uses a priority queue of available nodes to schedule.
110b57cec5SDimitry Andric // One at a time, nodes are taken from the priority queue (thus in priority
120b57cec5SDimitry Andric // order), checked for legality to schedule, and emitted if legal.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric // Nodes may not be legal to schedule either due to structural hazards (e.g.
150b57cec5SDimitry Andric // pipeline or resource constraints) or because an input to the instruction has
160b57cec5SDimitry Andric // not completed execution.
170b57cec5SDimitry Andric //
180b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
225ffd83dbSDimitry Andric #include "llvm/CodeGen/AntiDepBreaker.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/LatencyPriorityQueue.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterClassInfo.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAGInstrs.h"
3081ad6265SDimitry Andric #include "llvm/CodeGen/ScheduleDAGMutation.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
350b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
36480093f4SDimitry Andric #include "llvm/InitializePasses.h"
3781ad6265SDimitry Andric #include "llvm/Pass.h"
380b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
390b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
400b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
410b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
420b57cec5SDimitry Andric using namespace llvm;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric #define DEBUG_TYPE "post-RA-sched"
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric STATISTIC(NumNoops, "Number of noops inserted");
470b57cec5SDimitry Andric STATISTIC(NumStalls, "Number of pipeline stalls");
480b57cec5SDimitry Andric STATISTIC(NumFixedAnti, "Number of fixed anti-dependencies");
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric // Post-RA scheduling is enabled with
510b57cec5SDimitry Andric // TargetSubtargetInfo.enablePostRAScheduler(). This flag can be used to
520b57cec5SDimitry Andric // override the target.
530b57cec5SDimitry Andric static cl::opt<bool>
540b57cec5SDimitry Andric EnablePostRAScheduler("post-RA-scheduler",
550b57cec5SDimitry Andric                        cl::desc("Enable scheduling after register allocation"),
560b57cec5SDimitry Andric                        cl::init(false), cl::Hidden);
570b57cec5SDimitry Andric static cl::opt<std::string>
580b57cec5SDimitry Andric EnableAntiDepBreaking("break-anti-dependencies",
590b57cec5SDimitry Andric                       cl::desc("Break post-RA scheduling anti-dependencies: "
600b57cec5SDimitry Andric                                "\"critical\", \"all\", or \"none\""),
610b57cec5SDimitry Andric                       cl::init("none"), cl::Hidden);
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod
640b57cec5SDimitry Andric static cl::opt<int>
650b57cec5SDimitry Andric DebugDiv("postra-sched-debugdiv",
660b57cec5SDimitry Andric                       cl::desc("Debug control MBBs that are scheduled"),
670b57cec5SDimitry Andric                       cl::init(0), cl::Hidden);
680b57cec5SDimitry Andric static cl::opt<int>
690b57cec5SDimitry Andric DebugMod("postra-sched-debugmod",
700b57cec5SDimitry Andric                       cl::desc("Debug control MBBs that are scheduled"),
710b57cec5SDimitry Andric                       cl::init(0), cl::Hidden);
720b57cec5SDimitry Andric 
7381ad6265SDimitry Andric AntiDepBreaker::~AntiDepBreaker() = default;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric namespace {
760b57cec5SDimitry Andric   class PostRAScheduler : public MachineFunctionPass {
77480093f4SDimitry Andric     const TargetInstrInfo *TII = nullptr;
780b57cec5SDimitry Andric     RegisterClassInfo RegClassInfo;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   public:
810b57cec5SDimitry Andric     static char ID;
820b57cec5SDimitry Andric     PostRAScheduler() : MachineFunctionPass(ID) {}
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric     void getAnalysisUsage(AnalysisUsage &AU) const override {
850b57cec5SDimitry Andric       AU.setPreservesCFG();
860b57cec5SDimitry Andric       AU.addRequired<AAResultsWrapperPass>();
870b57cec5SDimitry Andric       AU.addRequired<TargetPassConfig>();
88*0fca6ea1SDimitry Andric       AU.addRequired<MachineDominatorTreeWrapperPass>();
89*0fca6ea1SDimitry Andric       AU.addPreserved<MachineDominatorTreeWrapperPass>();
90*0fca6ea1SDimitry Andric       AU.addRequired<MachineLoopInfoWrapperPass>();
91*0fca6ea1SDimitry Andric       AU.addPreserved<MachineLoopInfoWrapperPass>();
920b57cec5SDimitry Andric       MachineFunctionPass::getAnalysisUsage(AU);
930b57cec5SDimitry Andric     }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric     MachineFunctionProperties getRequiredProperties() const override {
960b57cec5SDimitry Andric       return MachineFunctionProperties().set(
970b57cec5SDimitry Andric           MachineFunctionProperties::Property::NoVRegs);
980b57cec5SDimitry Andric     }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &Fn) override;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   private:
1030b57cec5SDimitry Andric     bool enablePostRAScheduler(
1045f757f3fSDimitry Andric         const TargetSubtargetInfo &ST, CodeGenOptLevel OptLevel,
1050b57cec5SDimitry Andric         TargetSubtargetInfo::AntiDepBreakMode &Mode,
1060b57cec5SDimitry Andric         TargetSubtargetInfo::RegClassVector &CriticalPathRCs) const;
1070b57cec5SDimitry Andric   };
1080b57cec5SDimitry Andric   char PostRAScheduler::ID = 0;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   class SchedulePostRATDList : public ScheduleDAGInstrs {
1110b57cec5SDimitry Andric     /// AvailableQueue - The priority queue to use for the available SUnits.
1120b57cec5SDimitry Andric     ///
1130b57cec5SDimitry Andric     LatencyPriorityQueue AvailableQueue;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     /// PendingQueue - This contains all of the instructions whose operands have
1160b57cec5SDimitry Andric     /// been issued, but their results are not ready yet (due to the latency of
1170b57cec5SDimitry Andric     /// the operation).  Once the operands becomes available, the instruction is
1180b57cec5SDimitry Andric     /// added to the AvailableQueue.
1190b57cec5SDimitry Andric     std::vector<SUnit*> PendingQueue;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric     /// HazardRec - The hazard recognizer to use.
1220b57cec5SDimitry Andric     ScheduleHazardRecognizer *HazardRec;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric     /// AntiDepBreak - Anti-dependence breaking object, or NULL if none
1250b57cec5SDimitry Andric     AntiDepBreaker *AntiDepBreak;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     /// AA - AliasAnalysis for making memory reference queries.
1280b57cec5SDimitry Andric     AliasAnalysis *AA;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric     /// The schedule. Null SUnit*'s represent noop instructions.
1310b57cec5SDimitry Andric     std::vector<SUnit*> Sequence;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric     /// Ordered list of DAG postprocessing steps.
1340b57cec5SDimitry Andric     std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric     /// The index in BB of RegionEnd.
1370b57cec5SDimitry Andric     ///
1380b57cec5SDimitry Andric     /// This is the instruction number from the top of the current block, not
1390b57cec5SDimitry Andric     /// the SlotIndex. It is only used by the AntiDepBreaker.
1401fd87a68SDimitry Andric     unsigned EndIndex = 0;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   public:
1430b57cec5SDimitry Andric     SchedulePostRATDList(
1440b57cec5SDimitry Andric         MachineFunction &MF, MachineLoopInfo &MLI, AliasAnalysis *AA,
1450b57cec5SDimitry Andric         const RegisterClassInfo &,
1460b57cec5SDimitry Andric         TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,
1470b57cec5SDimitry Andric         SmallVectorImpl<const TargetRegisterClass *> &CriticalPathRCs);
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric     ~SchedulePostRATDList() override;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric     /// startBlock - Initialize register live-range state for scheduling in
1520b57cec5SDimitry Andric     /// this block.
1530b57cec5SDimitry Andric     ///
1540b57cec5SDimitry Andric     void startBlock(MachineBasicBlock *BB) override;
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric     // Set the index of RegionEnd within the current BB.
1570b57cec5SDimitry Andric     void setEndIndex(unsigned EndIdx) { EndIndex = EndIdx; }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric     /// Initialize the scheduler state for the next scheduling region.
1600b57cec5SDimitry Andric     void enterRegion(MachineBasicBlock *bb,
1610b57cec5SDimitry Andric                      MachineBasicBlock::iterator begin,
1620b57cec5SDimitry Andric                      MachineBasicBlock::iterator end,
1630b57cec5SDimitry Andric                      unsigned regioninstrs) override;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric     /// Notify that the scheduler has finished scheduling the current region.
1660b57cec5SDimitry Andric     void exitRegion() override;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric     /// Schedule - Schedule the instruction range using list scheduling.
1690b57cec5SDimitry Andric     ///
1700b57cec5SDimitry Andric     void schedule() override;
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric     void EmitSchedule();
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric     /// Observe - Update liveness information to account for the current
1750b57cec5SDimitry Andric     /// instruction, which will not be scheduled.
1760b57cec5SDimitry Andric     ///
1770b57cec5SDimitry Andric     void Observe(MachineInstr &MI, unsigned Count);
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric     /// finishBlock - Clean up register live-range state.
1800b57cec5SDimitry Andric     ///
1810b57cec5SDimitry Andric     void finishBlock() override;
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   private:
1840b57cec5SDimitry Andric     /// Apply each ScheduleDAGMutation step in order.
18506c3fb27SDimitry Andric     void postProcessDAG();
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric     void ReleaseSucc(SUnit *SU, SDep *SuccEdge);
1880b57cec5SDimitry Andric     void ReleaseSuccessors(SUnit *SU);
1890b57cec5SDimitry Andric     void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle);
1900b57cec5SDimitry Andric     void ListScheduleTopDown();
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric     void dumpSchedule() const;
1930b57cec5SDimitry Andric     void emitNoop(unsigned CurCycle);
1940b57cec5SDimitry Andric   };
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric char &llvm::PostRASchedulerID = PostRAScheduler::ID;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric INITIALIZE_PASS(PostRAScheduler, DEBUG_TYPE,
2000b57cec5SDimitry Andric                 "Post RA top-down list latency scheduler", false, false)
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric SchedulePostRATDList::SchedulePostRATDList(
2030b57cec5SDimitry Andric     MachineFunction &MF, MachineLoopInfo &MLI, AliasAnalysis *AA,
2040b57cec5SDimitry Andric     const RegisterClassInfo &RCI,
2050b57cec5SDimitry Andric     TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,
2060b57cec5SDimitry Andric     SmallVectorImpl<const TargetRegisterClass *> &CriticalPathRCs)
2071fd87a68SDimitry Andric     : ScheduleDAGInstrs(MF, &MLI), AA(AA) {
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   const InstrItineraryData *InstrItins =
2100b57cec5SDimitry Andric       MF.getSubtarget().getInstrItineraryData();
2110b57cec5SDimitry Andric   HazardRec =
2120b57cec5SDimitry Andric       MF.getSubtarget().getInstrInfo()->CreateTargetPostRAHazardRecognizer(
2130b57cec5SDimitry Andric           InstrItins, this);
2140b57cec5SDimitry Andric   MF.getSubtarget().getPostRAMutations(Mutations);
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   assert((AntiDepMode == TargetSubtargetInfo::ANTIDEP_NONE ||
2170b57cec5SDimitry Andric           MRI.tracksLiveness()) &&
2180b57cec5SDimitry Andric          "Live-ins must be accurate for anti-dependency breaking");
2195ffd83dbSDimitry Andric   AntiDepBreak = ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_ALL)
2205ffd83dbSDimitry Andric                       ? createAggressiveAntiDepBreaker(MF, RCI, CriticalPathRCs)
2215ffd83dbSDimitry Andric                       : ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_CRITICAL)
2225ffd83dbSDimitry Andric                              ? createCriticalAntiDepBreaker(MF, RCI)
2235ffd83dbSDimitry Andric                              : nullptr));
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric SchedulePostRATDList::~SchedulePostRATDList() {
2270b57cec5SDimitry Andric   delete HazardRec;
2280b57cec5SDimitry Andric   delete AntiDepBreak;
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric /// Initialize state associated with the next scheduling region.
2320b57cec5SDimitry Andric void SchedulePostRATDList::enterRegion(MachineBasicBlock *bb,
2330b57cec5SDimitry Andric                  MachineBasicBlock::iterator begin,
2340b57cec5SDimitry Andric                  MachineBasicBlock::iterator end,
2350b57cec5SDimitry Andric                  unsigned regioninstrs) {
2360b57cec5SDimitry Andric   ScheduleDAGInstrs::enterRegion(bb, begin, end, regioninstrs);
2370b57cec5SDimitry Andric   Sequence.clear();
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric /// Print the schedule before exiting the region.
2410b57cec5SDimitry Andric void SchedulePostRATDList::exitRegion() {
2420b57cec5SDimitry Andric   LLVM_DEBUG({
2430b57cec5SDimitry Andric     dbgs() << "*** Final schedule ***\n";
2440b57cec5SDimitry Andric     dumpSchedule();
2450b57cec5SDimitry Andric     dbgs() << '\n';
2460b57cec5SDimitry Andric   });
2470b57cec5SDimitry Andric   ScheduleDAGInstrs::exitRegion();
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2510b57cec5SDimitry Andric /// dumpSchedule - dump the scheduled Sequence.
2520b57cec5SDimitry Andric LLVM_DUMP_METHOD void SchedulePostRATDList::dumpSchedule() const {
2530eae32dcSDimitry Andric   for (const SUnit *SU : Sequence) {
2540eae32dcSDimitry Andric     if (SU)
2550b57cec5SDimitry Andric       dumpNode(*SU);
2560b57cec5SDimitry Andric     else
2570b57cec5SDimitry Andric       dbgs() << "**** NOOP ****\n";
2580b57cec5SDimitry Andric   }
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric #endif
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric bool PostRAScheduler::enablePostRAScheduler(
2635f757f3fSDimitry Andric     const TargetSubtargetInfo &ST, CodeGenOptLevel OptLevel,
2640b57cec5SDimitry Andric     TargetSubtargetInfo::AntiDepBreakMode &Mode,
2650b57cec5SDimitry Andric     TargetSubtargetInfo::RegClassVector &CriticalPathRCs) const {
2660b57cec5SDimitry Andric   Mode = ST.getAntiDepBreakMode();
2670b57cec5SDimitry Andric   ST.getCriticalPathRCs(CriticalPathRCs);
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   // Check for explicit enable/disable of post-ra scheduling.
2700b57cec5SDimitry Andric   if (EnablePostRAScheduler.getPosition() > 0)
2710b57cec5SDimitry Andric     return EnablePostRAScheduler;
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   return ST.enablePostRAScheduler() &&
2740b57cec5SDimitry Andric          OptLevel >= ST.getOptLevelToEnablePostRAScheduler();
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
2780b57cec5SDimitry Andric   if (skipFunction(Fn.getFunction()))
2790b57cec5SDimitry Andric     return false;
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   TII = Fn.getSubtarget().getInstrInfo();
282*0fca6ea1SDimitry Andric   MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
2830b57cec5SDimitry Andric   AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
2840b57cec5SDimitry Andric   TargetPassConfig *PassConfig = &getAnalysis<TargetPassConfig>();
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   RegClassInfo.runOnMachineFunction(Fn);
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   TargetSubtargetInfo::AntiDepBreakMode AntiDepMode =
2890b57cec5SDimitry Andric     TargetSubtargetInfo::ANTIDEP_NONE;
2900b57cec5SDimitry Andric   SmallVector<const TargetRegisterClass*, 4> CriticalPathRCs;
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   // Check that post-RA scheduling is enabled for this target.
2930b57cec5SDimitry Andric   // This may upgrade the AntiDepMode.
2940b57cec5SDimitry Andric   if (!enablePostRAScheduler(Fn.getSubtarget(), PassConfig->getOptLevel(),
2950b57cec5SDimitry Andric                              AntiDepMode, CriticalPathRCs))
2960b57cec5SDimitry Andric     return false;
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   // Check for antidep breaking override...
2990b57cec5SDimitry Andric   if (EnableAntiDepBreaking.getPosition() > 0) {
3000b57cec5SDimitry Andric     AntiDepMode = (EnableAntiDepBreaking == "all")
3010b57cec5SDimitry Andric       ? TargetSubtargetInfo::ANTIDEP_ALL
3020b57cec5SDimitry Andric       : ((EnableAntiDepBreaking == "critical")
3030b57cec5SDimitry Andric          ? TargetSubtargetInfo::ANTIDEP_CRITICAL
3040b57cec5SDimitry Andric          : TargetSubtargetInfo::ANTIDEP_NONE);
3050b57cec5SDimitry Andric   }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "PostRAScheduler\n");
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   SchedulePostRATDList Scheduler(Fn, MLI, AA, RegClassInfo, AntiDepMode,
3100b57cec5SDimitry Andric                                  CriticalPathRCs);
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   // Loop over all of the basic blocks
3130b57cec5SDimitry Andric   for (auto &MBB : Fn) {
3140b57cec5SDimitry Andric #ifndef NDEBUG
3150b57cec5SDimitry Andric     // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod
3160b57cec5SDimitry Andric     if (DebugDiv > 0) {
3170b57cec5SDimitry Andric       static int bbcnt = 0;
3180b57cec5SDimitry Andric       if (bbcnt++ % DebugDiv != DebugMod)
3190b57cec5SDimitry Andric         continue;
3200b57cec5SDimitry Andric       dbgs() << "*** DEBUG scheduling " << Fn.getName() << ":"
3210b57cec5SDimitry Andric              << printMBBReference(MBB) << " ***\n";
3220b57cec5SDimitry Andric     }
3230b57cec5SDimitry Andric #endif
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric     // Initialize register live-range state for scheduling in this block.
3260b57cec5SDimitry Andric     Scheduler.startBlock(&MBB);
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric     // Schedule each sequence of instructions not interrupted by a label
3290b57cec5SDimitry Andric     // or anything else that effectively needs to shut down scheduling.
3300b57cec5SDimitry Andric     MachineBasicBlock::iterator Current = MBB.end();
3310b57cec5SDimitry Andric     unsigned Count = MBB.size(), CurrentCount = Count;
3320b57cec5SDimitry Andric     for (MachineBasicBlock::iterator I = Current; I != MBB.begin();) {
3330b57cec5SDimitry Andric       MachineInstr &MI = *std::prev(I);
3340b57cec5SDimitry Andric       --Count;
3350b57cec5SDimitry Andric       // Calls are not scheduling boundaries before register allocation, but
3360b57cec5SDimitry Andric       // post-ra we don't gain anything by scheduling across calls since we
3370b57cec5SDimitry Andric       // don't need to worry about register pressure.
3380b57cec5SDimitry Andric       if (MI.isCall() || TII->isSchedulingBoundary(MI, &MBB, Fn)) {
3390b57cec5SDimitry Andric         Scheduler.enterRegion(&MBB, I, Current, CurrentCount - Count);
3400b57cec5SDimitry Andric         Scheduler.setEndIndex(CurrentCount);
3410b57cec5SDimitry Andric         Scheduler.schedule();
3420b57cec5SDimitry Andric         Scheduler.exitRegion();
3430b57cec5SDimitry Andric         Scheduler.EmitSchedule();
3440b57cec5SDimitry Andric         Current = &MI;
3450b57cec5SDimitry Andric         CurrentCount = Count;
3460b57cec5SDimitry Andric         Scheduler.Observe(MI, CurrentCount);
3470b57cec5SDimitry Andric       }
3480b57cec5SDimitry Andric       I = MI;
3490b57cec5SDimitry Andric       if (MI.isBundle())
3500b57cec5SDimitry Andric         Count -= MI.getBundleSize();
3510b57cec5SDimitry Andric     }
3520b57cec5SDimitry Andric     assert(Count == 0 && "Instruction count mismatch!");
3530b57cec5SDimitry Andric     assert((MBB.begin() == Current || CurrentCount != 0) &&
3540b57cec5SDimitry Andric            "Instruction count mismatch!");
3550b57cec5SDimitry Andric     Scheduler.enterRegion(&MBB, MBB.begin(), Current, CurrentCount);
3560b57cec5SDimitry Andric     Scheduler.setEndIndex(CurrentCount);
3570b57cec5SDimitry Andric     Scheduler.schedule();
3580b57cec5SDimitry Andric     Scheduler.exitRegion();
3590b57cec5SDimitry Andric     Scheduler.EmitSchedule();
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric     // Clean up register live-range state.
3620b57cec5SDimitry Andric     Scheduler.finishBlock();
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric     // Update register kills
3650b57cec5SDimitry Andric     Scheduler.fixupKills(MBB);
3660b57cec5SDimitry Andric   }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   return true;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric /// StartBlock - Initialize register live-range state for scheduling in
3720b57cec5SDimitry Andric /// this block.
3730b57cec5SDimitry Andric ///
3740b57cec5SDimitry Andric void SchedulePostRATDList::startBlock(MachineBasicBlock *BB) {
3750b57cec5SDimitry Andric   // Call the superclass.
3760b57cec5SDimitry Andric   ScheduleDAGInstrs::startBlock(BB);
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   // Reset the hazard recognizer and anti-dep breaker.
3790b57cec5SDimitry Andric   HazardRec->Reset();
3800b57cec5SDimitry Andric   if (AntiDepBreak)
3810b57cec5SDimitry Andric     AntiDepBreak->StartBlock(BB);
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric /// Schedule - Schedule the instruction range using list scheduling.
3850b57cec5SDimitry Andric ///
3860b57cec5SDimitry Andric void SchedulePostRATDList::schedule() {
3870b57cec5SDimitry Andric   // Build the scheduling graph.
3880b57cec5SDimitry Andric   buildSchedGraph(AA);
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric   if (AntiDepBreak) {
3910b57cec5SDimitry Andric     unsigned Broken =
3920b57cec5SDimitry Andric       AntiDepBreak->BreakAntiDependencies(SUnits, RegionBegin, RegionEnd,
3930b57cec5SDimitry Andric                                           EndIndex, DbgValues);
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric     if (Broken != 0) {
3960b57cec5SDimitry Andric       // We made changes. Update the dependency graph.
3970b57cec5SDimitry Andric       // Theoretically we could update the graph in place:
3980b57cec5SDimitry Andric       // When a live range is changed to use a different register, remove
3990b57cec5SDimitry Andric       // the def's anti-dependence *and* output-dependence edges due to
4000b57cec5SDimitry Andric       // that register, and add new anti-dependence and output-dependence
4010b57cec5SDimitry Andric       // edges based on the next live range of the register.
4020b57cec5SDimitry Andric       ScheduleDAG::clearDAG();
4030b57cec5SDimitry Andric       buildSchedGraph(AA);
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric       NumFixedAnti += Broken;
4060b57cec5SDimitry Andric     }
4070b57cec5SDimitry Andric   }
4080b57cec5SDimitry Andric 
40906c3fb27SDimitry Andric   postProcessDAG();
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "********** List Scheduling **********\n");
4120b57cec5SDimitry Andric   LLVM_DEBUG(dump());
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   AvailableQueue.initNodes(SUnits);
4150b57cec5SDimitry Andric   ListScheduleTopDown();
4160b57cec5SDimitry Andric   AvailableQueue.releaseState();
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric /// Observe - Update liveness information to account for the current
4200b57cec5SDimitry Andric /// instruction, which will not be scheduled.
4210b57cec5SDimitry Andric ///
4220b57cec5SDimitry Andric void SchedulePostRATDList::Observe(MachineInstr &MI, unsigned Count) {
4230b57cec5SDimitry Andric   if (AntiDepBreak)
4240b57cec5SDimitry Andric     AntiDepBreak->Observe(MI, Count, EndIndex);
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric /// FinishBlock - Clean up register live-range state.
4280b57cec5SDimitry Andric ///
4290b57cec5SDimitry Andric void SchedulePostRATDList::finishBlock() {
4300b57cec5SDimitry Andric   if (AntiDepBreak)
4310b57cec5SDimitry Andric     AntiDepBreak->FinishBlock();
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   // Call the superclass.
4340b57cec5SDimitry Andric   ScheduleDAGInstrs::finishBlock();
4350b57cec5SDimitry Andric }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric /// Apply each ScheduleDAGMutation step in order.
43806c3fb27SDimitry Andric void SchedulePostRATDList::postProcessDAG() {
4390b57cec5SDimitry Andric   for (auto &M : Mutations)
4400b57cec5SDimitry Andric     M->apply(this);
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4440b57cec5SDimitry Andric //  Top-Down Scheduling
4450b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric /// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
4480b57cec5SDimitry Andric /// the PendingQueue if the count reaches zero.
4490b57cec5SDimitry Andric void SchedulePostRATDList::ReleaseSucc(SUnit *SU, SDep *SuccEdge) {
4500b57cec5SDimitry Andric   SUnit *SuccSU = SuccEdge->getSUnit();
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   if (SuccEdge->isWeak()) {
4530b57cec5SDimitry Andric     --SuccSU->WeakPredsLeft;
4540b57cec5SDimitry Andric     return;
4550b57cec5SDimitry Andric   }
4560b57cec5SDimitry Andric #ifndef NDEBUG
4570b57cec5SDimitry Andric   if (SuccSU->NumPredsLeft == 0) {
4580b57cec5SDimitry Andric     dbgs() << "*** Scheduling failed! ***\n";
4590b57cec5SDimitry Andric     dumpNode(*SuccSU);
4600b57cec5SDimitry Andric     dbgs() << " has been released too many times!\n";
4610b57cec5SDimitry Andric     llvm_unreachable(nullptr);
4620b57cec5SDimitry Andric   }
4630b57cec5SDimitry Andric #endif
4640b57cec5SDimitry Andric   --SuccSU->NumPredsLeft;
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   // Standard scheduler algorithms will recompute the depth of the successor
4670b57cec5SDimitry Andric   // here as such:
4680b57cec5SDimitry Andric   //   SuccSU->setDepthToAtLeast(SU->getDepth() + SuccEdge->getLatency());
4690b57cec5SDimitry Andric   //
4700b57cec5SDimitry Andric   // However, we lazily compute node depth instead. Note that
4710b57cec5SDimitry Andric   // ScheduleNodeTopDown has already updated the depth of this node which causes
4720b57cec5SDimitry Andric   // all descendents to be marked dirty. Setting the successor depth explicitly
4730b57cec5SDimitry Andric   // here would cause depth to be recomputed for all its ancestors. If the
4740b57cec5SDimitry Andric   // successor is not yet ready (because of a transitively redundant edge) then
4750b57cec5SDimitry Andric   // this causes depth computation to be quadratic in the size of the DAG.
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   // If all the node's predecessors are scheduled, this node is ready
4780b57cec5SDimitry Andric   // to be scheduled. Ignore the special ExitSU node.
4790b57cec5SDimitry Andric   if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU)
4800b57cec5SDimitry Andric     PendingQueue.push_back(SuccSU);
4810b57cec5SDimitry Andric }
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric /// ReleaseSuccessors - Call ReleaseSucc on each of SU's successors.
4840b57cec5SDimitry Andric void SchedulePostRATDList::ReleaseSuccessors(SUnit *SU) {
4850b57cec5SDimitry Andric   for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
4860b57cec5SDimitry Andric        I != E; ++I) {
4870b57cec5SDimitry Andric     ReleaseSucc(SU, &*I);
4880b57cec5SDimitry Andric   }
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric /// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
4920b57cec5SDimitry Andric /// count of its successors. If a successor pending count is zero, add it to
4930b57cec5SDimitry Andric /// the Available queue.
4940b57cec5SDimitry Andric void SchedulePostRATDList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
4950b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: ");
4960b57cec5SDimitry Andric   LLVM_DEBUG(dumpNode(*SU));
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   Sequence.push_back(SU);
4990b57cec5SDimitry Andric   assert(CurCycle >= SU->getDepth() &&
5000b57cec5SDimitry Andric          "Node scheduled above its depth!");
5010b57cec5SDimitry Andric   SU->setDepthToAtLeast(CurCycle);
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   ReleaseSuccessors(SU);
5040b57cec5SDimitry Andric   SU->isScheduled = true;
5050b57cec5SDimitry Andric   AvailableQueue.scheduledNode(SU);
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric /// emitNoop - Add a noop to the current instruction sequence.
5090b57cec5SDimitry Andric void SchedulePostRATDList::emitNoop(unsigned CurCycle) {
5100b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "*** Emitting noop in cycle " << CurCycle << '\n');
5110b57cec5SDimitry Andric   HazardRec->EmitNoop();
5120b57cec5SDimitry Andric   Sequence.push_back(nullptr);   // NULL here means noop
5130b57cec5SDimitry Andric   ++NumNoops;
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric /// ListScheduleTopDown - The main loop of list scheduling for top-down
5170b57cec5SDimitry Andric /// schedulers.
5180b57cec5SDimitry Andric void SchedulePostRATDList::ListScheduleTopDown() {
5190b57cec5SDimitry Andric   unsigned CurCycle = 0;
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   // We're scheduling top-down but we're visiting the regions in
5220b57cec5SDimitry Andric   // bottom-up order, so we don't know the hazards at the start of a
5230b57cec5SDimitry Andric   // region. So assume no hazards (this should usually be ok as most
5240b57cec5SDimitry Andric   // blocks are a single region).
5250b57cec5SDimitry Andric   HazardRec->Reset();
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   // Release any successors of the special Entry node.
5280b57cec5SDimitry Andric   ReleaseSuccessors(&EntrySU);
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   // Add all leaves to Available queue.
5310eae32dcSDimitry Andric   for (SUnit &SUnit : SUnits) {
5320b57cec5SDimitry Andric     // It is available if it has no predecessors.
5330eae32dcSDimitry Andric     if (!SUnit.NumPredsLeft && !SUnit.isAvailable) {
5340eae32dcSDimitry Andric       AvailableQueue.push(&SUnit);
5350eae32dcSDimitry Andric       SUnit.isAvailable = true;
5360b57cec5SDimitry Andric     }
5370b57cec5SDimitry Andric   }
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   // In any cycle where we can't schedule any instructions, we must
5400b57cec5SDimitry Andric   // stall or emit a noop, depending on the target.
5410b57cec5SDimitry Andric   bool CycleHasInsts = false;
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   // While Available queue is not empty, grab the node with the highest
5440b57cec5SDimitry Andric   // priority. If it is not ready put it back.  Schedule the node.
5450b57cec5SDimitry Andric   std::vector<SUnit*> NotReady;
5460b57cec5SDimitry Andric   Sequence.reserve(SUnits.size());
5470b57cec5SDimitry Andric   while (!AvailableQueue.empty() || !PendingQueue.empty()) {
5480b57cec5SDimitry Andric     // Check to see if any of the pending instructions are ready to issue.  If
5490b57cec5SDimitry Andric     // so, add them to the available queue.
5500b57cec5SDimitry Andric     unsigned MinDepth = ~0u;
5510b57cec5SDimitry Andric     for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
5520b57cec5SDimitry Andric       if (PendingQueue[i]->getDepth() <= CurCycle) {
5530b57cec5SDimitry Andric         AvailableQueue.push(PendingQueue[i]);
5540b57cec5SDimitry Andric         PendingQueue[i]->isAvailable = true;
5550b57cec5SDimitry Andric         PendingQueue[i] = PendingQueue.back();
5560b57cec5SDimitry Andric         PendingQueue.pop_back();
5570b57cec5SDimitry Andric         --i; --e;
5580b57cec5SDimitry Andric       } else if (PendingQueue[i]->getDepth() < MinDepth)
5590b57cec5SDimitry Andric         MinDepth = PendingQueue[i]->getDepth();
5600b57cec5SDimitry Andric     }
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\n*** Examining Available\n";
5630b57cec5SDimitry Andric                AvailableQueue.dump(this));
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric     SUnit *FoundSUnit = nullptr, *NotPreferredSUnit = nullptr;
5660b57cec5SDimitry Andric     bool HasNoopHazards = false;
5670b57cec5SDimitry Andric     while (!AvailableQueue.empty()) {
5680b57cec5SDimitry Andric       SUnit *CurSUnit = AvailableQueue.pop();
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric       ScheduleHazardRecognizer::HazardType HT =
5710b57cec5SDimitry Andric         HazardRec->getHazardType(CurSUnit, 0/*no stalls*/);
5720b57cec5SDimitry Andric       if (HT == ScheduleHazardRecognizer::NoHazard) {
5730b57cec5SDimitry Andric         if (HazardRec->ShouldPreferAnother(CurSUnit)) {
5740b57cec5SDimitry Andric           if (!NotPreferredSUnit) {
5750b57cec5SDimitry Andric             // If this is the first non-preferred node for this cycle, then
5760b57cec5SDimitry Andric             // record it and continue searching for a preferred node. If this
5770b57cec5SDimitry Andric             // is not the first non-preferred node, then treat it as though
5780b57cec5SDimitry Andric             // there had been a hazard.
5790b57cec5SDimitry Andric             NotPreferredSUnit = CurSUnit;
5800b57cec5SDimitry Andric             continue;
5810b57cec5SDimitry Andric           }
5820b57cec5SDimitry Andric         } else {
5830b57cec5SDimitry Andric           FoundSUnit = CurSUnit;
5840b57cec5SDimitry Andric           break;
5850b57cec5SDimitry Andric         }
5860b57cec5SDimitry Andric       }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric       // Remember if this is a noop hazard.
5890b57cec5SDimitry Andric       HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard;
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric       NotReady.push_back(CurSUnit);
5920b57cec5SDimitry Andric     }
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric     // If we have a non-preferred node, push it back onto the available list.
5950b57cec5SDimitry Andric     // If we did not find a preferred node, then schedule this first
5960b57cec5SDimitry Andric     // non-preferred node.
5970b57cec5SDimitry Andric     if (NotPreferredSUnit) {
5980b57cec5SDimitry Andric       if (!FoundSUnit) {
5990b57cec5SDimitry Andric         LLVM_DEBUG(
6000b57cec5SDimitry Andric             dbgs() << "*** Will schedule a non-preferred instruction...\n");
6010b57cec5SDimitry Andric         FoundSUnit = NotPreferredSUnit;
6020b57cec5SDimitry Andric       } else {
6030b57cec5SDimitry Andric         AvailableQueue.push(NotPreferredSUnit);
6040b57cec5SDimitry Andric       }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric       NotPreferredSUnit = nullptr;
6070b57cec5SDimitry Andric     }
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric     // Add the nodes that aren't ready back onto the available list.
6100b57cec5SDimitry Andric     if (!NotReady.empty()) {
6110b57cec5SDimitry Andric       AvailableQueue.push_all(NotReady);
6120b57cec5SDimitry Andric       NotReady.clear();
6130b57cec5SDimitry Andric     }
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric     // If we found a node to schedule...
6160b57cec5SDimitry Andric     if (FoundSUnit) {
6170b57cec5SDimitry Andric       // If we need to emit noops prior to this instruction, then do so.
6180b57cec5SDimitry Andric       unsigned NumPreNoops = HazardRec->PreEmitNoops(FoundSUnit);
6190b57cec5SDimitry Andric       for (unsigned i = 0; i != NumPreNoops; ++i)
6200b57cec5SDimitry Andric         emitNoop(CurCycle);
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric       // ... schedule the node...
6230b57cec5SDimitry Andric       ScheduleNodeTopDown(FoundSUnit, CurCycle);
6240b57cec5SDimitry Andric       HazardRec->EmitInstruction(FoundSUnit);
6250b57cec5SDimitry Andric       CycleHasInsts = true;
6260b57cec5SDimitry Andric       if (HazardRec->atIssueLimit()) {
6270b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "*** Max instructions per cycle " << CurCycle
6280b57cec5SDimitry Andric                           << '\n');
6290b57cec5SDimitry Andric         HazardRec->AdvanceCycle();
6300b57cec5SDimitry Andric         ++CurCycle;
6310b57cec5SDimitry Andric         CycleHasInsts = false;
6320b57cec5SDimitry Andric       }
6330b57cec5SDimitry Andric     } else {
6340b57cec5SDimitry Andric       if (CycleHasInsts) {
6350b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "*** Finished cycle " << CurCycle << '\n');
6360b57cec5SDimitry Andric         HazardRec->AdvanceCycle();
6370b57cec5SDimitry Andric       } else if (!HasNoopHazards) {
6380b57cec5SDimitry Andric         // Otherwise, we have a pipeline stall, but no other problem,
6390b57cec5SDimitry Andric         // just advance the current cycle and try again.
6400b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "*** Stall in cycle " << CurCycle << '\n');
6410b57cec5SDimitry Andric         HazardRec->AdvanceCycle();
6420b57cec5SDimitry Andric         ++NumStalls;
6430b57cec5SDimitry Andric       } else {
6440b57cec5SDimitry Andric         // Otherwise, we have no instructions to issue and we have instructions
6450b57cec5SDimitry Andric         // that will fault if we don't do this right.  This is the case for
6460b57cec5SDimitry Andric         // processors without pipeline interlocks and other cases.
6470b57cec5SDimitry Andric         emitNoop(CurCycle);
6480b57cec5SDimitry Andric       }
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric       ++CurCycle;
6510b57cec5SDimitry Andric       CycleHasInsts = false;
6520b57cec5SDimitry Andric     }
6530b57cec5SDimitry Andric   }
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric #ifndef NDEBUG
6560b57cec5SDimitry Andric   unsigned ScheduledNodes = VerifyScheduledDAG(/*isBottomUp=*/false);
6570eae32dcSDimitry Andric   unsigned Noops = llvm::count(Sequence, nullptr);
6580b57cec5SDimitry Andric   assert(Sequence.size() - Noops == ScheduledNodes &&
6590b57cec5SDimitry Andric          "The number of nodes scheduled doesn't match the expected number!");
6600b57cec5SDimitry Andric #endif // NDEBUG
6610b57cec5SDimitry Andric }
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric // EmitSchedule - Emit the machine code in scheduled order.
6640b57cec5SDimitry Andric void SchedulePostRATDList::EmitSchedule() {
6650b57cec5SDimitry Andric   RegionBegin = RegionEnd;
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   // If first instruction was a DBG_VALUE then put it back.
6680b57cec5SDimitry Andric   if (FirstDbgValue)
6690b57cec5SDimitry Andric     BB->splice(RegionEnd, BB, FirstDbgValue);
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric   // Then re-insert them according to the given schedule.
6720b57cec5SDimitry Andric   for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
6730b57cec5SDimitry Andric     if (SUnit *SU = Sequence[i])
6740b57cec5SDimitry Andric       BB->splice(RegionEnd, BB, SU->getInstr());
6750b57cec5SDimitry Andric     else
6760b57cec5SDimitry Andric       // Null SUnit* is a noop.
6770b57cec5SDimitry Andric       TII->insertNoop(*BB, RegionEnd);
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric     // Update the Begin iterator, as the first instruction in the block
6800b57cec5SDimitry Andric     // may have been scheduled later.
6810b57cec5SDimitry Andric     if (i == 0)
6820b57cec5SDimitry Andric       RegionBegin = std::prev(RegionEnd);
6830b57cec5SDimitry Andric   }
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric   // Reinsert any remaining debug_values.
6860b57cec5SDimitry Andric   for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
6870b57cec5SDimitry Andric          DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
6880b57cec5SDimitry Andric     std::pair<MachineInstr *, MachineInstr *> P = *std::prev(DI);
6890b57cec5SDimitry Andric     MachineInstr *DbgValue = P.first;
6900b57cec5SDimitry Andric     MachineBasicBlock::iterator OrigPrivMI = P.second;
6910b57cec5SDimitry Andric     BB->splice(++OrigPrivMI, BB, DbgValue);
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric   DbgValues.clear();
6940b57cec5SDimitry Andric   FirstDbgValue = nullptr;
6950b57cec5SDimitry Andric }
696