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