LLVM 24.0.0git
PostRASchedulerList.cpp
Go to the documentation of this file.
1//===----- SchedulePostRAList.cpp - list scheduler ------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This implements a top-down list scheduler, using standard algorithms.
10// The basic approach uses a priority queue of available nodes to schedule.
11// One at a time, nodes are taken from the priority queue (thus in priority
12// order), checked for legality to schedule, and emitted if legal.
13//
14// Nodes may not be legal to schedule either due to structural hazards (e.g.
15// pipeline or resource constraints) or because an input to the instruction has
16// not completed execution.
17//
18//===----------------------------------------------------------------------===//
19
21#include "llvm/ADT/Statistic.h"
36#include "llvm/Config/llvm-config.h"
38#include "llvm/Pass.h"
40#include "llvm/Support/Debug.h"
44using namespace llvm;
45
46#define DEBUG_TYPE "post-RA-sched"
47
48STATISTIC(NumNoops, "Number of noops inserted");
49STATISTIC(NumStalls, "Number of pipeline stalls");
50STATISTIC(NumFixedAnti, "Number of fixed anti-dependencies");
51
52// Post-RA scheduling is enabled with
53// TargetSubtargetInfo.enablePostRAScheduler(). This flag can be used to
54// override the target.
55static cl::opt<bool>
56EnablePostRAScheduler("post-RA-scheduler",
57 cl::desc("Enable scheduling after register allocation"),
58 cl::init(false), cl::Hidden);
60EnableAntiDepBreaking("break-anti-dependencies",
61 cl::desc("Break post-RA scheduling anti-dependencies: "
62 "\"critical\", \"all\", or \"none\""),
63 cl::init("none"), cl::Hidden);
64
65// If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod
66static cl::opt<int>
67DebugDiv("postra-sched-debugdiv",
68 cl::desc("Debug control MBBs that are scheduled"),
70static cl::opt<int>
71DebugMod("postra-sched-debugmod",
72 cl::desc("Debug control MBBs that are scheduled"),
74
76
77namespace {
78class PostRAScheduler {
79 const TargetInstrInfo *TII = nullptr;
80 MachineLoopInfo *MLI = nullptr;
81 AliasAnalysis *AA = nullptr;
82 const TargetMachine *TM = nullptr;
83 const RegisterClassInfo *RegClassInfo = nullptr;
84
85public:
86 PostRAScheduler(MachineFunction &MF, MachineLoopInfo *MLI, AliasAnalysis *AA,
87 const TargetMachine *TM,
88 const RegisterClassInfo *RegClassInfo)
89 : TII(MF.getSubtarget().getInstrInfo()), MLI(MLI), AA(AA), TM(TM),
90 RegClassInfo(RegClassInfo) {}
91 bool run(MachineFunction &MF);
92};
93
94class PostRASchedulerLegacy : public MachineFunctionPass {
95public:
96 static char ID;
97 PostRASchedulerLegacy() : MachineFunctionPass(ID) {}
98
99 void getAnalysisUsage(AnalysisUsage &AU) const override {
100 AU.setPreservesCFG();
101 AU.addRequired<AAResultsWrapperPass>();
102 AU.addRequired<TargetPassConfig>();
103 AU.addRequired<MachineDominatorTreeWrapperPass>();
104 AU.addPreserved<MachineDominatorTreeWrapperPass>();
105 AU.addRequired<MachineLoopInfoWrapperPass>();
106 AU.addPreserved<MachineLoopInfoWrapperPass>();
107 AU.addRequired<MachineRegisterClassInfoWrapperPass>();
108 AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
110 }
111
112 MachineFunctionProperties getRequiredProperties() const override {
113 return MachineFunctionProperties().setNoVRegs();
114 }
115
116 bool runOnMachineFunction(MachineFunction &Fn) override;
117};
118char PostRASchedulerLegacy::ID = 0;
119
120class SchedulePostRATDList : public ScheduleDAGInstrs {
121 /// AvailableQueue - The priority queue to use for the available SUnits.
122 ///
123 LatencyPriorityQueue AvailableQueue;
124
125 /// PendingQueue - This contains all of the instructions whose operands have
126 /// been issued, but their results are not ready yet (due to the latency of
127 /// the operation). Once the operands becomes available, the instruction is
128 /// added to the AvailableQueue.
129 std::vector<SUnit *> PendingQueue;
130
131 /// HazardRec - The hazard recognizer to use.
132 ScheduleHazardRecognizer *HazardRec;
133
134 /// AntiDepBreak - Anti-dependence breaking object, or NULL if none
135 AntiDepBreaker *AntiDepBreak;
136
137 /// AA - AliasAnalysis for making memory reference queries.
138 AliasAnalysis *AA;
139
140 /// The schedule. Null SUnit*'s represent noop instructions.
141 std::vector<SUnit *> Sequence;
142
143 /// Ordered list of DAG postprocessing steps.
144 std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
145
146 /// The index in BB of RegionEnd.
147 ///
148 /// This is the instruction number from the top of the current block, not
149 /// the SlotIndex. It is only used by the AntiDepBreaker.
150 unsigned EndIndex = 0;
151
152public:
153 SchedulePostRATDList(
154 MachineFunction &MF, MachineLoopInfo &MLI, AliasAnalysis *AA,
155 const RegisterClassInfo &,
157 SmallVectorImpl<const TargetRegisterClass *> &CriticalPathRCs);
158
159 ~SchedulePostRATDList() override;
160
161 /// startBlock - Initialize register live-range state for scheduling in
162 /// this block.
163 ///
164 void startBlock(MachineBasicBlock *BB) override;
165
166 // Set the index of RegionEnd within the current BB.
167 void setEndIndex(unsigned EndIdx) { EndIndex = EndIdx; }
168
169 /// Initialize the scheduler state for the next scheduling region.
170 void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin,
172 unsigned regioninstrs) override;
173
174 /// Notify that the scheduler has finished scheduling the current region.
175 void exitRegion() override;
176
177 /// Schedule - Schedule the instruction range using list scheduling.
178 ///
179 void schedule() override;
180
181 void EmitSchedule();
182
183 /// Observe - Update liveness information to account for the current
184 /// instruction, which will not be scheduled.
185 ///
186 void Observe(MachineInstr &MI, unsigned Count);
187
188 /// finishBlock - Clean up register live-range state.
189 ///
190 void finishBlock() override;
191
192private:
193 /// Apply each ScheduleDAGMutation step in order.
194 void postProcessDAG();
195
196 void ReleaseSucc(SUnit *SU, SDep *SuccEdge);
197 void ReleaseSuccessors(SUnit *SU);
198 void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle);
199 void ListScheduleTopDown();
200
201 void dumpSchedule() const;
202 void emitNoop(unsigned CurCycle);
203};
204} // namespace
205
206char &llvm::PostRASchedulerID = PostRASchedulerLegacy::ID;
207
208INITIALIZE_PASS_BEGIN(PostRASchedulerLegacy, DEBUG_TYPE,
209 "Post RA top-down list latency scheduler", false, false)
211INITIALIZE_PASS_END(PostRASchedulerLegacy, DEBUG_TYPE,
212 "Post RA top-down list latency scheduler", false, false)
213
214SchedulePostRATDList::SchedulePostRATDList(
217 TargetSubtargetInfo::AntiDepBreakMode AntiDepMode,
218 SmallVectorImpl<const TargetRegisterClass *> &CriticalPathRCs)
219 : ScheduleDAGInstrs(MF, &MLI), AA(AA) {
220
221 const InstrItineraryData *InstrItins =
222 MF.getSubtarget().getInstrItineraryData();
223 HazardRec =
224 MF.getSubtarget().getInstrInfo()->CreateTargetPostRAHazardRecognizer(
225 InstrItins, this);
226 MF.getSubtarget().getPostRAMutations(Mutations);
227
228 assert((AntiDepMode == TargetSubtargetInfo::ANTIDEP_NONE ||
229 MRI.tracksLiveness()) &&
230 "Live-ins must be accurate for anti-dependency breaking");
231 AntiDepBreak = ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_ALL)
232 ? createAggressiveAntiDepBreaker(MF, RCI, CriticalPathRCs)
233 : ((AntiDepMode == TargetSubtargetInfo::ANTIDEP_CRITICAL)
235 : nullptr));
236}
237
238SchedulePostRATDList::~SchedulePostRATDList() {
239 delete HazardRec;
240 delete AntiDepBreak;
241}
242
243/// Initialize state associated with the next scheduling region.
244void SchedulePostRATDList::enterRegion(MachineBasicBlock *bb,
247 unsigned regioninstrs) {
248 ScheduleDAGInstrs::enterRegion(bb, begin, end, regioninstrs);
249 Sequence.clear();
250}
251
252/// Print the schedule before exiting the region.
253void SchedulePostRATDList::exitRegion() {
254 LLVM_DEBUG({
255 dbgs() << "*** Final schedule ***\n";
256 dumpSchedule();
257 dbgs() << '\n';
258 });
260}
261
262#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
263/// dumpSchedule - dump the scheduled Sequence.
264LLVM_DUMP_METHOD void SchedulePostRATDList::dumpSchedule() const {
265 for (const SUnit *SU : Sequence) {
266 if (SU)
267 dumpNode(*SU);
268 else
269 dbgs() << "**** NOOP ****\n";
270 }
271}
272#endif
273
275 CodeGenOptLevel OptLevel) {
276 // Check for explicit enable/disable of post-ra scheduling.
277 if (EnablePostRAScheduler.getPosition() > 0)
279
280 return ST.enablePostRAScheduler() &&
281 OptLevel >= ST.getOptLevelToEnablePostRAScheduler();
282}
283
284bool PostRAScheduler::run(MachineFunction &MF) {
285 const auto &Subtarget = MF.getSubtarget();
286 // Check that post-RA scheduling is enabled for this target.
287 if (!enablePostRAScheduler(Subtarget, TM->getOptLevel()))
288 return false;
289
291 Subtarget.getAntiDepBreakMode();
292 if (EnableAntiDepBreaking.getPosition() > 0) {
293 AntiDepMode = (EnableAntiDepBreaking == "all")
294 ? TargetSubtargetInfo::ANTIDEP_ALL
295 : ((EnableAntiDepBreaking == "critical")
296 ? TargetSubtargetInfo::ANTIDEP_CRITICAL
297 : TargetSubtargetInfo::ANTIDEP_NONE);
298 }
300 Subtarget.getCriticalPathRCs(CriticalPathRCs);
301
302 LLVM_DEBUG(dbgs() << "PostRAScheduler\n");
303
304 SchedulePostRATDList Scheduler(MF, *MLI, AA, *RegClassInfo, AntiDepMode,
305 CriticalPathRCs);
306
307 // Loop over all of the basic blocks
308 for (auto &MBB : MF) {
309#ifndef NDEBUG
310 // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod
311 if (DebugDiv > 0) {
312 static int bbcnt = 0;
313 if (bbcnt++ % DebugDiv != DebugMod)
314 continue;
315 dbgs() << "*** DEBUG scheduling " << MF.getName() << ":"
316 << printMBBReference(MBB) << " ***\n";
317 }
318#endif
319
320 // Initialize register live-range state for scheduling in this block.
321 Scheduler.startBlock(&MBB);
322
323 // Schedule each sequence of instructions not interrupted by a label
324 // or anything else that effectively needs to shut down scheduling.
326 unsigned Count = MBB.size(), CurrentCount = Count;
327 for (MachineBasicBlock::iterator I = Current; I != MBB.begin();) {
328 MachineInstr &MI = *std::prev(I);
329 --Count;
330 // Calls are not scheduling boundaries before register allocation, but
331 // post-ra we don't gain anything by scheduling across calls since we
332 // don't need to worry about register pressure.
333 if (MI.isCall() || TII->isSchedulingBoundary(MI, &MBB, MF)) {
334 Scheduler.enterRegion(&MBB, I, Current, CurrentCount - Count);
335 Scheduler.setEndIndex(CurrentCount);
336 Scheduler.schedule();
337 Scheduler.exitRegion();
338 Scheduler.EmitSchedule();
339 Current = &MI;
340 CurrentCount = Count;
341 Scheduler.Observe(MI, CurrentCount);
342 }
343 I = MI;
344 if (MI.isBundle())
345 Count -= MI.getBundleSize();
346 }
347 assert(Count == 0 && "Instruction count mismatch!");
348 assert((MBB.begin() == Current || CurrentCount != 0) &&
349 "Instruction count mismatch!");
350 Scheduler.enterRegion(&MBB, MBB.begin(), Current, CurrentCount);
351 Scheduler.setEndIndex(CurrentCount);
352 Scheduler.schedule();
353 Scheduler.exitRegion();
354 Scheduler.EmitSchedule();
355
356 // Clean up register live-range state.
357 Scheduler.finishBlock();
358
359 // Update register kills
360 Scheduler.fixupKills(MBB);
361 }
362
363 return true;
364}
365
366bool PostRASchedulerLegacy::runOnMachineFunction(MachineFunction &MF) {
367 if (skipFunction(MF.getFunction()))
368 return false;
369
370 MachineLoopInfo *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
371 AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
372 const TargetMachine *TM =
373 &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
374 RegisterClassInfo *RegClassInfo =
375 &getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
376 PostRAScheduler Impl(MF, MLI, AA, TM, RegClassInfo);
377 return Impl.run(MF);
378}
379
380PreservedAnalyses
383 MFPropsModifier _(*this, MF);
384
387 .getManager();
388 AliasAnalysis *AA = &FAM.getResult<AAManager>(MF.getFunction());
389 const RegisterClassInfo &RegClassInfo =
391 PostRAScheduler Impl(MF, MLI, AA, TM, &RegClassInfo);
392 bool Changed = Impl.run(MF);
393 if (!Changed)
394 return PreservedAnalyses::all();
395
400 return PA;
401}
402
403/// StartBlock - Initialize register live-range state for scheduling in
404/// this block.
405///
406void SchedulePostRATDList::startBlock(MachineBasicBlock *BB) {
407 // Call the superclass.
409
410 // Reset the hazard recognizer and anti-dep breaker.
411 HazardRec->Reset();
412 if (AntiDepBreak)
413 AntiDepBreak->StartBlock(BB);
414}
415
416/// Schedule - Schedule the instruction range using list scheduling.
417///
418void SchedulePostRATDList::schedule() {
419 // Build the scheduling graph.
420 buildSchedGraph(AA);
421
422 if (AntiDepBreak) {
423 unsigned Broken =
424 AntiDepBreak->BreakAntiDependencies(SUnits, RegionBegin, RegionEnd,
425 EndIndex, DbgValues);
426
427 if (Broken != 0) {
428 // We made changes. Update the dependency graph.
429 // Theoretically we could update the graph in place:
430 // When a live range is changed to use a different register, remove
431 // the def's anti-dependence *and* output-dependence edges due to
432 // that register, and add new anti-dependence and output-dependence
433 // edges based on the next live range of the register.
435 buildSchedGraph(AA);
436
437 NumFixedAnti += Broken;
438 }
439 }
440
441 postProcessDAG();
442
443 LLVM_DEBUG(dbgs() << "********** List Scheduling **********\n");
444 LLVM_DEBUG(dump());
445
446 AvailableQueue.initNodes(SUnits);
447 ListScheduleTopDown();
448 AvailableQueue.releaseState();
449}
450
451/// Observe - Update liveness information to account for the current
452/// instruction, which will not be scheduled.
453///
454void SchedulePostRATDList::Observe(MachineInstr &MI, unsigned Count) {
455 if (AntiDepBreak)
456 AntiDepBreak->Observe(MI, Count, EndIndex);
457}
458
459/// FinishBlock - Clean up register live-range state.
460///
461void SchedulePostRATDList::finishBlock() {
462 if (AntiDepBreak)
463 AntiDepBreak->FinishBlock();
464
465 // Call the superclass.
467}
468
469/// Apply each ScheduleDAGMutation step in order.
470void SchedulePostRATDList::postProcessDAG() {
471 for (auto &M : Mutations)
472 M->apply(this);
473}
474
475//===----------------------------------------------------------------------===//
476// Top-Down Scheduling
477//===----------------------------------------------------------------------===//
478
479/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
480/// the PendingQueue if the count reaches zero.
481void SchedulePostRATDList::ReleaseSucc(SUnit *SU, SDep *SuccEdge) {
482 SUnit *SuccSU = SuccEdge->getSUnit();
483
484 if (SuccEdge->isWeak()) {
485 --SuccSU->WeakPredsLeft;
486 return;
487 }
488#ifndef NDEBUG
489 if (SuccSU->NumPredsLeft == 0) {
490 dbgs() << "*** Scheduling failed! ***\n";
491 dumpNode(*SuccSU);
492 dbgs() << " has been released too many times!\n";
493 llvm_unreachable(nullptr);
494 }
495#endif
496 --SuccSU->NumPredsLeft;
497
498 // Standard scheduler algorithms will recompute the depth of the successor
499 // here as such:
500 // SuccSU->setDepthToAtLeast(SU->getDepth() + SuccEdge->getLatency());
501 //
502 // However, we lazily compute node depth instead. Note that
503 // ScheduleNodeTopDown has already updated the depth of this node which causes
504 // all descendents to be marked dirty. Setting the successor depth explicitly
505 // here would cause depth to be recomputed for all its ancestors. If the
506 // successor is not yet ready (because of a transitively redundant edge) then
507 // this causes depth computation to be quadratic in the size of the DAG.
508
509 // If all the node's predecessors are scheduled, this node is ready
510 // to be scheduled. Ignore the special ExitSU node.
511 if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU)
512 PendingQueue.push_back(SuccSU);
513}
514
515/// ReleaseSuccessors - Call ReleaseSucc on each of SU's successors.
516void SchedulePostRATDList::ReleaseSuccessors(SUnit *SU) {
517 for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
518 I != E; ++I) {
519 ReleaseSucc(SU, &*I);
520 }
521}
522
523/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
524/// count of its successors. If a successor pending count is zero, add it to
525/// the Available queue.
526void SchedulePostRATDList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
527 LLVM_DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: ");
528 LLVM_DEBUG(dumpNode(*SU));
529
530 Sequence.push_back(SU);
531 assert(CurCycle >= SU->getDepth() &&
532 "Node scheduled above its depth!");
533 SU->setDepthToAtLeast(CurCycle);
534
535 ReleaseSuccessors(SU);
536 SU->isScheduled = true;
537 AvailableQueue.scheduledNode(SU);
538}
539
540/// emitNoop - Add a noop to the current instruction sequence.
541void SchedulePostRATDList::emitNoop(unsigned CurCycle) {
542 LLVM_DEBUG(dbgs() << "*** Emitting noop in cycle " << CurCycle << '\n');
543 HazardRec->EmitNoop();
544 Sequence.push_back(nullptr); // NULL here means noop
545 ++NumNoops;
546}
547
548/// ListScheduleTopDown - The main loop of list scheduling for top-down
549/// schedulers.
550void SchedulePostRATDList::ListScheduleTopDown() {
551 unsigned CurCycle = 0;
552
553 // We're scheduling top-down but we're visiting the regions in
554 // bottom-up order, so we don't know the hazards at the start of a
555 // region. So assume no hazards (this should usually be ok as most
556 // blocks are a single region).
557 HazardRec->Reset();
558
559 // Release any successors of the special Entry node.
560 ReleaseSuccessors(&EntrySU);
561
562 // Add all leaves to Available queue.
563 for (SUnit &SUnit : SUnits) {
564 // It is available if it has no predecessors.
565 if (!SUnit.NumPredsLeft && !SUnit.isAvailable) {
566 AvailableQueue.push(&SUnit);
567 SUnit.isAvailable = true;
568 }
569 }
570
571 // In any cycle where we can't schedule any instructions, we must
572 // stall or emit a noop, depending on the target.
573 bool CycleHasInsts = false;
574
575 // While Available queue is not empty, grab the node with the highest
576 // priority. If it is not ready put it back. Schedule the node.
577 std::vector<SUnit*> NotReady;
578 Sequence.reserve(SUnits.size());
579 while (!AvailableQueue.empty() || !PendingQueue.empty()) {
580 // Check to see if any of the pending instructions are ready to issue. If
581 // so, add them to the available queue.
582 unsigned MinDepth = ~0u;
583 for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
584 if (PendingQueue[i]->getDepth() <= CurCycle) {
585 AvailableQueue.push(PendingQueue[i]);
586 PendingQueue[i]->isAvailable = true;
587 PendingQueue[i] = PendingQueue.back();
588 PendingQueue.pop_back();
589 --i; --e;
590 } else if (PendingQueue[i]->getDepth() < MinDepth)
591 MinDepth = PendingQueue[i]->getDepth();
592 }
593
594 LLVM_DEBUG(dbgs() << "\n*** Examining Available\n";
595 AvailableQueue.dump(this));
596
597 SUnit *FoundSUnit = nullptr, *NotPreferredSUnit = nullptr;
598 bool HasNoopHazards = false;
599 while (!AvailableQueue.empty()) {
600 SUnit *CurSUnit = AvailableQueue.pop();
601
603 HazardRec->getHazardType(CurSUnit, 0/*no stalls*/);
605 if (HazardRec->ShouldPreferAnother(CurSUnit)) {
606 if (!NotPreferredSUnit) {
607 // If this is the first non-preferred node for this cycle, then
608 // record it and continue searching for a preferred node. If this
609 // is not the first non-preferred node, then treat it as though
610 // there had been a hazard.
611 NotPreferredSUnit = CurSUnit;
612 continue;
613 }
614 } else {
615 FoundSUnit = CurSUnit;
616 break;
617 }
618 }
619
620 // Remember if this is a noop hazard.
621 HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard;
622
623 NotReady.push_back(CurSUnit);
624 }
625
626 // If we have a non-preferred node, push it back onto the available list.
627 // If we did not find a preferred node, then schedule this first
628 // non-preferred node.
629 if (NotPreferredSUnit) {
630 if (!FoundSUnit) {
632 dbgs() << "*** Will schedule a non-preferred instruction...\n");
633 FoundSUnit = NotPreferredSUnit;
634 } else {
635 AvailableQueue.push(NotPreferredSUnit);
636 }
637
638 NotPreferredSUnit = nullptr;
639 }
640
641 // Add the nodes that aren't ready back onto the available list.
642 if (!NotReady.empty()) {
643 AvailableQueue.push_all(NotReady);
644 NotReady.clear();
645 }
646
647 // If we found a node to schedule...
648 if (FoundSUnit) {
649 // If we need to emit noops prior to this instruction, then do so.
650 unsigned NumPreNoops = HazardRec->PreEmitNoops(FoundSUnit);
651 for (unsigned i = 0; i != NumPreNoops; ++i)
652 emitNoop(CurCycle);
653
654 // ... schedule the node...
655 ScheduleNodeTopDown(FoundSUnit, CurCycle);
656 HazardRec->EmitInstruction(FoundSUnit);
657 CycleHasInsts = true;
658 if (HazardRec->atIssueLimit()) {
659 LLVM_DEBUG(dbgs() << "*** Max instructions per cycle " << CurCycle
660 << '\n');
661 HazardRec->AdvanceCycle();
662 ++CurCycle;
663 CycleHasInsts = false;
664 }
665 } else {
666 if (CycleHasInsts) {
667 LLVM_DEBUG(dbgs() << "*** Finished cycle " << CurCycle << '\n');
668 HazardRec->AdvanceCycle();
669 } else if (!HasNoopHazards) {
670 // Otherwise, we have a pipeline stall, but no other problem,
671 // just advance the current cycle and try again.
672 LLVM_DEBUG(dbgs() << "*** Stall in cycle " << CurCycle << '\n');
673 HazardRec->AdvanceCycle();
674 ++NumStalls;
675 } else {
676 // Otherwise, we have no instructions to issue and we have instructions
677 // that will fault if we don't do this right. This is the case for
678 // processors without pipeline interlocks and other cases.
679 emitNoop(CurCycle);
680 }
681
682 ++CurCycle;
683 CycleHasInsts = false;
684 }
685 }
686
687#ifndef NDEBUG
688 unsigned ScheduledNodes = VerifyScheduledDAG(/*isBottomUp=*/false);
689 unsigned Noops = llvm::count(Sequence, nullptr);
690 assert(Sequence.size() - Noops == ScheduledNodes &&
691 "The number of nodes scheduled doesn't match the expected number!");
692#endif // NDEBUG
693}
694
695// EmitSchedule - Emit the machine code in scheduled order.
696void SchedulePostRATDList::EmitSchedule() {
697 RegionBegin = RegionEnd;
698
699 // If first instruction was a DBG_VALUE then put it back.
700 if (FirstDbgValue)
701 BB->splice(RegionEnd, BB, FirstDbgValue);
702
703 // Then re-insert them according to the given schedule.
704 for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
705 if (SUnit *SU = Sequence[i])
706 BB->splice(RegionEnd, BB, SU->getInstr());
707 else
708 // Null SUnit* is a noop.
709 TII->insertNoop(*BB, RegionEnd);
710
711 // Update the Begin iterator, as the first instruction in the block
712 // may have been scheduled later.
713 if (i == 0)
714 RegionBegin = std::prev(RegionEnd);
715 }
716
717 // Reinsert any remaining debug_values.
718 for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
719 DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
720 std::pair<MachineInstr *, MachineInstr *> P = *std::prev(DI);
721 MachineInstr *DbgValue = P.first;
722 MachineBasicBlock::iterator OrigPrivMI = P.second;
723 BB->splice(++OrigPrivMI, BB, DbgValue);
724 }
725 DbgValues.clear();
726 FirstDbgValue = nullptr;
727}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
MachineBasicBlock & MBB
static cl::opt< int > DebugDiv("agg-antidep-debugdiv", cl::desc("Debug control for aggressive anti-dep breaker"), cl::init(0), cl::Hidden)
static cl::opt< int > DebugMod("agg-antidep-debugmod", cl::desc("Debug control for aggressive anti-dep breaker"), cl::init(0), cl::Hidden)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:672
#define DEBUG_TYPE
const HexagonInstrInfo * TII
#define _
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
PostRA Machine Instruction Scheduler
#define P(N)
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
static cl::opt< int > DebugDiv("postra-sched-debugdiv", cl::desc("Debug control MBBs that are scheduled"), cl::init(0), cl::Hidden)
static cl::opt< bool > EnablePostRAScheduler("post-RA-scheduler", cl::desc("Enable scheduling after register allocation"), cl::init(false), cl::Hidden)
static cl::opt< std::string > EnableAntiDepBreaking("break-anti-dependencies", cl::desc("Break post-RA scheduling anti-dependencies: " "\"critical\", \"all\", or \"none\""), cl::init("none"), cl::Hidden)
static bool enablePostRAScheduler(const TargetSubtargetInfo &ST, CodeGenOptLevel OptLevel)
static cl::opt< int > DebugMod("postra-sched-debugmod", cl::desc("Debug control MBBs that are scheduled"), cl::init(0), cl::Hidden)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
Target-Independent Code Generator Pass Configuration Options pass.
A manager for alias analyses.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:275
virtual void FinishBlock()=0
Finish anti-dep breaking for a basic block.
virtual unsigned BreakAntiDependencies(const std::vector< SUnit > &SUnits, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned InsertPosIndex, DbgValueVector &DbgValues)=0
Identifiy anti-dependencies within a basic-block region and break them by renaming registers.
virtual void Observe(MachineInstr &MI, unsigned Count, unsigned InsertPosIndex)=0
Update liveness information to account for the current instruction, which will not be scheduled.
virtual ~AntiDepBreaker()
virtual void StartBlock(MachineBasicBlock *BB)=0
Initialize anti-dep breaking for a new basic block.
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
Insert a noop into the instruction stream at the specified point.
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
Test if the given instruction should be considered a scheduling boundary.
Itinerary data supplied by a subtarget to be used by a target.
LLVM_DUMP_METHOD void dump(ScheduleDAG *DAG) const override
void scheduledNode(SUnit *SU) override
As each node is scheduled, this method is invoked.
void initNodes(std::vector< SUnit > &sunits) override
An RAII based helper class to modify MachineFunctionProperties when running pass.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Analysis pass that exposes the MachineLoopInfo for a machine function.
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition Analysis.h:132
SUnit * getSUnit() const
bool isWeak() const
Tests if this a weak dependence.
unsigned getDepth() const
Returns the depth of this node, which is the length of the maximum path up to any node which has no p...
bool isScheduled
True once scheduled.
unsigned NumPredsLeft
SmallVector< SDep, 4 > Succs
All sunit successors.
unsigned WeakPredsLeft
SmallVectorImpl< SDep >::iterator succ_iterator
LLVM_ABI void setDepthToAtLeast(unsigned NewDepth)
If NewDepth is greater than this node's depth value, sets it to be the new depth value.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
A ScheduleDAG for scheduling lists of MachineInstr.
virtual void finishBlock()
Cleans up after scheduling in the given block.
virtual void startBlock(MachineBasicBlock *BB)
Prepares to perform scheduling in the given block.
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs)
Initialize the DAG and common scheduler state for a new scheduling region.
void clearDAG()
Clears the DAG state (between regions).
virtual void Reset()
Reset - This callback is invoked when a new block of instructions is about to be schedule.
virtual void EmitInstruction(SUnit *)
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
virtual bool atIssueLimit() const
atIssueLimit - Return true if no more instructions may be issued in this cycle.
virtual bool ShouldPreferAnother(SUnit *) const
ShouldPreferAnother - This callback may be invoked if getHazardType returns NoHazard.
virtual void EmitNoop()
EmitNoop - This callback is invoked when a noop was added to the instruction stream.
virtual void AdvanceCycle()
AdvanceCycle - This callback is invoked whenever the next top-down instruction to be scheduled cannot...
virtual HazardType getHazardType(SUnit *, int Stalls=0)
getHazardType - Return the hazard type of emitting this node.
virtual unsigned PreEmitNoops(SUnit *)
PreEmitNoops - This callback is invoked prior to emitting an instruction.
void push_all(const std::vector< SUnit * > &Nodes)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
TargetInstrInfo - Interface to description of machine instruction set.
Primary interface to the complete machine description for the target machine.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
TargetSubtargetInfo - Generic base class for all target subtargets.
enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode
virtual AntiDepBreakMode getAntiDepBreakMode() const
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:165
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
constexpr double e
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
Definition PtrState.h:41
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
LLVM_ABI AntiDepBreaker * createAggressiveAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI, TargetSubtargetInfo::RegClassVector &CriticalPathRCs)
LLVM_ABI char & PostRASchedulerID
PostRAScheduler - This pass performs post register allocation scheduling.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:82
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition STLExtras.h:2012
LLVM_ABI AntiDepBreaker * createCriticalAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI)
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58