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;
PostRAScheduler()820b57cec5SDimitry Andric PostRAScheduler() : MachineFunctionPass(ID) {}
830b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const840b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
850b57cec5SDimitry Andric AU.setPreservesCFG();
860b57cec5SDimitry Andric AU.addRequired<AAResultsWrapperPass>();
870b57cec5SDimitry Andric AU.addRequired<TargetPassConfig>();
880b57cec5SDimitry Andric AU.addRequired<MachineDominatorTree>();
890b57cec5SDimitry Andric AU.addPreserved<MachineDominatorTree>();
900b57cec5SDimitry Andric AU.addRequired<MachineLoopInfo>();
910b57cec5SDimitry Andric AU.addPreserved<MachineLoopInfo>();
920b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric
getRequiredProperties() const950b57cec5SDimitry 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(
104*c9157d92SDimitry 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.
setEndIndex(unsigned EndIdx)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.
185fe013be4SDimitry 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
SchedulePostRATDList(MachineFunction & MF,MachineLoopInfo & MLI,AliasAnalysis * AA,const RegisterClassInfo & RCI,TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,SmallVectorImpl<const TargetRegisterClass * > & CriticalPathRCs)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
~SchedulePostRATDList()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.
enterRegion(MachineBasicBlock * bb,MachineBasicBlock::iterator begin,MachineBasicBlock::iterator end,unsigned regioninstrs)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.
exitRegion()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.
dumpSchedule() const2520b57cec5SDimitry 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
enablePostRAScheduler(const TargetSubtargetInfo & ST,CodeGenOptLevel OptLevel,TargetSubtargetInfo::AntiDepBreakMode & Mode,TargetSubtargetInfo::RegClassVector & CriticalPathRCs) const2620b57cec5SDimitry Andric bool PostRAScheduler::enablePostRAScheduler(
263*c9157d92SDimitry 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
runOnMachineFunction(MachineFunction & Fn)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();
2820b57cec5SDimitry Andric MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
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 ///
startBlock(MachineBasicBlock * BB)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 ///
schedule()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
409fe013be4SDimitry 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 ///
Observe(MachineInstr & MI,unsigned Count)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 ///
finishBlock()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.
postProcessDAG()438fe013be4SDimitry 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.
ReleaseSucc(SUnit * SU,SDep * SuccEdge)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.
ReleaseSuccessors(SUnit * SU)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.
ScheduleNodeTopDown(SUnit * SU,unsigned CurCycle)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.
emitNoop(unsigned CurCycle)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.
ListScheduleTopDown()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.
EmitSchedule()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