1*9880d681SAndroid Build Coastguard Worker //===----- SchedulePostRAList.cpp - list scheduler ------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This implements a top-down list scheduler, using standard algorithms.
11*9880d681SAndroid Build Coastguard Worker // The basic approach uses a priority queue of available nodes to schedule.
12*9880d681SAndroid Build Coastguard Worker // One at a time, nodes are taken from the priority queue (thus in priority
13*9880d681SAndroid Build Coastguard Worker // order), checked for legality to schedule, and emitted if legal.
14*9880d681SAndroid Build Coastguard Worker //
15*9880d681SAndroid Build Coastguard Worker // Nodes may not be legal to schedule either due to structural hazards (e.g.
16*9880d681SAndroid Build Coastguard Worker // pipeline or resource constraints) or because an input to the instruction has
17*9880d681SAndroid Build Coastguard Worker // not completed execution.
18*9880d681SAndroid Build Coastguard Worker //
19*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Worker #include "AggressiveAntiDepBreaker.h"
22*9880d681SAndroid Build Coastguard Worker #include "AntiDepBreaker.h"
23*9880d681SAndroid Build Coastguard Worker #include "CriticalAntiDepBreaker.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AliasAnalysis.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/LatencyPriorityQueue.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineDominators.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineLoopInfo.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterClassInfo.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleDAGInstrs.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SchedulerRegistry.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/TargetPassConfig.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetLowering.h"
44*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
45*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
46*9880d681SAndroid Build Coastguard Worker using namespace llvm;
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "post-RA-sched"
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker STATISTIC(NumNoops, "Number of noops inserted");
51*9880d681SAndroid Build Coastguard Worker STATISTIC(NumStalls, "Number of pipeline stalls");
52*9880d681SAndroid Build Coastguard Worker STATISTIC(NumFixedAnti, "Number of fixed anti-dependencies");
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker // Post-RA scheduling is enabled with
55*9880d681SAndroid Build Coastguard Worker // TargetSubtargetInfo.enablePostRAScheduler(). This flag can be used to
56*9880d681SAndroid Build Coastguard Worker // override the target.
57*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
58*9880d681SAndroid Build Coastguard Worker EnablePostRAScheduler("post-RA-scheduler",
59*9880d681SAndroid Build Coastguard Worker cl::desc("Enable scheduling after register allocation"),
60*9880d681SAndroid Build Coastguard Worker cl::init(false), cl::Hidden);
61*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string>
62*9880d681SAndroid Build Coastguard Worker EnableAntiDepBreaking("break-anti-dependencies",
63*9880d681SAndroid Build Coastguard Worker cl::desc("Break post-RA scheduling anti-dependencies: "
64*9880d681SAndroid Build Coastguard Worker "\"critical\", \"all\", or \"none\""),
65*9880d681SAndroid Build Coastguard Worker cl::init("none"), cl::Hidden);
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod
68*9880d681SAndroid Build Coastguard Worker static cl::opt<int>
69*9880d681SAndroid Build Coastguard Worker DebugDiv("postra-sched-debugdiv",
70*9880d681SAndroid Build Coastguard Worker cl::desc("Debug control MBBs that are scheduled"),
71*9880d681SAndroid Build Coastguard Worker cl::init(0), cl::Hidden);
72*9880d681SAndroid Build Coastguard Worker static cl::opt<int>
73*9880d681SAndroid Build Coastguard Worker DebugMod("postra-sched-debugmod",
74*9880d681SAndroid Build Coastguard Worker cl::desc("Debug control MBBs that are scheduled"),
75*9880d681SAndroid Build Coastguard Worker cl::init(0), cl::Hidden);
76*9880d681SAndroid Build Coastguard Worker
~AntiDepBreaker()77*9880d681SAndroid Build Coastguard Worker AntiDepBreaker::~AntiDepBreaker() { }
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Worker namespace {
80*9880d681SAndroid Build Coastguard Worker class PostRAScheduler : public MachineFunctionPass {
81*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII;
82*9880d681SAndroid Build Coastguard Worker RegisterClassInfo RegClassInfo;
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Worker public:
85*9880d681SAndroid Build Coastguard Worker static char ID;
PostRAScheduler()86*9880d681SAndroid Build Coastguard Worker PostRAScheduler() : MachineFunctionPass(ID) {}
87*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const88*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
89*9880d681SAndroid Build Coastguard Worker AU.setPreservesCFG();
90*9880d681SAndroid Build Coastguard Worker AU.addRequired<AAResultsWrapperPass>();
91*9880d681SAndroid Build Coastguard Worker AU.addRequired<TargetPassConfig>();
92*9880d681SAndroid Build Coastguard Worker AU.addRequired<MachineDominatorTree>();
93*9880d681SAndroid Build Coastguard Worker AU.addPreserved<MachineDominatorTree>();
94*9880d681SAndroid Build Coastguard Worker AU.addRequired<MachineLoopInfo>();
95*9880d681SAndroid Build Coastguard Worker AU.addPreserved<MachineLoopInfo>();
96*9880d681SAndroid Build Coastguard Worker MachineFunctionPass::getAnalysisUsage(AU);
97*9880d681SAndroid Build Coastguard Worker }
98*9880d681SAndroid Build Coastguard Worker
getRequiredProperties() const99*9880d681SAndroid Build Coastguard Worker MachineFunctionProperties getRequiredProperties() const override {
100*9880d681SAndroid Build Coastguard Worker return MachineFunctionProperties().set(
101*9880d681SAndroid Build Coastguard Worker MachineFunctionProperties::Property::AllVRegsAllocated);
102*9880d681SAndroid Build Coastguard Worker }
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &Fn) override;
105*9880d681SAndroid Build Coastguard Worker
106*9880d681SAndroid Build Coastguard Worker private:
107*9880d681SAndroid Build Coastguard Worker bool enablePostRAScheduler(
108*9880d681SAndroid Build Coastguard Worker const TargetSubtargetInfo &ST, CodeGenOpt::Level OptLevel,
109*9880d681SAndroid Build Coastguard Worker TargetSubtargetInfo::AntiDepBreakMode &Mode,
110*9880d681SAndroid Build Coastguard Worker TargetSubtargetInfo::RegClassVector &CriticalPathRCs) const;
111*9880d681SAndroid Build Coastguard Worker };
112*9880d681SAndroid Build Coastguard Worker char PostRAScheduler::ID = 0;
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker class SchedulePostRATDList : public ScheduleDAGInstrs {
115*9880d681SAndroid Build Coastguard Worker /// AvailableQueue - The priority queue to use for the available SUnits.
116*9880d681SAndroid Build Coastguard Worker ///
117*9880d681SAndroid Build Coastguard Worker LatencyPriorityQueue AvailableQueue;
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker /// PendingQueue - This contains all of the instructions whose operands have
120*9880d681SAndroid Build Coastguard Worker /// been issued, but their results are not ready yet (due to the latency of
121*9880d681SAndroid Build Coastguard Worker /// the operation). Once the operands becomes available, the instruction is
122*9880d681SAndroid Build Coastguard Worker /// added to the AvailableQueue.
123*9880d681SAndroid Build Coastguard Worker std::vector<SUnit*> PendingQueue;
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker /// HazardRec - The hazard recognizer to use.
126*9880d681SAndroid Build Coastguard Worker ScheduleHazardRecognizer *HazardRec;
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker /// AntiDepBreak - Anti-dependence breaking object, or NULL if none
129*9880d681SAndroid Build Coastguard Worker AntiDepBreaker *AntiDepBreak;
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker /// AA - AliasAnalysis for making memory reference queries.
132*9880d681SAndroid Build Coastguard Worker AliasAnalysis *AA;
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker /// The schedule. Null SUnit*'s represent noop instructions.
135*9880d681SAndroid Build Coastguard Worker std::vector<SUnit*> Sequence;
136*9880d681SAndroid Build Coastguard Worker
137*9880d681SAndroid Build Coastguard Worker /// Ordered list of DAG postprocessing steps.
138*9880d681SAndroid Build Coastguard Worker std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker /// The index in BB of RegionEnd.
141*9880d681SAndroid Build Coastguard Worker ///
142*9880d681SAndroid Build Coastguard Worker /// This is the instruction number from the top of the current block, not
143*9880d681SAndroid Build Coastguard Worker /// the SlotIndex. It is only used by the AntiDepBreaker.
144*9880d681SAndroid Build Coastguard Worker unsigned EndIndex;
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker public:
147*9880d681SAndroid Build Coastguard Worker SchedulePostRATDList(
148*9880d681SAndroid Build Coastguard Worker MachineFunction &MF, MachineLoopInfo &MLI, AliasAnalysis *AA,
149*9880d681SAndroid Build Coastguard Worker const RegisterClassInfo &,
150*9880d681SAndroid Build Coastguard Worker TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,
151*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<const TargetRegisterClass *> &CriticalPathRCs);
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker ~SchedulePostRATDList() override;
154*9880d681SAndroid Build Coastguard Worker
155*9880d681SAndroid Build Coastguard Worker /// startBlock - Initialize register live-range state for scheduling in
156*9880d681SAndroid Build Coastguard Worker /// this block.
157*9880d681SAndroid Build Coastguard Worker ///
158*9880d681SAndroid Build Coastguard Worker void startBlock(MachineBasicBlock *BB) override;
159*9880d681SAndroid Build Coastguard Worker
160*9880d681SAndroid Build Coastguard Worker // Set the index of RegionEnd within the current BB.
setEndIndex(unsigned EndIdx)161*9880d681SAndroid Build Coastguard Worker void setEndIndex(unsigned EndIdx) { EndIndex = EndIdx; }
162*9880d681SAndroid Build Coastguard Worker
163*9880d681SAndroid Build Coastguard Worker /// Initialize the scheduler state for the next scheduling region.
164*9880d681SAndroid Build Coastguard Worker void enterRegion(MachineBasicBlock *bb,
165*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator begin,
166*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator end,
167*9880d681SAndroid Build Coastguard Worker unsigned regioninstrs) override;
168*9880d681SAndroid Build Coastguard Worker
169*9880d681SAndroid Build Coastguard Worker /// Notify that the scheduler has finished scheduling the current region.
170*9880d681SAndroid Build Coastguard Worker void exitRegion() override;
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker /// Schedule - Schedule the instruction range using list scheduling.
173*9880d681SAndroid Build Coastguard Worker ///
174*9880d681SAndroid Build Coastguard Worker void schedule() override;
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker void EmitSchedule();
177*9880d681SAndroid Build Coastguard Worker
178*9880d681SAndroid Build Coastguard Worker /// Observe - Update liveness information to account for the current
179*9880d681SAndroid Build Coastguard Worker /// instruction, which will not be scheduled.
180*9880d681SAndroid Build Coastguard Worker ///
181*9880d681SAndroid Build Coastguard Worker void Observe(MachineInstr &MI, unsigned Count);
182*9880d681SAndroid Build Coastguard Worker
183*9880d681SAndroid Build Coastguard Worker /// finishBlock - Clean up register live-range state.
184*9880d681SAndroid Build Coastguard Worker ///
185*9880d681SAndroid Build Coastguard Worker void finishBlock() override;
186*9880d681SAndroid Build Coastguard Worker
187*9880d681SAndroid Build Coastguard Worker private:
188*9880d681SAndroid Build Coastguard Worker /// Apply each ScheduleDAGMutation step in order.
189*9880d681SAndroid Build Coastguard Worker void postprocessDAG();
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker void ReleaseSucc(SUnit *SU, SDep *SuccEdge);
192*9880d681SAndroid Build Coastguard Worker void ReleaseSuccessors(SUnit *SU);
193*9880d681SAndroid Build Coastguard Worker void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle);
194*9880d681SAndroid Build Coastguard Worker void ListScheduleTopDown();
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker void dumpSchedule() const;
197*9880d681SAndroid Build Coastguard Worker void emitNoop(unsigned CurCycle);
198*9880d681SAndroid Build Coastguard Worker };
199*9880d681SAndroid Build Coastguard Worker }
200*9880d681SAndroid Build Coastguard Worker
201*9880d681SAndroid Build Coastguard Worker char &llvm::PostRASchedulerID = PostRAScheduler::ID;
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(PostRAScheduler, "post-RA-sched",
204*9880d681SAndroid Build Coastguard Worker "Post RA top-down list latency scheduler", false, false)
205*9880d681SAndroid Build Coastguard Worker
SchedulePostRATDList(MachineFunction & MF,MachineLoopInfo & MLI,AliasAnalysis * AA,const RegisterClassInfo & RCI,TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,SmallVectorImpl<const TargetRegisterClass * > & CriticalPathRCs)206*9880d681SAndroid Build Coastguard Worker SchedulePostRATDList::SchedulePostRATDList(
207*9880d681SAndroid Build Coastguard Worker MachineFunction &MF, MachineLoopInfo &MLI, AliasAnalysis *AA,
208*9880d681SAndroid Build Coastguard Worker const RegisterClassInfo &RCI,
209*9880d681SAndroid Build Coastguard Worker TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,
210*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<const TargetRegisterClass *> &CriticalPathRCs)
211*9880d681SAndroid Build Coastguard Worker : ScheduleDAGInstrs(MF, &MLI), AA(AA), EndIndex(0) {
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker const InstrItineraryData *InstrItins =
214*9880d681SAndroid Build Coastguard Worker MF.getSubtarget().getInstrItineraryData();
215*9880d681SAndroid Build Coastguard Worker HazardRec =
216*9880d681SAndroid Build Coastguard Worker MF.getSubtarget().getInstrInfo()->CreateTargetPostRAHazardRecognizer(
217*9880d681SAndroid Build Coastguard Worker InstrItins, this);
218*9880d681SAndroid Build Coastguard Worker MF.getSubtarget().getPostRAMutations(Mutations);
219*9880d681SAndroid Build Coastguard Worker
220*9880d681SAndroid Build Coastguard Worker assert((AntiDepMode == TargetSubtargetInfo::ANTIDEP_NONE ||
221*9880d681SAndroid Build Coastguard Worker MRI.tracksLiveness()) &&
222*9880d681SAndroid Build Coastguard Worker "Live-ins must be accurate for anti-dependency breaking");
223*9880d681SAndroid Build Coastguard Worker AntiDepBreak =
224*9880d681SAndroid Build Coastguard Worker ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_ALL) ?
225*9880d681SAndroid Build Coastguard Worker (AntiDepBreaker *)new AggressiveAntiDepBreaker(MF, RCI, CriticalPathRCs) :
226*9880d681SAndroid Build Coastguard Worker ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_CRITICAL) ?
227*9880d681SAndroid Build Coastguard Worker (AntiDepBreaker *)new CriticalAntiDepBreaker(MF, RCI) : nullptr));
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker
~SchedulePostRATDList()230*9880d681SAndroid Build Coastguard Worker SchedulePostRATDList::~SchedulePostRATDList() {
231*9880d681SAndroid Build Coastguard Worker delete HazardRec;
232*9880d681SAndroid Build Coastguard Worker delete AntiDepBreak;
233*9880d681SAndroid Build Coastguard Worker }
234*9880d681SAndroid Build Coastguard Worker
235*9880d681SAndroid Build Coastguard Worker /// Initialize state associated with the next scheduling region.
enterRegion(MachineBasicBlock * bb,MachineBasicBlock::iterator begin,MachineBasicBlock::iterator end,unsigned regioninstrs)236*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::enterRegion(MachineBasicBlock *bb,
237*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator begin,
238*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator end,
239*9880d681SAndroid Build Coastguard Worker unsigned regioninstrs) {
240*9880d681SAndroid Build Coastguard Worker ScheduleDAGInstrs::enterRegion(bb, begin, end, regioninstrs);
241*9880d681SAndroid Build Coastguard Worker Sequence.clear();
242*9880d681SAndroid Build Coastguard Worker }
243*9880d681SAndroid Build Coastguard Worker
244*9880d681SAndroid Build Coastguard Worker /// Print the schedule before exiting the region.
exitRegion()245*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::exitRegion() {
246*9880d681SAndroid Build Coastguard Worker DEBUG({
247*9880d681SAndroid Build Coastguard Worker dbgs() << "*** Final schedule ***\n";
248*9880d681SAndroid Build Coastguard Worker dumpSchedule();
249*9880d681SAndroid Build Coastguard Worker dbgs() << '\n';
250*9880d681SAndroid Build Coastguard Worker });
251*9880d681SAndroid Build Coastguard Worker ScheduleDAGInstrs::exitRegion();
252*9880d681SAndroid Build Coastguard Worker }
253*9880d681SAndroid Build Coastguard Worker
254*9880d681SAndroid Build Coastguard Worker #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
255*9880d681SAndroid Build Coastguard Worker /// dumpSchedule - dump the scheduled Sequence.
dumpSchedule() const256*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::dumpSchedule() const {
257*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
258*9880d681SAndroid Build Coastguard Worker if (SUnit *SU = Sequence[i])
259*9880d681SAndroid Build Coastguard Worker SU->dump(this);
260*9880d681SAndroid Build Coastguard Worker else
261*9880d681SAndroid Build Coastguard Worker dbgs() << "**** NOOP ****\n";
262*9880d681SAndroid Build Coastguard Worker }
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker #endif
265*9880d681SAndroid Build Coastguard Worker
enablePostRAScheduler(const TargetSubtargetInfo & ST,CodeGenOpt::Level OptLevel,TargetSubtargetInfo::AntiDepBreakMode & Mode,TargetSubtargetInfo::RegClassVector & CriticalPathRCs) const266*9880d681SAndroid Build Coastguard Worker bool PostRAScheduler::enablePostRAScheduler(
267*9880d681SAndroid Build Coastguard Worker const TargetSubtargetInfo &ST,
268*9880d681SAndroid Build Coastguard Worker CodeGenOpt::Level OptLevel,
269*9880d681SAndroid Build Coastguard Worker TargetSubtargetInfo::AntiDepBreakMode &Mode,
270*9880d681SAndroid Build Coastguard Worker TargetSubtargetInfo::RegClassVector &CriticalPathRCs) const {
271*9880d681SAndroid Build Coastguard Worker Mode = ST.getAntiDepBreakMode();
272*9880d681SAndroid Build Coastguard Worker ST.getCriticalPathRCs(CriticalPathRCs);
273*9880d681SAndroid Build Coastguard Worker
274*9880d681SAndroid Build Coastguard Worker // Check for explicit enable/disable of post-ra scheduling.
275*9880d681SAndroid Build Coastguard Worker if (EnablePostRAScheduler.getPosition() > 0)
276*9880d681SAndroid Build Coastguard Worker return EnablePostRAScheduler;
277*9880d681SAndroid Build Coastguard Worker
278*9880d681SAndroid Build Coastguard Worker return ST.enablePostRAScheduler() &&
279*9880d681SAndroid Build Coastguard Worker OptLevel >= ST.getOptLevelToEnablePostRAScheduler();
280*9880d681SAndroid Build Coastguard Worker }
281*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & Fn)282*9880d681SAndroid Build Coastguard Worker bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
283*9880d681SAndroid Build Coastguard Worker if (skipFunction(*Fn.getFunction()))
284*9880d681SAndroid Build Coastguard Worker return false;
285*9880d681SAndroid Build Coastguard Worker
286*9880d681SAndroid Build Coastguard Worker TII = Fn.getSubtarget().getInstrInfo();
287*9880d681SAndroid Build Coastguard Worker MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
288*9880d681SAndroid Build Coastguard Worker AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
289*9880d681SAndroid Build Coastguard Worker TargetPassConfig *PassConfig = &getAnalysis<TargetPassConfig>();
290*9880d681SAndroid Build Coastguard Worker
291*9880d681SAndroid Build Coastguard Worker RegClassInfo.runOnMachineFunction(Fn);
292*9880d681SAndroid Build Coastguard Worker
293*9880d681SAndroid Build Coastguard Worker TargetSubtargetInfo::AntiDepBreakMode AntiDepMode =
294*9880d681SAndroid Build Coastguard Worker TargetSubtargetInfo::ANTIDEP_NONE;
295*9880d681SAndroid Build Coastguard Worker SmallVector<const TargetRegisterClass*, 4> CriticalPathRCs;
296*9880d681SAndroid Build Coastguard Worker
297*9880d681SAndroid Build Coastguard Worker // Check that post-RA scheduling is enabled for this target.
298*9880d681SAndroid Build Coastguard Worker // This may upgrade the AntiDepMode.
299*9880d681SAndroid Build Coastguard Worker if (!enablePostRAScheduler(Fn.getSubtarget(), PassConfig->getOptLevel(),
300*9880d681SAndroid Build Coastguard Worker AntiDepMode, CriticalPathRCs))
301*9880d681SAndroid Build Coastguard Worker return false;
302*9880d681SAndroid Build Coastguard Worker
303*9880d681SAndroid Build Coastguard Worker // Check for antidep breaking override...
304*9880d681SAndroid Build Coastguard Worker if (EnableAntiDepBreaking.getPosition() > 0) {
305*9880d681SAndroid Build Coastguard Worker AntiDepMode = (EnableAntiDepBreaking == "all")
306*9880d681SAndroid Build Coastguard Worker ? TargetSubtargetInfo::ANTIDEP_ALL
307*9880d681SAndroid Build Coastguard Worker : ((EnableAntiDepBreaking == "critical")
308*9880d681SAndroid Build Coastguard Worker ? TargetSubtargetInfo::ANTIDEP_CRITICAL
309*9880d681SAndroid Build Coastguard Worker : TargetSubtargetInfo::ANTIDEP_NONE);
310*9880d681SAndroid Build Coastguard Worker }
311*9880d681SAndroid Build Coastguard Worker
312*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "PostRAScheduler\n");
313*9880d681SAndroid Build Coastguard Worker
314*9880d681SAndroid Build Coastguard Worker SchedulePostRATDList Scheduler(Fn, MLI, AA, RegClassInfo, AntiDepMode,
315*9880d681SAndroid Build Coastguard Worker CriticalPathRCs);
316*9880d681SAndroid Build Coastguard Worker
317*9880d681SAndroid Build Coastguard Worker // Loop over all of the basic blocks
318*9880d681SAndroid Build Coastguard Worker for (auto &MBB : Fn) {
319*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
320*9880d681SAndroid Build Coastguard Worker // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod
321*9880d681SAndroid Build Coastguard Worker if (DebugDiv > 0) {
322*9880d681SAndroid Build Coastguard Worker static int bbcnt = 0;
323*9880d681SAndroid Build Coastguard Worker if (bbcnt++ % DebugDiv != DebugMod)
324*9880d681SAndroid Build Coastguard Worker continue;
325*9880d681SAndroid Build Coastguard Worker dbgs() << "*** DEBUG scheduling " << Fn.getName()
326*9880d681SAndroid Build Coastguard Worker << ":BB#" << MBB.getNumber() << " ***\n";
327*9880d681SAndroid Build Coastguard Worker }
328*9880d681SAndroid Build Coastguard Worker #endif
329*9880d681SAndroid Build Coastguard Worker
330*9880d681SAndroid Build Coastguard Worker // Initialize register live-range state for scheduling in this block.
331*9880d681SAndroid Build Coastguard Worker Scheduler.startBlock(&MBB);
332*9880d681SAndroid Build Coastguard Worker
333*9880d681SAndroid Build Coastguard Worker // Schedule each sequence of instructions not interrupted by a label
334*9880d681SAndroid Build Coastguard Worker // or anything else that effectively needs to shut down scheduling.
335*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator Current = MBB.end();
336*9880d681SAndroid Build Coastguard Worker unsigned Count = MBB.size(), CurrentCount = Count;
337*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator I = Current; I != MBB.begin();) {
338*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *std::prev(I);
339*9880d681SAndroid Build Coastguard Worker --Count;
340*9880d681SAndroid Build Coastguard Worker // Calls are not scheduling boundaries before register allocation, but
341*9880d681SAndroid Build Coastguard Worker // post-ra we don't gain anything by scheduling across calls since we
342*9880d681SAndroid Build Coastguard Worker // don't need to worry about register pressure.
343*9880d681SAndroid Build Coastguard Worker if (MI.isCall() || TII->isSchedulingBoundary(MI, &MBB, Fn)) {
344*9880d681SAndroid Build Coastguard Worker Scheduler.enterRegion(&MBB, I, Current, CurrentCount - Count);
345*9880d681SAndroid Build Coastguard Worker Scheduler.setEndIndex(CurrentCount);
346*9880d681SAndroid Build Coastguard Worker Scheduler.schedule();
347*9880d681SAndroid Build Coastguard Worker Scheduler.exitRegion();
348*9880d681SAndroid Build Coastguard Worker Scheduler.EmitSchedule();
349*9880d681SAndroid Build Coastguard Worker Current = &MI;
350*9880d681SAndroid Build Coastguard Worker CurrentCount = Count;
351*9880d681SAndroid Build Coastguard Worker Scheduler.Observe(MI, CurrentCount);
352*9880d681SAndroid Build Coastguard Worker }
353*9880d681SAndroid Build Coastguard Worker I = MI;
354*9880d681SAndroid Build Coastguard Worker if (MI.isBundle())
355*9880d681SAndroid Build Coastguard Worker Count -= MI.getBundleSize();
356*9880d681SAndroid Build Coastguard Worker }
357*9880d681SAndroid Build Coastguard Worker assert(Count == 0 && "Instruction count mismatch!");
358*9880d681SAndroid Build Coastguard Worker assert((MBB.begin() == Current || CurrentCount != 0) &&
359*9880d681SAndroid Build Coastguard Worker "Instruction count mismatch!");
360*9880d681SAndroid Build Coastguard Worker Scheduler.enterRegion(&MBB, MBB.begin(), Current, CurrentCount);
361*9880d681SAndroid Build Coastguard Worker Scheduler.setEndIndex(CurrentCount);
362*9880d681SAndroid Build Coastguard Worker Scheduler.schedule();
363*9880d681SAndroid Build Coastguard Worker Scheduler.exitRegion();
364*9880d681SAndroid Build Coastguard Worker Scheduler.EmitSchedule();
365*9880d681SAndroid Build Coastguard Worker
366*9880d681SAndroid Build Coastguard Worker // Clean up register live-range state.
367*9880d681SAndroid Build Coastguard Worker Scheduler.finishBlock();
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker // Update register kills
370*9880d681SAndroid Build Coastguard Worker Scheduler.fixupKills(&MBB);
371*9880d681SAndroid Build Coastguard Worker }
372*9880d681SAndroid Build Coastguard Worker
373*9880d681SAndroid Build Coastguard Worker return true;
374*9880d681SAndroid Build Coastguard Worker }
375*9880d681SAndroid Build Coastguard Worker
376*9880d681SAndroid Build Coastguard Worker /// StartBlock - Initialize register live-range state for scheduling in
377*9880d681SAndroid Build Coastguard Worker /// this block.
378*9880d681SAndroid Build Coastguard Worker ///
startBlock(MachineBasicBlock * BB)379*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::startBlock(MachineBasicBlock *BB) {
380*9880d681SAndroid Build Coastguard Worker // Call the superclass.
381*9880d681SAndroid Build Coastguard Worker ScheduleDAGInstrs::startBlock(BB);
382*9880d681SAndroid Build Coastguard Worker
383*9880d681SAndroid Build Coastguard Worker // Reset the hazard recognizer and anti-dep breaker.
384*9880d681SAndroid Build Coastguard Worker HazardRec->Reset();
385*9880d681SAndroid Build Coastguard Worker if (AntiDepBreak)
386*9880d681SAndroid Build Coastguard Worker AntiDepBreak->StartBlock(BB);
387*9880d681SAndroid Build Coastguard Worker }
388*9880d681SAndroid Build Coastguard Worker
389*9880d681SAndroid Build Coastguard Worker /// Schedule - Schedule the instruction range using list scheduling.
390*9880d681SAndroid Build Coastguard Worker ///
schedule()391*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::schedule() {
392*9880d681SAndroid Build Coastguard Worker // Build the scheduling graph.
393*9880d681SAndroid Build Coastguard Worker buildSchedGraph(AA);
394*9880d681SAndroid Build Coastguard Worker
395*9880d681SAndroid Build Coastguard Worker if (AntiDepBreak) {
396*9880d681SAndroid Build Coastguard Worker unsigned Broken =
397*9880d681SAndroid Build Coastguard Worker AntiDepBreak->BreakAntiDependencies(SUnits, RegionBegin, RegionEnd,
398*9880d681SAndroid Build Coastguard Worker EndIndex, DbgValues);
399*9880d681SAndroid Build Coastguard Worker
400*9880d681SAndroid Build Coastguard Worker if (Broken != 0) {
401*9880d681SAndroid Build Coastguard Worker // We made changes. Update the dependency graph.
402*9880d681SAndroid Build Coastguard Worker // Theoretically we could update the graph in place:
403*9880d681SAndroid Build Coastguard Worker // When a live range is changed to use a different register, remove
404*9880d681SAndroid Build Coastguard Worker // the def's anti-dependence *and* output-dependence edges due to
405*9880d681SAndroid Build Coastguard Worker // that register, and add new anti-dependence and output-dependence
406*9880d681SAndroid Build Coastguard Worker // edges based on the next live range of the register.
407*9880d681SAndroid Build Coastguard Worker ScheduleDAG::clearDAG();
408*9880d681SAndroid Build Coastguard Worker buildSchedGraph(AA);
409*9880d681SAndroid Build Coastguard Worker
410*9880d681SAndroid Build Coastguard Worker NumFixedAnti += Broken;
411*9880d681SAndroid Build Coastguard Worker }
412*9880d681SAndroid Build Coastguard Worker }
413*9880d681SAndroid Build Coastguard Worker
414*9880d681SAndroid Build Coastguard Worker postprocessDAG();
415*9880d681SAndroid Build Coastguard Worker
416*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "********** List Scheduling **********\n");
417*9880d681SAndroid Build Coastguard Worker DEBUG(
418*9880d681SAndroid Build Coastguard Worker for (const SUnit &SU : SUnits) {
419*9880d681SAndroid Build Coastguard Worker SU.dumpAll(this);
420*9880d681SAndroid Build Coastguard Worker dbgs() << '\n';
421*9880d681SAndroid Build Coastguard Worker }
422*9880d681SAndroid Build Coastguard Worker );
423*9880d681SAndroid Build Coastguard Worker
424*9880d681SAndroid Build Coastguard Worker AvailableQueue.initNodes(SUnits);
425*9880d681SAndroid Build Coastguard Worker ListScheduleTopDown();
426*9880d681SAndroid Build Coastguard Worker AvailableQueue.releaseState();
427*9880d681SAndroid Build Coastguard Worker }
428*9880d681SAndroid Build Coastguard Worker
429*9880d681SAndroid Build Coastguard Worker /// Observe - Update liveness information to account for the current
430*9880d681SAndroid Build Coastguard Worker /// instruction, which will not be scheduled.
431*9880d681SAndroid Build Coastguard Worker ///
Observe(MachineInstr & MI,unsigned Count)432*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::Observe(MachineInstr &MI, unsigned Count) {
433*9880d681SAndroid Build Coastguard Worker if (AntiDepBreak)
434*9880d681SAndroid Build Coastguard Worker AntiDepBreak->Observe(MI, Count, EndIndex);
435*9880d681SAndroid Build Coastguard Worker }
436*9880d681SAndroid Build Coastguard Worker
437*9880d681SAndroid Build Coastguard Worker /// FinishBlock - Clean up register live-range state.
438*9880d681SAndroid Build Coastguard Worker ///
finishBlock()439*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::finishBlock() {
440*9880d681SAndroid Build Coastguard Worker if (AntiDepBreak)
441*9880d681SAndroid Build Coastguard Worker AntiDepBreak->FinishBlock();
442*9880d681SAndroid Build Coastguard Worker
443*9880d681SAndroid Build Coastguard Worker // Call the superclass.
444*9880d681SAndroid Build Coastguard Worker ScheduleDAGInstrs::finishBlock();
445*9880d681SAndroid Build Coastguard Worker }
446*9880d681SAndroid Build Coastguard Worker
447*9880d681SAndroid Build Coastguard Worker /// Apply each ScheduleDAGMutation step in order.
postprocessDAG()448*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::postprocessDAG() {
449*9880d681SAndroid Build Coastguard Worker for (auto &M : Mutations)
450*9880d681SAndroid Build Coastguard Worker M->apply(this);
451*9880d681SAndroid Build Coastguard Worker }
452*9880d681SAndroid Build Coastguard Worker
453*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
454*9880d681SAndroid Build Coastguard Worker // Top-Down Scheduling
455*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
456*9880d681SAndroid Build Coastguard Worker
457*9880d681SAndroid Build Coastguard Worker /// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
458*9880d681SAndroid Build Coastguard Worker /// the PendingQueue if the count reaches zero.
ReleaseSucc(SUnit * SU,SDep * SuccEdge)459*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::ReleaseSucc(SUnit *SU, SDep *SuccEdge) {
460*9880d681SAndroid Build Coastguard Worker SUnit *SuccSU = SuccEdge->getSUnit();
461*9880d681SAndroid Build Coastguard Worker
462*9880d681SAndroid Build Coastguard Worker if (SuccEdge->isWeak()) {
463*9880d681SAndroid Build Coastguard Worker --SuccSU->WeakPredsLeft;
464*9880d681SAndroid Build Coastguard Worker return;
465*9880d681SAndroid Build Coastguard Worker }
466*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
467*9880d681SAndroid Build Coastguard Worker if (SuccSU->NumPredsLeft == 0) {
468*9880d681SAndroid Build Coastguard Worker dbgs() << "*** Scheduling failed! ***\n";
469*9880d681SAndroid Build Coastguard Worker SuccSU->dump(this);
470*9880d681SAndroid Build Coastguard Worker dbgs() << " has been released too many times!\n";
471*9880d681SAndroid Build Coastguard Worker llvm_unreachable(nullptr);
472*9880d681SAndroid Build Coastguard Worker }
473*9880d681SAndroid Build Coastguard Worker #endif
474*9880d681SAndroid Build Coastguard Worker --SuccSU->NumPredsLeft;
475*9880d681SAndroid Build Coastguard Worker
476*9880d681SAndroid Build Coastguard Worker // Standard scheduler algorithms will recompute the depth of the successor
477*9880d681SAndroid Build Coastguard Worker // here as such:
478*9880d681SAndroid Build Coastguard Worker // SuccSU->setDepthToAtLeast(SU->getDepth() + SuccEdge->getLatency());
479*9880d681SAndroid Build Coastguard Worker //
480*9880d681SAndroid Build Coastguard Worker // However, we lazily compute node depth instead. Note that
481*9880d681SAndroid Build Coastguard Worker // ScheduleNodeTopDown has already updated the depth of this node which causes
482*9880d681SAndroid Build Coastguard Worker // all descendents to be marked dirty. Setting the successor depth explicitly
483*9880d681SAndroid Build Coastguard Worker // here would cause depth to be recomputed for all its ancestors. If the
484*9880d681SAndroid Build Coastguard Worker // successor is not yet ready (because of a transitively redundant edge) then
485*9880d681SAndroid Build Coastguard Worker // this causes depth computation to be quadratic in the size of the DAG.
486*9880d681SAndroid Build Coastguard Worker
487*9880d681SAndroid Build Coastguard Worker // If all the node's predecessors are scheduled, this node is ready
488*9880d681SAndroid Build Coastguard Worker // to be scheduled. Ignore the special ExitSU node.
489*9880d681SAndroid Build Coastguard Worker if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU)
490*9880d681SAndroid Build Coastguard Worker PendingQueue.push_back(SuccSU);
491*9880d681SAndroid Build Coastguard Worker }
492*9880d681SAndroid Build Coastguard Worker
493*9880d681SAndroid Build Coastguard Worker /// ReleaseSuccessors - Call ReleaseSucc on each of SU's successors.
ReleaseSuccessors(SUnit * SU)494*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::ReleaseSuccessors(SUnit *SU) {
495*9880d681SAndroid Build Coastguard Worker for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
496*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
497*9880d681SAndroid Build Coastguard Worker ReleaseSucc(SU, &*I);
498*9880d681SAndroid Build Coastguard Worker }
499*9880d681SAndroid Build Coastguard Worker }
500*9880d681SAndroid Build Coastguard Worker
501*9880d681SAndroid Build Coastguard Worker /// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
502*9880d681SAndroid Build Coastguard Worker /// count of its successors. If a successor pending count is zero, add it to
503*9880d681SAndroid Build Coastguard Worker /// the Available queue.
ScheduleNodeTopDown(SUnit * SU,unsigned CurCycle)504*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
505*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: ");
506*9880d681SAndroid Build Coastguard Worker DEBUG(SU->dump(this));
507*9880d681SAndroid Build Coastguard Worker
508*9880d681SAndroid Build Coastguard Worker Sequence.push_back(SU);
509*9880d681SAndroid Build Coastguard Worker assert(CurCycle >= SU->getDepth() &&
510*9880d681SAndroid Build Coastguard Worker "Node scheduled above its depth!");
511*9880d681SAndroid Build Coastguard Worker SU->setDepthToAtLeast(CurCycle);
512*9880d681SAndroid Build Coastguard Worker
513*9880d681SAndroid Build Coastguard Worker ReleaseSuccessors(SU);
514*9880d681SAndroid Build Coastguard Worker SU->isScheduled = true;
515*9880d681SAndroid Build Coastguard Worker AvailableQueue.scheduledNode(SU);
516*9880d681SAndroid Build Coastguard Worker }
517*9880d681SAndroid Build Coastguard Worker
518*9880d681SAndroid Build Coastguard Worker /// emitNoop - Add a noop to the current instruction sequence.
emitNoop(unsigned CurCycle)519*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::emitNoop(unsigned CurCycle) {
520*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "*** Emitting noop in cycle " << CurCycle << '\n');
521*9880d681SAndroid Build Coastguard Worker HazardRec->EmitNoop();
522*9880d681SAndroid Build Coastguard Worker Sequence.push_back(nullptr); // NULL here means noop
523*9880d681SAndroid Build Coastguard Worker ++NumNoops;
524*9880d681SAndroid Build Coastguard Worker }
525*9880d681SAndroid Build Coastguard Worker
526*9880d681SAndroid Build Coastguard Worker /// ListScheduleTopDown - The main loop of list scheduling for top-down
527*9880d681SAndroid Build Coastguard Worker /// schedulers.
ListScheduleTopDown()528*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::ListScheduleTopDown() {
529*9880d681SAndroid Build Coastguard Worker unsigned CurCycle = 0;
530*9880d681SAndroid Build Coastguard Worker
531*9880d681SAndroid Build Coastguard Worker // We're scheduling top-down but we're visiting the regions in
532*9880d681SAndroid Build Coastguard Worker // bottom-up order, so we don't know the hazards at the start of a
533*9880d681SAndroid Build Coastguard Worker // region. So assume no hazards (this should usually be ok as most
534*9880d681SAndroid Build Coastguard Worker // blocks are a single region).
535*9880d681SAndroid Build Coastguard Worker HazardRec->Reset();
536*9880d681SAndroid Build Coastguard Worker
537*9880d681SAndroid Build Coastguard Worker // Release any successors of the special Entry node.
538*9880d681SAndroid Build Coastguard Worker ReleaseSuccessors(&EntrySU);
539*9880d681SAndroid Build Coastguard Worker
540*9880d681SAndroid Build Coastguard Worker // Add all leaves to Available queue.
541*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
542*9880d681SAndroid Build Coastguard Worker // It is available if it has no predecessors.
543*9880d681SAndroid Build Coastguard Worker if (!SUnits[i].NumPredsLeft && !SUnits[i].isAvailable) {
544*9880d681SAndroid Build Coastguard Worker AvailableQueue.push(&SUnits[i]);
545*9880d681SAndroid Build Coastguard Worker SUnits[i].isAvailable = true;
546*9880d681SAndroid Build Coastguard Worker }
547*9880d681SAndroid Build Coastguard Worker }
548*9880d681SAndroid Build Coastguard Worker
549*9880d681SAndroid Build Coastguard Worker // In any cycle where we can't schedule any instructions, we must
550*9880d681SAndroid Build Coastguard Worker // stall or emit a noop, depending on the target.
551*9880d681SAndroid Build Coastguard Worker bool CycleHasInsts = false;
552*9880d681SAndroid Build Coastguard Worker
553*9880d681SAndroid Build Coastguard Worker // While Available queue is not empty, grab the node with the highest
554*9880d681SAndroid Build Coastguard Worker // priority. If it is not ready put it back. Schedule the node.
555*9880d681SAndroid Build Coastguard Worker std::vector<SUnit*> NotReady;
556*9880d681SAndroid Build Coastguard Worker Sequence.reserve(SUnits.size());
557*9880d681SAndroid Build Coastguard Worker while (!AvailableQueue.empty() || !PendingQueue.empty()) {
558*9880d681SAndroid Build Coastguard Worker // Check to see if any of the pending instructions are ready to issue. If
559*9880d681SAndroid Build Coastguard Worker // so, add them to the available queue.
560*9880d681SAndroid Build Coastguard Worker unsigned MinDepth = ~0u;
561*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
562*9880d681SAndroid Build Coastguard Worker if (PendingQueue[i]->getDepth() <= CurCycle) {
563*9880d681SAndroid Build Coastguard Worker AvailableQueue.push(PendingQueue[i]);
564*9880d681SAndroid Build Coastguard Worker PendingQueue[i]->isAvailable = true;
565*9880d681SAndroid Build Coastguard Worker PendingQueue[i] = PendingQueue.back();
566*9880d681SAndroid Build Coastguard Worker PendingQueue.pop_back();
567*9880d681SAndroid Build Coastguard Worker --i; --e;
568*9880d681SAndroid Build Coastguard Worker } else if (PendingQueue[i]->getDepth() < MinDepth)
569*9880d681SAndroid Build Coastguard Worker MinDepth = PendingQueue[i]->getDepth();
570*9880d681SAndroid Build Coastguard Worker }
571*9880d681SAndroid Build Coastguard Worker
572*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n*** Examining Available\n"; AvailableQueue.dump(this));
573*9880d681SAndroid Build Coastguard Worker
574*9880d681SAndroid Build Coastguard Worker SUnit *FoundSUnit = nullptr, *NotPreferredSUnit = nullptr;
575*9880d681SAndroid Build Coastguard Worker bool HasNoopHazards = false;
576*9880d681SAndroid Build Coastguard Worker while (!AvailableQueue.empty()) {
577*9880d681SAndroid Build Coastguard Worker SUnit *CurSUnit = AvailableQueue.pop();
578*9880d681SAndroid Build Coastguard Worker
579*9880d681SAndroid Build Coastguard Worker ScheduleHazardRecognizer::HazardType HT =
580*9880d681SAndroid Build Coastguard Worker HazardRec->getHazardType(CurSUnit, 0/*no stalls*/);
581*9880d681SAndroid Build Coastguard Worker if (HT == ScheduleHazardRecognizer::NoHazard) {
582*9880d681SAndroid Build Coastguard Worker if (HazardRec->ShouldPreferAnother(CurSUnit)) {
583*9880d681SAndroid Build Coastguard Worker if (!NotPreferredSUnit) {
584*9880d681SAndroid Build Coastguard Worker // If this is the first non-preferred node for this cycle, then
585*9880d681SAndroid Build Coastguard Worker // record it and continue searching for a preferred node. If this
586*9880d681SAndroid Build Coastguard Worker // is not the first non-preferred node, then treat it as though
587*9880d681SAndroid Build Coastguard Worker // there had been a hazard.
588*9880d681SAndroid Build Coastguard Worker NotPreferredSUnit = CurSUnit;
589*9880d681SAndroid Build Coastguard Worker continue;
590*9880d681SAndroid Build Coastguard Worker }
591*9880d681SAndroid Build Coastguard Worker } else {
592*9880d681SAndroid Build Coastguard Worker FoundSUnit = CurSUnit;
593*9880d681SAndroid Build Coastguard Worker break;
594*9880d681SAndroid Build Coastguard Worker }
595*9880d681SAndroid Build Coastguard Worker }
596*9880d681SAndroid Build Coastguard Worker
597*9880d681SAndroid Build Coastguard Worker // Remember if this is a noop hazard.
598*9880d681SAndroid Build Coastguard Worker HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard;
599*9880d681SAndroid Build Coastguard Worker
600*9880d681SAndroid Build Coastguard Worker NotReady.push_back(CurSUnit);
601*9880d681SAndroid Build Coastguard Worker }
602*9880d681SAndroid Build Coastguard Worker
603*9880d681SAndroid Build Coastguard Worker // If we have a non-preferred node, push it back onto the available list.
604*9880d681SAndroid Build Coastguard Worker // If we did not find a preferred node, then schedule this first
605*9880d681SAndroid Build Coastguard Worker // non-preferred node.
606*9880d681SAndroid Build Coastguard Worker if (NotPreferredSUnit) {
607*9880d681SAndroid Build Coastguard Worker if (!FoundSUnit) {
608*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "*** Will schedule a non-preferred instruction...\n");
609*9880d681SAndroid Build Coastguard Worker FoundSUnit = NotPreferredSUnit;
610*9880d681SAndroid Build Coastguard Worker } else {
611*9880d681SAndroid Build Coastguard Worker AvailableQueue.push(NotPreferredSUnit);
612*9880d681SAndroid Build Coastguard Worker }
613*9880d681SAndroid Build Coastguard Worker
614*9880d681SAndroid Build Coastguard Worker NotPreferredSUnit = nullptr;
615*9880d681SAndroid Build Coastguard Worker }
616*9880d681SAndroid Build Coastguard Worker
617*9880d681SAndroid Build Coastguard Worker // Add the nodes that aren't ready back onto the available list.
618*9880d681SAndroid Build Coastguard Worker if (!NotReady.empty()) {
619*9880d681SAndroid Build Coastguard Worker AvailableQueue.push_all(NotReady);
620*9880d681SAndroid Build Coastguard Worker NotReady.clear();
621*9880d681SAndroid Build Coastguard Worker }
622*9880d681SAndroid Build Coastguard Worker
623*9880d681SAndroid Build Coastguard Worker // If we found a node to schedule...
624*9880d681SAndroid Build Coastguard Worker if (FoundSUnit) {
625*9880d681SAndroid Build Coastguard Worker // If we need to emit noops prior to this instruction, then do so.
626*9880d681SAndroid Build Coastguard Worker unsigned NumPreNoops = HazardRec->PreEmitNoops(FoundSUnit);
627*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i != NumPreNoops; ++i)
628*9880d681SAndroid Build Coastguard Worker emitNoop(CurCycle);
629*9880d681SAndroid Build Coastguard Worker
630*9880d681SAndroid Build Coastguard Worker // ... schedule the node...
631*9880d681SAndroid Build Coastguard Worker ScheduleNodeTopDown(FoundSUnit, CurCycle);
632*9880d681SAndroid Build Coastguard Worker HazardRec->EmitInstruction(FoundSUnit);
633*9880d681SAndroid Build Coastguard Worker CycleHasInsts = true;
634*9880d681SAndroid Build Coastguard Worker if (HazardRec->atIssueLimit()) {
635*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "*** Max instructions per cycle " << CurCycle << '\n');
636*9880d681SAndroid Build Coastguard Worker HazardRec->AdvanceCycle();
637*9880d681SAndroid Build Coastguard Worker ++CurCycle;
638*9880d681SAndroid Build Coastguard Worker CycleHasInsts = false;
639*9880d681SAndroid Build Coastguard Worker }
640*9880d681SAndroid Build Coastguard Worker } else {
641*9880d681SAndroid Build Coastguard Worker if (CycleHasInsts) {
642*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "*** Finished cycle " << CurCycle << '\n');
643*9880d681SAndroid Build Coastguard Worker HazardRec->AdvanceCycle();
644*9880d681SAndroid Build Coastguard Worker } else if (!HasNoopHazards) {
645*9880d681SAndroid Build Coastguard Worker // Otherwise, we have a pipeline stall, but no other problem,
646*9880d681SAndroid Build Coastguard Worker // just advance the current cycle and try again.
647*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "*** Stall in cycle " << CurCycle << '\n');
648*9880d681SAndroid Build Coastguard Worker HazardRec->AdvanceCycle();
649*9880d681SAndroid Build Coastguard Worker ++NumStalls;
650*9880d681SAndroid Build Coastguard Worker } else {
651*9880d681SAndroid Build Coastguard Worker // Otherwise, we have no instructions to issue and we have instructions
652*9880d681SAndroid Build Coastguard Worker // that will fault if we don't do this right. This is the case for
653*9880d681SAndroid Build Coastguard Worker // processors without pipeline interlocks and other cases.
654*9880d681SAndroid Build Coastguard Worker emitNoop(CurCycle);
655*9880d681SAndroid Build Coastguard Worker }
656*9880d681SAndroid Build Coastguard Worker
657*9880d681SAndroid Build Coastguard Worker ++CurCycle;
658*9880d681SAndroid Build Coastguard Worker CycleHasInsts = false;
659*9880d681SAndroid Build Coastguard Worker }
660*9880d681SAndroid Build Coastguard Worker }
661*9880d681SAndroid Build Coastguard Worker
662*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
663*9880d681SAndroid Build Coastguard Worker unsigned ScheduledNodes = VerifyScheduledDAG(/*isBottomUp=*/false);
664*9880d681SAndroid Build Coastguard Worker unsigned Noops = 0;
665*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Sequence.size(); i != e; ++i)
666*9880d681SAndroid Build Coastguard Worker if (!Sequence[i])
667*9880d681SAndroid Build Coastguard Worker ++Noops;
668*9880d681SAndroid Build Coastguard Worker assert(Sequence.size() - Noops == ScheduledNodes &&
669*9880d681SAndroid Build Coastguard Worker "The number of nodes scheduled doesn't match the expected number!");
670*9880d681SAndroid Build Coastguard Worker #endif // NDEBUG
671*9880d681SAndroid Build Coastguard Worker }
672*9880d681SAndroid Build Coastguard Worker
673*9880d681SAndroid Build Coastguard Worker // EmitSchedule - Emit the machine code in scheduled order.
EmitSchedule()674*9880d681SAndroid Build Coastguard Worker void SchedulePostRATDList::EmitSchedule() {
675*9880d681SAndroid Build Coastguard Worker RegionBegin = RegionEnd;
676*9880d681SAndroid Build Coastguard Worker
677*9880d681SAndroid Build Coastguard Worker // If first instruction was a DBG_VALUE then put it back.
678*9880d681SAndroid Build Coastguard Worker if (FirstDbgValue)
679*9880d681SAndroid Build Coastguard Worker BB->splice(RegionEnd, BB, FirstDbgValue);
680*9880d681SAndroid Build Coastguard Worker
681*9880d681SAndroid Build Coastguard Worker // Then re-insert them according to the given schedule.
682*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
683*9880d681SAndroid Build Coastguard Worker if (SUnit *SU = Sequence[i])
684*9880d681SAndroid Build Coastguard Worker BB->splice(RegionEnd, BB, SU->getInstr());
685*9880d681SAndroid Build Coastguard Worker else
686*9880d681SAndroid Build Coastguard Worker // Null SUnit* is a noop.
687*9880d681SAndroid Build Coastguard Worker TII->insertNoop(*BB, RegionEnd);
688*9880d681SAndroid Build Coastguard Worker
689*9880d681SAndroid Build Coastguard Worker // Update the Begin iterator, as the first instruction in the block
690*9880d681SAndroid Build Coastguard Worker // may have been scheduled later.
691*9880d681SAndroid Build Coastguard Worker if (i == 0)
692*9880d681SAndroid Build Coastguard Worker RegionBegin = std::prev(RegionEnd);
693*9880d681SAndroid Build Coastguard Worker }
694*9880d681SAndroid Build Coastguard Worker
695*9880d681SAndroid Build Coastguard Worker // Reinsert any remaining debug_values.
696*9880d681SAndroid Build Coastguard Worker for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
697*9880d681SAndroid Build Coastguard Worker DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
698*9880d681SAndroid Build Coastguard Worker std::pair<MachineInstr *, MachineInstr *> P = *std::prev(DI);
699*9880d681SAndroid Build Coastguard Worker MachineInstr *DbgValue = P.first;
700*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator OrigPrivMI = P.second;
701*9880d681SAndroid Build Coastguard Worker BB->splice(++OrigPrivMI, BB, DbgValue);
702*9880d681SAndroid Build Coastguard Worker }
703*9880d681SAndroid Build Coastguard Worker DbgValues.clear();
704*9880d681SAndroid Build Coastguard Worker FirstDbgValue = nullptr;
705*9880d681SAndroid Build Coastguard Worker }
706