LLVM 24.0.0git
MachineScheduler.cpp
Go to the documentation of this file.
1//===- MachineScheduler.cpp - Machine Instruction 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// MachineScheduler schedules machine instructions after phi elimination. It
10// preserves LiveIntervals so it can be invoked before register allocation.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/BitVector.h"
17#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/Statistic.h"
52#include "llvm/Config/llvm-config.h"
54#include "llvm/MC/LaneBitmask.h"
55#include "llvm/Pass.h"
58#include "llvm/Support/Debug.h"
63#include <algorithm>
64#include <cassert>
65#include <cstdint>
66#include <iterator>
67#include <limits>
68#include <memory>
69#include <string>
70#include <tuple>
71#include <utility>
72#include <vector>
73
74using namespace llvm;
75
76#define DEBUG_TYPE "machine-scheduler"
77
78STATISTIC(NumInstrsInSourceOrderPreRA,
79 "Number of instructions in source order after pre-RA scheduling");
80STATISTIC(NumInstrsInSourceOrderPostRA,
81 "Number of instructions in source order after post-RA scheduling");
82STATISTIC(NumInstrsScheduledPreRA,
83 "Number of instructions scheduled by pre-RA scheduler");
84STATISTIC(NumInstrsScheduledPostRA,
85 "Number of instructions scheduled by post-RA scheduler");
86STATISTIC(NumClustered, "Number of load/store pairs clustered");
87
88STATISTIC(NumTopPreRA,
89 "Number of scheduling units chosen from top queue pre-RA");
90STATISTIC(NumBotPreRA,
91 "Number of scheduling units chosen from bottom queue pre-RA");
92STATISTIC(NumNoCandPreRA,
93 "Number of scheduling units chosen for NoCand heuristic pre-RA");
94STATISTIC(NumOnly1PreRA,
95 "Number of scheduling units chosen for Only1 heuristic pre-RA");
96STATISTIC(NumPhysRegPreRA,
97 "Number of scheduling units chosen for PhysReg heuristic pre-RA");
98STATISTIC(NumRegExcessPreRA,
99 "Number of scheduling units chosen for RegExcess heuristic pre-RA");
100STATISTIC(NumRegCriticalPreRA,
101 "Number of scheduling units chosen for RegCritical heuristic pre-RA");
102STATISTIC(NumStallPreRA,
103 "Number of scheduling units chosen for Stall heuristic pre-RA");
104STATISTIC(NumClusterPreRA,
105 "Number of scheduling units chosen for Cluster heuristic pre-RA");
106STATISTIC(NumWeakPreRA,
107 "Number of scheduling units chosen for Weak heuristic pre-RA");
108STATISTIC(NumRegMaxPreRA,
109 "Number of scheduling units chosen for RegMax heuristic pre-RA");
111 NumResourceReducePreRA,
112 "Number of scheduling units chosen for ResourceReduce heuristic pre-RA");
114 NumResourceDemandPreRA,
115 "Number of scheduling units chosen for ResourceDemand heuristic pre-RA");
117 NumTopDepthReducePreRA,
118 "Number of scheduling units chosen for TopDepthReduce heuristic pre-RA");
120 NumTopPathReducePreRA,
121 "Number of scheduling units chosen for TopPathReduce heuristic pre-RA");
123 NumBotHeightReducePreRA,
124 "Number of scheduling units chosen for BotHeightReduce heuristic pre-RA");
126 NumBotPathReducePreRA,
127 "Number of scheduling units chosen for BotPathReduce heuristic pre-RA");
128STATISTIC(NumNodeOrderPreRA,
129 "Number of scheduling units chosen for NodeOrder heuristic pre-RA");
130STATISTIC(NumFirstValidPreRA,
131 "Number of scheduling units chosen for FirstValid heuristic pre-RA");
132
133STATISTIC(NumTopPostRA,
134 "Number of scheduling units chosen from top queue post-RA");
135STATISTIC(NumBotPostRA,
136 "Number of scheduling units chosen from bottom queue post-RA");
137STATISTIC(NumNoCandPostRA,
138 "Number of scheduling units chosen for NoCand heuristic post-RA");
139STATISTIC(NumOnly1PostRA,
140 "Number of scheduling units chosen for Only1 heuristic post-RA");
141STATISTIC(NumPhysRegPostRA,
142 "Number of scheduling units chosen for PhysReg heuristic post-RA");
143STATISTIC(NumRegExcessPostRA,
144 "Number of scheduling units chosen for RegExcess heuristic post-RA");
146 NumRegCriticalPostRA,
147 "Number of scheduling units chosen for RegCritical heuristic post-RA");
148STATISTIC(NumStallPostRA,
149 "Number of scheduling units chosen for Stall heuristic post-RA");
150STATISTIC(NumClusterPostRA,
151 "Number of scheduling units chosen for Cluster heuristic post-RA");
152STATISTIC(NumWeakPostRA,
153 "Number of scheduling units chosen for Weak heuristic post-RA");
154STATISTIC(NumRegMaxPostRA,
155 "Number of scheduling units chosen for RegMax heuristic post-RA");
157 NumResourceReducePostRA,
158 "Number of scheduling units chosen for ResourceReduce heuristic post-RA");
160 NumResourceDemandPostRA,
161 "Number of scheduling units chosen for ResourceDemand heuristic post-RA");
163 NumTopDepthReducePostRA,
164 "Number of scheduling units chosen for TopDepthReduce heuristic post-RA");
166 NumTopPathReducePostRA,
167 "Number of scheduling units chosen for TopPathReduce heuristic post-RA");
169 NumBotHeightReducePostRA,
170 "Number of scheduling units chosen for BotHeightReduce heuristic post-RA");
172 NumBotPathReducePostRA,
173 "Number of scheduling units chosen for BotPathReduce heuristic post-RA");
174STATISTIC(NumNodeOrderPostRA,
175 "Number of scheduling units chosen for NodeOrder heuristic post-RA");
176STATISTIC(NumFirstValidPostRA,
177 "Number of scheduling units chosen for FirstValid heuristic post-RA");
178
180 "misched-prera-direction", cl::Hidden,
181 cl::desc("Pre reg-alloc list scheduling direction"),
184 clEnumValN(MISched::TopDown, "topdown",
185 "Force top-down pre reg-alloc list scheduling"),
186 clEnumValN(MISched::BottomUp, "bottomup",
187 "Force bottom-up pre reg-alloc list scheduling"),
188 clEnumValN(MISched::Bidirectional, "bidirectional",
189 "Force bidirectional pre reg-alloc list scheduling")));
190
192 "misched-postra-direction", cl::Hidden,
193 cl::desc("Post reg-alloc list scheduling direction"),
196 clEnumValN(MISched::TopDown, "topdown",
197 "Force top-down post reg-alloc list scheduling"),
198 clEnumValN(MISched::BottomUp, "bottomup",
199 "Force bottom-up post reg-alloc list scheduling"),
200 clEnumValN(MISched::Bidirectional, "bidirectional",
201 "Force bidirectional post reg-alloc list scheduling")));
202
203static cl::opt<bool>
205 cl::desc("Print critical path length to stdout"));
206
208 "verify-misched", cl::Hidden,
209 cl::desc("Verify machine instrs before and after machine scheduling"));
210
213
214#ifndef NDEBUG
216 "view-misched-dags", cl::Hidden,
217 cl::desc("Pop up a window to show MISched dags after they are processed"));
218cl::opt<bool> llvm::PrintDAGs("misched-print-dags", cl::Hidden,
219 cl::desc("Print schedule DAGs"));
221 "misched-dump-reserved-cycles", cl::Hidden, cl::init(false),
222 cl::desc("Dump resource usage at schedule boundary."));
224 "misched-detail-resource-booking", cl::Hidden, cl::init(false),
225 cl::desc("Show details of invoking getNextResoufceCycle."));
226#else
227const bool llvm::ViewMISchedDAGs = false;
228const bool llvm::PrintDAGs = false;
229static const bool MischedDetailResourceBooking = false;
230#ifdef LLVM_ENABLE_DUMP
231static const bool MISchedDumpReservedCycles = false;
232#endif // LLVM_ENABLE_DUMP
233#endif // NDEBUG
234
235#ifndef NDEBUG
236/// In some situations a few uninteresting nodes depend on nearly all other
237/// nodes in the graph, provide a cutoff to hide them.
238static cl::opt<unsigned> ViewMISchedCutoff("view-misched-cutoff", cl::Hidden,
239 cl::desc("Hide nodes with more predecessor/successor than cutoff"));
240
242 cl::desc("Stop scheduling after N instructions"), cl::init(~0U));
243
245 cl::desc("Only schedule this function"));
246static cl::opt<unsigned> SchedOnlyBlock("misched-only-block", cl::Hidden,
247 cl::desc("Only schedule this MBB#"));
248#endif // NDEBUG
249
250/// Avoid quadratic complexity in unusually large basic blocks by limiting the
251/// size of the ready lists.
253 cl::desc("Limit ready list to N instructions"), cl::init(256));
254
255static cl::opt<bool> EnableRegPressure("misched-regpressure", cl::Hidden,
256 cl::desc("Enable register pressure scheduling."), cl::init(true));
257
258static cl::opt<bool> EnableCyclicPath("misched-cyclicpath", cl::Hidden,
259 cl::desc("Enable cyclic critical path analysis."), cl::init(true));
260
262 cl::desc("Enable memop clustering."),
263 cl::init(true));
264static cl::opt<bool>
265 ForceFastCluster("force-fast-cluster", cl::Hidden,
266 cl::desc("Switch to fast cluster algorithm with the lost "
267 "of some fusion opportunities"),
268 cl::init(false));
270 FastClusterThreshold("fast-cluster-threshold", cl::Hidden,
271 cl::desc("The threshold for fast cluster"),
272 cl::init(1000));
273
274#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
276 "misched-dump-schedule-trace", cl::Hidden, cl::init(false),
277 cl::desc("Dump resource usage at schedule boundary."));
279 HeaderColWidth("misched-dump-schedule-trace-col-header-width", cl::Hidden,
280 cl::desc("Set width of the columns with "
281 "the resources and schedule units"),
282 cl::init(19));
284 ColWidth("misched-dump-schedule-trace-col-width", cl::Hidden,
285 cl::desc("Set width of the columns showing resource booking."),
286 cl::init(5));
288 "misched-sort-resources-in-trace", cl::Hidden, cl::init(true),
289 cl::desc("Sort the resources printed in the dump trace"));
290#endif
291
293 MIResourceCutOff("misched-resource-cutoff", cl::Hidden,
294 cl::desc("Number of intervals to track"), cl::init(10));
295
296// DAG subtrees must have at least this many nodes.
297static const unsigned MinSubtreeSize = 8;
298
299// Pin the vtables to this file.
300void MachineSchedStrategy::anchor() {}
301
302void ScheduleDAGMutation::anchor() {}
303
304//===----------------------------------------------------------------------===//
305// Machine Instruction Scheduling Pass and Registry
306//===----------------------------------------------------------------------===//
307
310
311namespace llvm {
312namespace impl_detail {
313
314/// Base class for the machine scheduler classes.
316protected:
317 void scheduleRegions(ScheduleDAGInstrs &Scheduler, bool FixKillFlags);
318};
319
320/// Impl class for MachineScheduler.
322 // These are only for using MF.verify()
323 // remove when verify supports passing in all analyses
324 MachineFunctionPass *P = nullptr;
325 MachineFunctionAnalysisManager *MFAM = nullptr;
326
327public:
335
337 // Migration only
338 void setLegacyPass(MachineFunctionPass *P) { this->P = P; }
339 void setMFAM(MachineFunctionAnalysisManager *MFAM) { this->MFAM = MFAM; }
340
341 bool run(MachineFunction &MF, const TargetMachine &TM,
342 const RequiredAnalyses &Analyses);
343
344protected:
346};
347
348/// Impl class for PostMachineScheduler.
350 // These are only for using MF.verify()
351 // remove when verify supports passing in all analyses
352 MachineFunctionPass *P = nullptr;
353 MachineFunctionAnalysisManager *MFAM = nullptr;
354
355public:
361 // Migration only
362 void setLegacyPass(MachineFunctionPass *P) { this->P = P; }
363 void setMFAM(MachineFunctionAnalysisManager *MFAM) { this->MFAM = MFAM; }
364
365 bool run(MachineFunction &Func, const TargetMachine &TM,
366 const RequiredAnalyses &Analyses);
367
368protected:
370};
371
372} // namespace impl_detail
373} // namespace llvm
374
378
379namespace {
380/// MachineScheduler runs after coalescing and before register allocation.
381class MachineSchedulerLegacy : public MachineFunctionPass {
382 MachineSchedulerImpl Impl;
383
384public:
385 MachineSchedulerLegacy();
386 void getAnalysisUsage(AnalysisUsage &AU) const override;
387 bool runOnMachineFunction(MachineFunction&) override;
388
389 static char ID; // Class identification, replacement for typeinfo
390};
391
392/// PostMachineScheduler runs after shortly before code emission.
393class PostMachineSchedulerLegacy : public MachineFunctionPass {
394 PostMachineSchedulerImpl Impl;
395
396public:
397 PostMachineSchedulerLegacy();
398 void getAnalysisUsage(AnalysisUsage &AU) const override;
399 bool runOnMachineFunction(MachineFunction &) override;
400
401 static char ID; // Class identification, replacement for typeinfo
402};
403
404} // end anonymous namespace
405
406char MachineSchedulerLegacy::ID = 0;
407
408char &llvm::MachineSchedulerID = MachineSchedulerLegacy::ID;
409
410INITIALIZE_PASS_BEGIN(MachineSchedulerLegacy, DEBUG_TYPE,
411 "Machine Instruction Scheduler", false, false)
417INITIALIZE_PASS_END(MachineSchedulerLegacy, DEBUG_TYPE,
418 "Machine Instruction Scheduler", false, false)
419
420MachineSchedulerLegacy::MachineSchedulerLegacy() : MachineFunctionPass(ID) {}
421
422void MachineSchedulerLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
423 AU.setPreservesCFG();
433}
434
435char PostMachineSchedulerLegacy::ID = 0;
436
437char &llvm::PostMachineSchedulerID = PostMachineSchedulerLegacy::ID;
438
439INITIALIZE_PASS_BEGIN(PostMachineSchedulerLegacy, "postmisched",
440 "PostRA Machine Instruction Scheduler", false, false)
444INITIALIZE_PASS_END(PostMachineSchedulerLegacy, "postmisched",
445 "PostRA Machine Instruction Scheduler", false, false)
446
447PostMachineSchedulerLegacy::PostMachineSchedulerLegacy()
448 : MachineFunctionPass(ID) {}
449
450void PostMachineSchedulerLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
451 AU.setPreservesCFG();
456}
457
460
461/// A dummy default scheduler factory indicates whether the scheduler
462/// is overridden on the command line.
466
467/// MachineSchedOpt allows command line selection of the scheduler.
472 cl::desc("Machine instruction scheduler to use"));
473
475DefaultSchedRegistry("default", "Use the target's default scheduler choice.",
477
479 "enable-misched",
480 cl::desc("Enable the machine instruction scheduling pass."), cl::init(true),
481 cl::Hidden);
482
484 "enable-post-misched",
485 cl::desc("Enable the post-ra machine instruction scheduling pass."),
486 cl::init(true), cl::Hidden);
487
488/// Decrement this iterator until reaching the top or a non-debug instr.
492 assert(I != Beg && "reached the top of the region, cannot decrement");
493 while (--I != Beg) {
494 if (!I->isDebugOrPseudoInstr())
495 break;
496 }
497 return I;
498}
499
500/// Non-const version.
507
508/// If this iterator is a debug value, increment until reaching the End or a
509/// non-debug instruction.
513 for(; I != End; ++I) {
514 if (!I->isDebugOrPseudoInstr())
515 break;
516 }
517 return I;
518}
519
520/// Non-const version.
527
528/// Instantiate a ScheduleDAGInstrs that will be owned by the caller.
530 // Select the scheduler, or set the default.
532 if (Ctor != useDefaultMachineSched)
533 return Ctor(this);
534
535 // Get the default scheduler set by the target for this function.
536 ScheduleDAGInstrs *Scheduler = TM->createMachineScheduler(this);
537 if (Scheduler)
538 return Scheduler;
539
540 // Default to GenericScheduler.
541 return createSchedLive(this);
542}
543
545 const RequiredAnalyses &Analyses) {
546 MF = &Func;
547 MLI = &Analyses.MLI;
548 this->TM = &TM;
549 AA = &Analyses.AA;
550 LIS = &Analyses.LIS;
551 RegClassInfo = &Analyses.RegClassInfo;
552 MBFI = &Analyses.MBFI;
553
554 if (VerifyScheduling) {
555 LLVM_DEBUG(LIS->dump());
556 const char *MSchedBanner = "Before machine scheduling.";
557 if (P)
558 MF->verify(P, MSchedBanner, &errs());
559 else
560 MF->verify(*MFAM, MSchedBanner, &errs());
561 }
562
563 // Instantiate the selected scheduler for this target, function, and
564 // optimization level.
565 std::unique_ptr<ScheduleDAGInstrs> Scheduler(createMachineScheduler());
566 scheduleRegions(*Scheduler, false);
567
568 LLVM_DEBUG(LIS->dump());
569 if (VerifyScheduling) {
570 const char *MSchedBanner = "After machine scheduling.";
571 if (P)
572 MF->verify(P, MSchedBanner, &errs());
573 else
574 MF->verify(*MFAM, MSchedBanner, &errs());
575 }
576 return true;
577}
578
579/// Instantiate a ScheduleDAGInstrs for PostRA scheduling that will be owned by
580/// the caller. We don't have a command line option to override the postRA
581/// scheduler. The Target must configure it.
583 // Get the postRA scheduler set by the target for this function.
584 ScheduleDAGInstrs *Scheduler = TM->createPostMachineScheduler(this);
585 if (Scheduler)
586 return Scheduler;
587
588 // Default to GenericScheduler.
589 return createSchedPostRA(this);
590}
591
593 const TargetMachine &TM,
594 const RequiredAnalyses &Analyses) {
595 MF = &Func;
596 MLI = &Analyses.MLI;
597 this->TM = &TM;
598 AA = &Analyses.AA;
599
600 if (VerifyScheduling) {
601 const char *PostMSchedBanner = "Before post machine scheduling.";
602 if (P)
603 MF->verify(P, PostMSchedBanner, &errs());
604 else
605 MF->verify(*MFAM, PostMSchedBanner, &errs());
606 }
607
608 // Instantiate the selected scheduler for this target, function, and
609 // optimization level.
610 std::unique_ptr<ScheduleDAGInstrs> Scheduler(createPostMachineScheduler());
612
613 if (VerifyScheduling) {
614 const char *PostMSchedBanner = "After post machine scheduling.";
615 if (P)
616 MF->verify(P, PostMSchedBanner, &errs());
617 else
618 MF->verify(*MFAM, PostMSchedBanner, &errs());
619 }
620 return true;
621}
622
623/// Top-level MachineScheduler pass driver.
624///
625/// Visit blocks in function order. Divide each block into scheduling regions
626/// and visit them bottom-up. Visiting regions bottom-up is not required, but is
627/// consistent with the DAG builder, which traverses the interior of the
628/// scheduling regions bottom-up.
629///
630/// This design avoids exposing scheduling boundaries to the DAG builder,
631/// simplifying the DAG builder's support for "special" target instructions.
632/// At the same time the design allows target schedulers to operate across
633/// scheduling boundaries, for example to bundle the boundary instructions
634/// without reordering them. This creates complexity, because the target
635/// scheduler must update the RegionBegin and RegionEnd positions cached by
636/// ScheduleDAGInstrs whenever adding or removing instructions. A much simpler
637/// design would be to split blocks at scheduling boundaries, but LLVM has a
638/// general bias against block splitting purely for implementation simplicity.
639bool MachineSchedulerLegacy::runOnMachineFunction(MachineFunction &MF) {
640 if (skipFunction(MF.getFunction()))
641 return false;
642
643 if (EnableMachineSched.getNumOccurrences()) {
645 return false;
646 } else if (!MF.getSubtarget().enableMachineScheduler()) {
647 return false;
648 }
649
650 LLVM_DEBUG(dbgs() << "Before MISched:\n"; MF.print(dbgs()));
651
652 auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
653 auto &TM = getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
654 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
655 auto &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
656 auto &RegClassInfo =
657 getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
658 auto &MBFI = getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
659
660 Impl.setLegacyPass(this);
661 return Impl.run(MF, TM, {MLI, AA, LIS, RegClassInfo, MBFI});
662}
663
665 : Impl(std::make_unique<MachineSchedulerImpl>()), TM(TM) {}
668 default;
669
671 : Impl(std::make_unique<PostMachineSchedulerImpl>()), TM(TM) {}
673 PostMachineSchedulerPass &&Other) = default;
675
679 if (EnableMachineSched.getNumOccurrences()) {
681 return PreservedAnalyses::all();
682 } else if (!MF.getSubtarget().enableMachineScheduler()) {
683 return PreservedAnalyses::all();
684 }
685
686 LLVM_DEBUG(dbgs() << "Before MISched:\n"; MF.print(dbgs()));
687 auto &MLI = MFAM.getResult<MachineLoopAnalysis>(MF);
689 .getManager();
690 auto &AA = FAM.getResult<AAManager>(MF.getFunction());
691 auto &LIS = MFAM.getResult<LiveIntervalsAnalysis>(MF);
692 auto &RegClassInfo = MFAM.getResult<MachineRegisterClassAnalysis>(MF);
693 auto &MBFI = MFAM.getResult<MachineBlockFrequencyAnalysis>(MF);
694
695 Impl->setMFAM(&MFAM);
696 bool Changed = Impl->run(MF, *TM, {MLI, AA, LIS, RegClassInfo, MBFI});
697 if (!Changed)
698 return PreservedAnalyses::all();
699
702 .preserve<SlotIndexesAnalysis>()
703 .preserve<LiveIntervalsAnalysis>();
704}
705
706bool PostMachineSchedulerLegacy::runOnMachineFunction(MachineFunction &MF) {
707 if (skipFunction(MF.getFunction()))
708 return false;
709
710 if (EnablePostRAMachineSched.getNumOccurrences()) {
712 return false;
713 } else if (!MF.getSubtarget().enablePostRAMachineScheduler()) {
714 LLVM_DEBUG(dbgs() << "Subtarget disables post-MI-sched.\n");
715 return false;
716 }
717 LLVM_DEBUG(dbgs() << "Before post-MI-sched:\n"; MF.print(dbgs()));
718 auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
719 auto &TM = getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
720 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
721 Impl.setLegacyPass(this);
722 return Impl.run(MF, TM, {MLI, AA});
723}
724
728 if (EnablePostRAMachineSched.getNumOccurrences()) {
730 return PreservedAnalyses::all();
731 } else if (!MF.getSubtarget().enablePostRAMachineScheduler()) {
732 LLVM_DEBUG(dbgs() << "Subtarget disables post-MI-sched.\n");
733 return PreservedAnalyses::all();
734 }
735 LLVM_DEBUG(dbgs() << "Before post-MI-sched:\n"; MF.print(dbgs()));
736 auto &MLI = MFAM.getResult<MachineLoopAnalysis>(MF);
738 .getManager();
739 auto &AA = FAM.getResult<AAManager>(MF.getFunction());
740
741 Impl->setMFAM(&MFAM);
742 bool Changed = Impl->run(MF, *TM, {MLI, AA});
743 if (!Changed)
744 return PreservedAnalyses::all();
745
748 return PA;
749}
750
751/// Return true of the given instruction should not be included in a scheduling
752/// region.
753///
754/// MachineScheduler does not currently support scheduling across calls. To
755/// handle calls, the DAG builder needs to be modified to create register
756/// anti/output dependencies on the registers clobbered by the call's regmask
757/// operand. In PreRA scheduling, the stack pointer adjustment already prevents
758/// scheduling across calls. In PostRA scheduling, we need the isCall to enforce
759/// the boundary, but there would be no benefit to postRA scheduling across
760/// calls this late anyway.
763 MachineFunction *MF,
764 const TargetInstrInfo *TII) {
765 return MI->isCall() || TII->isSchedulingBoundary(*MI, MBB, *MF) ||
766 MI->isFakeUse();
767}
768
770
771static void
773 MBBRegionsVector &Regions,
774 bool RegionsTopDown) {
775 MachineFunction *MF = MBB->getParent();
777
779 for(MachineBasicBlock::iterator RegionEnd = MBB->end();
780 RegionEnd != MBB->begin(); RegionEnd = I) {
781
782 // Avoid decrementing RegionEnd for blocks with no terminator.
783 if (RegionEnd != MBB->end() ||
784 isSchedBoundary(&*std::prev(RegionEnd), &*MBB, MF, TII)) {
785 --RegionEnd;
786 }
787
788 // The next region starts above the previous region. Look backward in the
789 // instruction stream until we find the nearest boundary.
790 unsigned NumRegionInstrs = 0;
791 I = RegionEnd;
792 for (;I != MBB->begin(); --I) {
793 MachineInstr &MI = *std::prev(I);
794 if (isSchedBoundary(&MI, &*MBB, MF, TII))
795 break;
796 if (!MI.isDebugOrPseudoInstr()) {
797 // MBB::size() uses instr_iterator to count. Here we need a bundle to
798 // count as a single instruction.
799 ++NumRegionInstrs;
800 }
801 }
802
803 // It's possible we found a scheduling region that only has debug
804 // instructions. Don't bother scheduling these.
805 if (NumRegionInstrs != 0)
806 Regions.push_back(SchedRegion(I, RegionEnd, NumRegionInstrs));
807 }
808
809 if (RegionsTopDown)
810 std::reverse(Regions.begin(), Regions.end());
811}
812
813/// Main driver for both MachineScheduler and PostMachineScheduler.
815 bool FixKillFlags) {
816 // Visit all machine basic blocks.
817 //
818 // TODO: Visit blocks in global postorder or postorder within the bottom-up
819 // loop tree. Then we can optionally compute global RegPressure.
820 for (MachineFunction::iterator MBB = MF->begin(), MBBEnd = MF->end();
821 MBB != MBBEnd; ++MBB) {
822#ifndef NDEBUG
823 if (SchedOnlyFunc.getNumOccurrences() && SchedOnlyFunc != MF->getName())
824 continue;
825 if (SchedOnlyBlock.getNumOccurrences()
826 && (int)SchedOnlyBlock != MBB->getNumber())
827 continue;
828#endif
829
830 Scheduler.startBlock(&*MBB);
831
832 // Break the block into scheduling regions [I, RegionEnd). RegionEnd
833 // points to the scheduling boundary at the bottom of the region. The DAG
834 // does not include RegionEnd, but the region does (i.e. the next
835 // RegionEnd is above the previous RegionBegin). If the current block has
836 // no terminator then RegionEnd == MBB->end() for the bottom region.
837 //
838 // All the regions of MBB are first found and stored in MBBRegions, which
839 // will be processed (MBB) top-down if initialized with true.
840 //
841 // The Scheduler may insert instructions during either schedule() or
842 // exitRegion(), even for empty regions. So the local iterators 'I' and
843 // 'RegionEnd' are invalid across these calls. Instructions must not be
844 // added to other regions than the current one without updating MBBRegions.
845
846 MBBRegionsVector MBBRegions;
847 getSchedRegions(&*MBB, MBBRegions, Scheduler.doMBBSchedRegionsTopDown());
848 bool ScheduleSingleMI = Scheduler.shouldScheduleSingleMIRegions();
849 for (const SchedRegion &R : MBBRegions) {
850 MachineBasicBlock::iterator I = R.RegionBegin;
851 MachineBasicBlock::iterator RegionEnd = R.RegionEnd;
852 unsigned NumRegionInstrs = R.NumRegionInstrs;
853
854 // Notify the scheduler of the region, even if we may skip scheduling
855 // it. Perhaps it still needs to be bundled.
856 Scheduler.enterRegion(&*MBB, I, RegionEnd, NumRegionInstrs);
857
858 // Skip empty scheduling regions and, conditionally, regions with a single
859 // MI.
860 if (I == RegionEnd || (!ScheduleSingleMI && I == std::prev(RegionEnd))) {
861 // Close the current region. Bundle the terminator if needed.
862 // This invalidates 'RegionEnd' and 'I'.
863 Scheduler.exitRegion();
864 continue;
865 }
866 auto DumpRegionHeader = [&] {
867 dbgs() << "Current Schedule Region\n";
868 dbgs() << MF->getName() << ":" << printMBBReference(*MBB) << " "
869 << MBB->getName() << "\n From: " << *I << " To: ";
870 if (RegionEnd != MBB->end())
871 dbgs() << *RegionEnd;
872 else
873 dbgs() << "End\n";
874 dbgs() << " RegionInstrs: " << NumRegionInstrs << '\n';
875 };
876 if (PrintDAGs)
877 DumpRegionHeader();
878 else
879 LLVM_DEBUG(DumpRegionHeader());
881 errs() << MF->getName();
882 errs() << ":%bb. " << MBB->getNumber();
883 errs() << " " << MBB->getName() << " \n";
884 }
885
886 // Schedule a region: possibly reorder instructions.
887 // This invalidates the original region iterators.
888 Scheduler.schedule();
889
890 // Close the current region.
891 Scheduler.exitRegion();
892 }
893 Scheduler.finishBlock();
894 // FIXME: Ideally, no further passes should rely on kill flags. However,
895 // thumb2 size reduction is currently an exception, so the PostMIScheduler
896 // needs to do this.
897 if (FixKillFlags)
898 Scheduler.fixupKills(*MBB);
899 }
900 Scheduler.finalizeSchedule();
901}
902
903#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
905 dbgs() << "Queue " << Name << ": ";
906 for (const SUnit *SU : Queue)
907 dbgs() << SU->NodeNum << " ";
908 dbgs() << "\n";
909}
910#endif
911
912//===----------------------------------------------------------------------===//
913// ScheduleDAGMI - Basic machine instruction scheduling. This is
914// independent of PreRA/PostRA scheduling and involves no extra book-keeping for
915// virtual registers.
916// ===----------------------------------------------------------------------===/
917
918// Provide a vtable anchor.
920
921/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. When
922/// NumPredsLeft reaches zero, release the successor node.
923///
924/// FIXME: Adjust SuccSU height based on MinLatency.
926 SUnit *SuccSU = SuccEdge->getSUnit();
927
928 if (SuccEdge->isWeak()) {
929 --SuccSU->WeakPredsLeft;
930 return;
931 }
932#ifndef NDEBUG
933 if (SuccSU->NumPredsLeft == 0) {
934 dbgs() << "*** Scheduling failed! ***\n";
935 dumpNode(*SuccSU);
936 dbgs() << " has been released too many times!\n";
937 llvm_unreachable(nullptr);
938 }
939#endif
940 // SU->TopReadyCycle was set to CurrCycle when it was scheduled. However,
941 // CurrCycle may have advanced since then.
942 if (SuccSU->TopReadyCycle < SU->TopReadyCycle + SuccEdge->getLatency())
943 SuccSU->TopReadyCycle = SU->TopReadyCycle + SuccEdge->getLatency();
944
945 --SuccSU->NumPredsLeft;
946 if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU)
947 SchedImpl->releaseTopNode(SuccSU);
948}
949
950/// releaseSuccessors - Call releaseSucc on each of SU's successors.
952 for (SDep &Succ : SU->Succs)
953 releaseSucc(SU, &Succ);
954}
955
956/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. When
957/// NumSuccsLeft reaches zero, release the predecessor node.
958///
959/// FIXME: Adjust PredSU height based on MinLatency.
961 SUnit *PredSU = PredEdge->getSUnit();
962
963 if (PredEdge->isWeak()) {
964 --PredSU->WeakSuccsLeft;
965 return;
966 }
967#ifndef NDEBUG
968 if (PredSU->NumSuccsLeft == 0) {
969 dbgs() << "*** Scheduling failed! ***\n";
970 dumpNode(*PredSU);
971 dbgs() << " has been released too many times!\n";
972 llvm_unreachable(nullptr);
973 }
974#endif
975 // SU->BotReadyCycle was set to CurrCycle when it was scheduled. However,
976 // CurrCycle may have advanced since then.
977 if (PredSU->BotReadyCycle < SU->BotReadyCycle + PredEdge->getLatency())
978 PredSU->BotReadyCycle = SU->BotReadyCycle + PredEdge->getLatency();
979
980 --PredSU->NumSuccsLeft;
981 if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU)
982 SchedImpl->releaseBottomNode(PredSU);
983}
984
985/// releasePredecessors - Call releasePred on each of SU's predecessors.
987 for (SDep &Pred : SU->Preds)
988 releasePred(SU, &Pred);
989}
990
995
1000
1001/// enterRegion - Called back from PostMachineScheduler::runOnMachineFunction
1002/// after crossing a scheduling boundary. [begin, end) includes all instructions
1003/// in the region, including the boundary itself and single-instruction regions
1004/// that don't get scheduled.
1008 unsigned regioninstrs)
1009{
1010 ScheduleDAGInstrs::enterRegion(bb, begin, end, regioninstrs);
1011
1012 SchedImpl->initPolicy(begin, end, regioninstrs);
1013
1014 // Set dump direction after initializing sched policy.
1016 if (SchedImpl->getPolicy().OnlyTopDown)
1018 else if (SchedImpl->getPolicy().OnlyBottomUp)
1020 else
1023}
1024
1025/// This is normally called from the main scheduler loop but may also be invoked
1026/// by the scheduling strategy to perform additional code motion.
1029 // Advance RegionBegin if the first instruction moves down.
1030 if (&*RegionBegin == MI)
1031 ++RegionBegin;
1032
1033 // Update the instruction stream.
1034 BB->splice(InsertPos, BB, MI);
1035
1036 // Update LiveIntervals
1037 if (LIS)
1038 LIS->handleMove(*MI, /*UpdateFlags=*/true);
1039
1040 // Recede RegionBegin if an instruction moves above the first.
1041 if (RegionBegin == InsertPos)
1042 RegionBegin = MI;
1043}
1044
1046#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
1047 if (NumInstrsScheduled == MISchedCutoff && MISchedCutoff != ~0U) {
1049 return false;
1050 }
1051 ++NumInstrsScheduled;
1052#endif
1053 return true;
1054}
1055
1056/// Per-region scheduling driver, called back from
1057/// PostMachineScheduler::runOnMachineFunction. This is a simplified driver
1058/// that does not consider liveness or register pressure. It is useful for
1059/// PostRA scheduling and potentially other custom schedulers.
1061 LLVM_DEBUG(dbgs() << "ScheduleDAGMI::schedule starting\n");
1062 LLVM_DEBUG(SchedImpl->dumpPolicy());
1063
1064 // Build the DAG.
1066
1068
1069 SmallVector<SUnit*, 8> TopRoots, BotRoots;
1070 findRootsAndBiasEdges(TopRoots, BotRoots);
1071
1072 LLVM_DEBUG(dump());
1073 if (PrintDAGs) dump();
1075
1076 // Initialize the strategy before modifying the DAG.
1077 // This may initialize a DFSResult to be used for queue priority.
1078 SchedImpl->initialize(this);
1079
1080 // Initialize ready queues now that the DAG and priority data are finalized.
1081 initQueues(TopRoots, BotRoots);
1082
1083 bool IsTopNode = false;
1084 while (true) {
1085 if (!checkSchedLimit())
1086 break;
1087
1088 LLVM_DEBUG(dbgs() << "** ScheduleDAGMI::schedule picking next node\n");
1089 SUnit *SU = SchedImpl->pickNode(IsTopNode);
1090 if (!SU) break;
1091
1092 assert(!SU->isScheduled && "Node already scheduled");
1093
1094 MachineInstr *MI = SU->getInstr();
1095 if (IsTopNode) {
1096 assert(SU->isTopReady() && "node still has unscheduled dependencies");
1097 if (&*CurrentTop == MI)
1099 else
1101 } else {
1102 assert(SU->isBottomReady() && "node still has unscheduled dependencies");
1105 if (&*priorII == MI)
1106 CurrentBottom = priorII;
1107 else {
1108 if (&*CurrentTop == MI)
1109 CurrentTop = nextIfDebug(++CurrentTop, priorII);
1111 CurrentBottom = MI;
1112 }
1113 }
1114 // Notify the scheduling strategy before updating the DAG.
1115 // This sets the scheduled node's ReadyCycle to CurrCycle. When updateQueues
1116 // runs, it can then use the accurate ReadyCycle time to determine whether
1117 // newly released nodes can move to the readyQ.
1118 SchedImpl->schedNode(SU, IsTopNode);
1119
1120 updateQueues(SU, IsTopNode);
1121 }
1122 assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
1123
1125
1126 LLVM_DEBUG({
1127 dbgs() << "*** Final schedule for "
1128 << printMBBReference(*begin()->getParent()) << " ***\n";
1129 dumpSchedule();
1130 dbgs() << '\n';
1131 });
1132}
1133
1134/// Apply each ScheduleDAGMutation step in order.
1136 for (auto &m : Mutations)
1137 m->apply(this);
1138}
1139
1142 SmallVectorImpl<SUnit*> &BotRoots) {
1143 for (SUnit &SU : SUnits) {
1144 assert(!SU.isBoundaryNode() && "Boundary node should not be in SUnits");
1145
1146 // Order predecessors so DFSResult follows the critical path.
1147 SU.biasCriticalPath();
1148
1149 // A SUnit is ready to top schedule if it has no predecessors.
1150 if (!SU.NumPredsLeft)
1151 TopRoots.push_back(&SU);
1152 // A SUnit is ready to bottom schedule if it has no successors.
1153 if (!SU.NumSuccsLeft)
1154 BotRoots.push_back(&SU);
1155 }
1156 ExitSU.biasCriticalPath();
1157}
1158
1159/// Identify DAG roots and setup scheduler queues.
1161 ArrayRef<SUnit *> BotRoots) {
1162 // Release all DAG roots for scheduling, not including EntrySU/ExitSU.
1163 //
1164 // Nodes with unreleased weak edges can still be roots.
1165 // Release top roots in forward order.
1166 for (SUnit *SU : TopRoots)
1167 SchedImpl->releaseTopNode(SU);
1168
1169 // Release bottom roots in reverse order so the higher priority nodes appear
1170 // first. This is more natural and slightly more efficient.
1172 I = BotRoots.rbegin(), E = BotRoots.rend(); I != E; ++I) {
1173 SchedImpl->releaseBottomNode(*I);
1174 }
1175
1178
1179 SchedImpl->registerRoots();
1180
1181 // Advance past initial DebugValues.
1184}
1185
1186/// Update scheduler queues after scheduling an instruction.
1187void ScheduleDAGMI::updateQueues(SUnit *SU, bool IsTopNode) {
1188 // Release dependent instructions for scheduling.
1189 if (IsTopNode)
1191 else
1193
1194 SU->isScheduled = true;
1195}
1196
1197/// Reinsert any remaining debug_values, just like the PostRA scheduler.
1199 // If first instruction was a DBG_VALUE then put it back.
1200 if (FirstDbgValue) {
1201 BB->splice(RegionBegin, BB, FirstDbgValue);
1203 }
1204
1205 for (std::vector<std::pair<MachineInstr *, MachineInstr *>>::iterator
1206 DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
1207 std::pair<MachineInstr *, MachineInstr *> P = *std::prev(DI);
1208 MachineInstr *DbgValue = P.first;
1209 MachineBasicBlock::iterator OrigPrevMI = P.second;
1210 if (&*RegionBegin == DbgValue)
1211 ++RegionBegin;
1212 BB->splice(std::next(OrigPrevMI), BB, DbgValue);
1213 if (RegionEnd != BB->end() && OrigPrevMI == &*RegionEnd)
1215 }
1216}
1217
1218#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1219static const char *scheduleTableLegend = " i: issue\n x: resource booked";
1220
1222 // Bail off when there is no schedule model to query.
1223 if (!SchedModel.hasInstrSchedModel())
1224 return;
1225
1226 // Nothing to show if there is no or just one instruction.
1227 if (BB->size() < 2)
1228 return;
1229
1230 dbgs() << " * Schedule table (TopDown):\n";
1231 dbgs() << scheduleTableLegend << "\n";
1232 const unsigned FirstCycle = getSUnit(&*(std::begin(*this)))->TopReadyCycle;
1233 unsigned LastCycle = getSUnit(&*(std::prev(std::end(*this))))->TopReadyCycle;
1234 for (MachineInstr &MI : *this) {
1235 SUnit *SU = getSUnit(&MI);
1236 if (!SU)
1237 continue;
1238 const MCSchedClassDesc *SC = getSchedClass(SU);
1239 for (TargetSchedModel::ProcResIter PI = SchedModel.getWriteProcResBegin(SC),
1240 PE = SchedModel.getWriteProcResEnd(SC);
1241 PI != PE; ++PI) {
1242 if (SU->TopReadyCycle + PI->ReleaseAtCycle - 1 > LastCycle)
1243 LastCycle = SU->TopReadyCycle + PI->ReleaseAtCycle - 1;
1244 }
1245 }
1246 // Print the header with the cycles
1247 dbgs() << llvm::left_justify("Cycle", HeaderColWidth);
1248 for (unsigned C = FirstCycle; C <= LastCycle; ++C)
1249 dbgs() << llvm::left_justify("| " + std::to_string(C), ColWidth);
1250 dbgs() << "|\n";
1251
1252 for (MachineInstr &MI : *this) {
1253 SUnit *SU = getSUnit(&MI);
1254 if (!SU) {
1255 dbgs() << "Missing SUnit\n";
1256 continue;
1257 }
1258 std::string NodeName("SU(");
1259 NodeName += std::to_string(SU->NodeNum) + ")";
1260 dbgs() << llvm::left_justify(NodeName, HeaderColWidth);
1261 unsigned C = FirstCycle;
1262 for (; C <= LastCycle; ++C) {
1263 if (C == SU->TopReadyCycle)
1264 dbgs() << llvm::left_justify("| i", ColWidth);
1265 else
1266 dbgs() << llvm::left_justify("|", ColWidth);
1267 }
1268 dbgs() << "|\n";
1269 const MCSchedClassDesc *SC = getSchedClass(SU);
1270
1272 make_range(SchedModel.getWriteProcResBegin(SC),
1273 SchedModel.getWriteProcResEnd(SC)));
1274
1277 ResourcesIt,
1278 [](const MCWriteProcResEntry &LHS,
1279 const MCWriteProcResEntry &RHS) -> bool {
1280 return std::tie(LHS.AcquireAtCycle, LHS.ReleaseAtCycle) <
1281 std::tie(RHS.AcquireAtCycle, RHS.ReleaseAtCycle);
1282 });
1283 for (const MCWriteProcResEntry &PI : ResourcesIt) {
1284 C = FirstCycle;
1285 const std::string ResName =
1286 SchedModel.getResourceName(PI.ProcResourceIdx);
1287 dbgs() << llvm::right_justify(ResName + " ", HeaderColWidth);
1288 for (; C < SU->TopReadyCycle + PI.AcquireAtCycle; ++C) {
1289 dbgs() << llvm::left_justify("|", ColWidth);
1290 }
1291 for (unsigned I = 0, E = PI.ReleaseAtCycle - PI.AcquireAtCycle; I != E;
1292 ++I, ++C)
1293 dbgs() << llvm::left_justify("| x", ColWidth);
1294 while (C++ <= LastCycle)
1295 dbgs() << llvm::left_justify("|", ColWidth);
1296 // Place end char
1297 dbgs() << "| \n";
1298 }
1299 }
1300}
1301
1303 // Bail off when there is no schedule model to query.
1304 if (!SchedModel.hasInstrSchedModel())
1305 return;
1306
1307 // Nothing to show if there is no or just one instruction.
1308 if (BB->size() < 2)
1309 return;
1310
1311 dbgs() << " * Schedule table (BottomUp):\n";
1312 dbgs() << scheduleTableLegend << "\n";
1313
1314 const int FirstCycle = getSUnit(&*(std::begin(*this)))->BotReadyCycle;
1315 int LastCycle = getSUnit(&*(std::prev(std::end(*this))))->BotReadyCycle;
1316 for (MachineInstr &MI : *this) {
1317 SUnit *SU = getSUnit(&MI);
1318 if (!SU)
1319 continue;
1320 const MCSchedClassDesc *SC = getSchedClass(SU);
1321 for (TargetSchedModel::ProcResIter PI = SchedModel.getWriteProcResBegin(SC),
1322 PE = SchedModel.getWriteProcResEnd(SC);
1323 PI != PE; ++PI) {
1324 if ((int)SU->BotReadyCycle - PI->ReleaseAtCycle + 1 < LastCycle)
1325 LastCycle = (int)SU->BotReadyCycle - PI->ReleaseAtCycle + 1;
1326 }
1327 }
1328 // Print the header with the cycles
1329 dbgs() << llvm::left_justify("Cycle", HeaderColWidth);
1330 for (int C = FirstCycle; C >= LastCycle; --C)
1331 dbgs() << llvm::left_justify("| " + std::to_string(C), ColWidth);
1332 dbgs() << "|\n";
1333
1334 for (MachineInstr &MI : *this) {
1335 SUnit *SU = getSUnit(&MI);
1336 if (!SU) {
1337 dbgs() << "Missing SUnit\n";
1338 continue;
1339 }
1340 std::string NodeName("SU(");
1341 NodeName += std::to_string(SU->NodeNum) + ")";
1342 dbgs() << llvm::left_justify(NodeName, HeaderColWidth);
1343 int C = FirstCycle;
1344 for (; C >= LastCycle; --C) {
1345 if (C == (int)SU->BotReadyCycle)
1346 dbgs() << llvm::left_justify("| i", ColWidth);
1347 else
1348 dbgs() << llvm::left_justify("|", ColWidth);
1349 }
1350 dbgs() << "|\n";
1351 const MCSchedClassDesc *SC = getSchedClass(SU);
1353 make_range(SchedModel.getWriteProcResBegin(SC),
1354 SchedModel.getWriteProcResEnd(SC)));
1355
1358 ResourcesIt,
1359 [](const MCWriteProcResEntry &LHS,
1360 const MCWriteProcResEntry &RHS) -> bool {
1361 return std::tie(LHS.AcquireAtCycle, LHS.ReleaseAtCycle) <
1362 std::tie(RHS.AcquireAtCycle, RHS.ReleaseAtCycle);
1363 });
1364 for (const MCWriteProcResEntry &PI : ResourcesIt) {
1365 C = FirstCycle;
1366 const std::string ResName =
1367 SchedModel.getResourceName(PI.ProcResourceIdx);
1368 dbgs() << llvm::right_justify(ResName + " ", HeaderColWidth);
1369 for (; C > ((int)SU->BotReadyCycle - (int)PI.AcquireAtCycle); --C) {
1370 dbgs() << llvm::left_justify("|", ColWidth);
1371 }
1372 for (unsigned I = 0, E = PI.ReleaseAtCycle - PI.AcquireAtCycle; I != E;
1373 ++I, --C)
1374 dbgs() << llvm::left_justify("| x", ColWidth);
1375 while (C-- >= LastCycle)
1376 dbgs() << llvm::left_justify("|", ColWidth);
1377 // Place end char
1378 dbgs() << "| \n";
1379 }
1380 }
1381}
1382#endif
1383
1384#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1389 else if (DumpDir == DumpDirection::BottomUp)
1392 dbgs() << "* Schedule table (Bidirectional): not implemented\n";
1393 } else {
1394 dbgs() << "* Schedule table: DumpDirection not set.\n";
1395 }
1396 }
1397
1398 for (MachineInstr &MI : *this) {
1399 if (SUnit *SU = getSUnit(&MI))
1400 dumpNode(*SU);
1401 else
1402 dbgs() << "Missing SUnit\n";
1403 }
1404}
1405#endif
1406
1407//===----------------------------------------------------------------------===//
1408// ScheduleDAGMILive - Base class for MachineInstr scheduling with LiveIntervals
1409// preservation.
1410//===----------------------------------------------------------------------===//
1411
1415
1417 const MachineInstr &MI = *SU.getInstr();
1418 for (const MachineOperand &MO : MI.operands()) {
1419 if (!MO.isReg())
1420 continue;
1421 if (!MO.readsReg())
1422 continue;
1423 if (TrackLaneMasks && !MO.isUse())
1424 continue;
1425
1426 Register Reg = MO.getReg();
1427 if (!Reg.isVirtual())
1428 continue;
1429
1430 // Ignore re-defs.
1431 if (TrackLaneMasks) {
1432 bool FoundDef = false;
1433 for (const MachineOperand &MO2 : MI.all_defs()) {
1434 if (MO2.getReg() == Reg && !MO2.isDead()) {
1435 FoundDef = true;
1436 break;
1437 }
1438 }
1439 if (FoundDef)
1440 continue;
1441 }
1442
1443 // Record this local VReg use.
1445 for (; UI != VRegUses.end(); ++UI) {
1446 if (UI->SU == &SU)
1447 break;
1448 }
1449 if (UI == VRegUses.end())
1450 VRegUses.insert(VReg2SUnit(Reg, LaneBitmask::getNone(), &SU));
1451 }
1452}
1453
1454/// enterRegion - Called back from MachineScheduler::runOnMachineFunction after
1455/// crossing a scheduling boundary. [begin, end) includes all instructions in
1456/// the region, including the boundary itself and single-instruction regions
1457/// that don't get scheduled.
1461 unsigned regioninstrs)
1462{
1463 // ScheduleDAGMI initializes SchedImpl's per-region policy.
1464 ScheduleDAGMI::enterRegion(bb, begin, end, regioninstrs);
1465
1466 // For convenience remember the end of the liveness region.
1467 LiveRegionEnd = (RegionEnd == bb->end()) ? RegionEnd : std::next(RegionEnd);
1468
1469 SUPressureDiffs.clear();
1470
1471 ShouldTrackPressure = SchedImpl->shouldTrackPressure();
1472 ShouldTrackLaneMasks = SchedImpl->shouldTrackLaneMasks();
1473
1475 "ShouldTrackLaneMasks requires ShouldTrackPressure");
1476}
1477
1478// Setup the register pressure trackers for the top scheduled and bottom
1479// scheduled regions.
1481 VRegUses.clear();
1482 VRegUses.setUniverse(MRI.getNumVirtRegs());
1483 for (SUnit &SU : SUnits)
1484 collectVRegUses(SU);
1485
1487 ShouldTrackLaneMasks, false);
1489 ShouldTrackLaneMasks, false);
1490
1491 // Close the RPTracker to finalize live ins.
1492 RPTracker.closeRegion();
1493
1494 LLVM_DEBUG(RPTracker.dump());
1495
1496 // Initialize the live ins and live outs.
1497 TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs);
1498 BotRPTracker.addLiveRegs(RPTracker.getPressure().LiveOutRegs);
1499
1500 // Close one end of the tracker so we can call
1501 // getMaxUpward/DownwardPressureDelta before advancing across any
1502 // instructions. This converts currently live regs into live ins/outs.
1503 TopRPTracker.closeTop();
1504 BotRPTracker.closeBottom();
1505
1506 BotRPTracker.initLiveThru(RPTracker);
1507 if (!BotRPTracker.getLiveThru().empty()) {
1508 TopRPTracker.initLiveThru(BotRPTracker.getLiveThru());
1509 LLVM_DEBUG(dbgs() << "Live Thru: ";
1510 dumpRegSetPressure(BotRPTracker.getLiveThru(), TRI));
1511 };
1512
1513 // For each live out vreg reduce the pressure change associated with other
1514 // uses of the same vreg below the live-out reaching def.
1515 updatePressureDiffs(RPTracker.getPressure().LiveOutRegs);
1516
1517 // Account for liveness generated by the region boundary.
1518 if (LiveRegionEnd != RegionEnd) {
1520 BotRPTracker.recede(&LiveUses);
1521 updatePressureDiffs(LiveUses);
1522 }
1523
1524 LLVM_DEBUG(dbgs() << "Top Pressure: ";
1525 dumpRegSetPressure(TopRPTracker.getRegSetPressureAtPos(), TRI);
1526 dbgs() << "Bottom Pressure: ";
1527 dumpRegSetPressure(BotRPTracker.getRegSetPressureAtPos(), TRI););
1528
1529 assert((BotRPTracker.getPos() == RegionEnd ||
1530 (RegionEnd->isDebugInstr() &&
1532 "Can't find the region bottom");
1533
1534 // Cache the list of excess pressure sets in this region. This will also track
1535 // the max pressure in the scheduled code for these sets.
1536 RegionCriticalPSets.clear();
1537 const std::vector<unsigned> &RegionPressure =
1538 RPTracker.getPressure().MaxSetPressure;
1539 for (unsigned i = 0, e = RegionPressure.size(); i < e; ++i) {
1540 unsigned Limit = RegClassInfo->getRegPressureSetLimit(i);
1541 if (RegionPressure[i] > Limit) {
1542 LLVM_DEBUG(dbgs() << TRI->getRegPressureSetName(i) << " Limit " << Limit
1543 << " Actual " << RegionPressure[i] << "\n");
1544 RegionCriticalPSets.push_back(PressureChange(i));
1545 }
1546 }
1547 LLVM_DEBUG({
1548 if (RegionCriticalPSets.size() > 0) {
1549 dbgs() << "Excess PSets: ";
1550 for (const PressureChange &RCPS : RegionCriticalPSets)
1551 dbgs() << TRI->getRegPressureSetName(RCPS.getPSet()) << " ";
1552 dbgs() << "\n";
1553 }
1554 });
1555}
1556
1559 const std::vector<unsigned> &NewMaxPressure) {
1560 const PressureDiff &PDiff = getPressureDiff(SU);
1561 unsigned CritIdx = 0, CritEnd = RegionCriticalPSets.size();
1562 for (const PressureChange &PC : PDiff) {
1563 if (!PC.isValid())
1564 break;
1565 unsigned ID = PC.getPSet();
1566 while (CritIdx != CritEnd && RegionCriticalPSets[CritIdx].getPSet() < ID)
1567 ++CritIdx;
1568 if (CritIdx != CritEnd && RegionCriticalPSets[CritIdx].getPSet() == ID) {
1569 if ((int)NewMaxPressure[ID] > RegionCriticalPSets[CritIdx].getUnitInc()
1570 && NewMaxPressure[ID] <= (unsigned)std::numeric_limits<int16_t>::max())
1571 RegionCriticalPSets[CritIdx].setUnitInc(NewMaxPressure[ID]);
1572 }
1573 unsigned Limit = RegClassInfo->getRegPressureSetLimit(ID);
1574 if (NewMaxPressure[ID] >= Limit - 2) {
1575 LLVM_DEBUG(dbgs() << " " << TRI->getRegPressureSetName(ID) << ": "
1576 << NewMaxPressure[ID]
1577 << ((NewMaxPressure[ID] > Limit) ? " > " : " <= ")
1578 << Limit << "(+ " << BotRPTracker.getLiveThru()[ID]
1579 << " livethru)\n");
1580 }
1581 }
1582}
1583
1584/// Update the PressureDiff array for liveness after scheduling this
1585/// instruction.
1587 for (const VRegMaskOrUnit &P : LiveUses) {
1588 /// FIXME: Currently assuming single-use physregs.
1589 if (!P.VRegOrUnit.isVirtualReg())
1590 continue;
1591 Register Reg = P.VRegOrUnit.asVirtualReg();
1592
1594 // If the register has just become live then other uses won't change
1595 // this fact anymore => decrement pressure.
1596 // If the register has just become dead then other uses make it come
1597 // back to life => increment pressure.
1598 bool Decrement = P.LaneMask.any();
1599
1600 for (const VReg2SUnit &V2SU
1601 : make_range(VRegUses.find(Reg), VRegUses.end())) {
1602 SUnit &SU = *V2SU.SU;
1603 if (SU.isScheduled || &SU == &ExitSU)
1604 continue;
1605
1606 PressureDiff &PDiff = getPressureDiff(&SU);
1607 PDiff.addPressureChange(VirtRegOrUnit(Reg), Decrement, &MRI);
1608 if (llvm::any_of(PDiff, [](const PressureChange &Change) {
1609 return Change.isValid();
1610 }))
1612 << " UpdateRegPressure: " << SU << " "
1613 << printReg(Reg, TRI) << ':'
1614 << PrintLaneMask(P.LaneMask) << ' ' << *SU.getInstr();
1615 dbgs() << " to "; PDiff.dump(*TRI););
1616 }
1617 } else {
1618 assert(P.LaneMask.any());
1619 LLVM_DEBUG(dbgs() << " LiveReg: " << printReg(Reg, TRI) << "\n");
1620 // This may be called before CurrentBottom has been initialized. However,
1621 // BotRPTracker must have a valid position. We want the value live into the
1622 // instruction or live out of the block, so ask for the previous
1623 // instruction's live-out.
1624 const LiveInterval &LI = LIS->getInterval(Reg);
1625 VNInfo *VNI;
1627 nextIfDebug(BotRPTracker.getPos(), BB->end());
1628 if (I == BB->end())
1629 VNI = LI.getVNInfoBefore(LIS->getMBBEndIdx(BB));
1630 else {
1631 LiveQueryResult LRQ = LI.Query(LIS->getInstructionIndex(*I));
1632 VNI = LRQ.valueIn();
1633 }
1634 // RegisterPressureTracker guarantees that readsReg is true for LiveUses.
1635 assert(VNI && "No live value at use.");
1636 for (const VReg2SUnit &V2SU
1637 : make_range(VRegUses.find(Reg), VRegUses.end())) {
1638 SUnit *SU = V2SU.SU;
1639 // If this use comes before the reaching def, it cannot be a last use,
1640 // so decrease its pressure change.
1641 if (!SU->isScheduled && SU != &ExitSU) {
1642 LiveQueryResult LRQ =
1643 LI.Query(LIS->getInstructionIndex(*SU->getInstr()));
1644 if (LRQ.valueIn() == VNI) {
1645 PressureDiff &PDiff = getPressureDiff(SU);
1646 PDiff.addPressureChange(VirtRegOrUnit(Reg), true, &MRI);
1647 if (llvm::any_of(PDiff, [](const PressureChange &Change) {
1648 return Change.isValid();
1649 }))
1650 LLVM_DEBUG(dbgs() << " UpdateRegPressure: " << *SU << " "
1651 << *SU->getInstr();
1652 dbgs() << " to ";
1653 PDiff.dump(*TRI););
1654 }
1655 }
1656 }
1657 }
1658 }
1659}
1660
1662#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1663 if (EntrySU.getInstr() != nullptr)
1665 for (const SUnit &SU : SUnits) {
1666 dumpNodeAll(SU);
1667 if (ShouldTrackPressure) {
1668 dbgs() << " Pressure Diff : ";
1669 getPressureDiff(&SU).dump(*TRI);
1670 }
1671 dbgs() << " Single Issue : ";
1672 if (SchedModel.mustBeginGroup(SU.getInstr()) &&
1673 SchedModel.mustEndGroup(SU.getInstr()))
1674 dbgs() << "true;";
1675 else
1676 dbgs() << "false;";
1677 dbgs() << '\n';
1678 }
1679 if (ExitSU.getInstr() != nullptr)
1681#endif
1682}
1683
1684/// schedule - Called back from MachineScheduler::runOnMachineFunction
1685/// after setting up the current scheduling region. [RegionBegin, RegionEnd)
1686/// only includes instructions that have DAG nodes, not scheduling boundaries.
1687///
1688/// This is a skeletal driver, with all the functionality pushed into helpers,
1689/// so that it can be easily extended by experimental schedulers. Generally,
1690/// implementing MachineSchedStrategy should be sufficient to implement a new
1691/// scheduling algorithm. However, if a scheduler further subclasses
1692/// ScheduleDAGMILive then it will want to override this virtual method in order
1693/// to update any specialized state.
1695 LLVM_DEBUG(dbgs() << "ScheduleDAGMILive::schedule starting\n");
1696 LLVM_DEBUG(SchedImpl->dumpPolicy());
1698
1700
1701 SmallVector<SUnit*, 8> TopRoots, BotRoots;
1702 findRootsAndBiasEdges(TopRoots, BotRoots);
1703
1704 // Initialize the strategy before modifying the DAG.
1705 // This may initialize a DFSResult to be used for queue priority.
1706 SchedImpl->initialize(this);
1707
1708 LLVM_DEBUG(dump());
1709 if (PrintDAGs) dump();
1711
1712 // Initialize ready queues now that the DAG and priority data are finalized.
1713 initQueues(TopRoots, BotRoots);
1714
1715 bool IsTopNode = false;
1716 while (true) {
1717 if (!checkSchedLimit())
1718 break;
1719
1720 LLVM_DEBUG(dbgs() << "** ScheduleDAGMILive::schedule picking next node\n");
1721 SUnit *SU = SchedImpl->pickNode(IsTopNode);
1722 if (!SU) break;
1723
1724 assert(!SU->isScheduled && "Node already scheduled");
1725
1726 scheduleMI(SU, IsTopNode);
1727
1728 if (DFSResult) {
1729 unsigned SubtreeID = DFSResult->getSubtreeID(SU);
1730 if (!ScheduledTrees.test(SubtreeID)) {
1731 ScheduledTrees.set(SubtreeID);
1732 DFSResult->scheduleTree(SubtreeID);
1733 SchedImpl->scheduleTree(SubtreeID);
1734 }
1735 }
1736
1737 // Notify the scheduling strategy after updating the DAG.
1738 SchedImpl->schedNode(SU, IsTopNode);
1739
1740 updateQueues(SU, IsTopNode);
1741 }
1742 assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
1743
1745
1746 LLVM_DEBUG({
1747 dbgs() << "*** Final schedule for "
1748 << printMBBReference(*begin()->getParent()) << " ***\n";
1749 dumpSchedule();
1750 dbgs() << '\n';
1751 });
1752}
1753
1754/// Build the DAG and setup three register pressure trackers.
1756 if (!ShouldTrackPressure) {
1757 RPTracker.reset();
1758 RegionCriticalPSets.clear();
1760 return;
1761 }
1762
1763 // Initialize the register pressure tracker used by buildSchedGraph.
1765 ShouldTrackLaneMasks, /*TrackUntiedDefs=*/true);
1766
1767 // Account for liveness generate by the region boundary.
1768 if (LiveRegionEnd != RegionEnd)
1769 RPTracker.recede();
1770
1771 // Build the DAG, and compute current register pressure.
1773
1774 // Initialize top/bottom trackers after computing region pressure.
1776}
1777
1779 if (!DFSResult)
1780 DFSResult = new SchedDFSResult(/*BottomU*/true, MinSubtreeSize);
1781 DFSResult->clear();
1782 ScheduledTrees.clear();
1783 DFSResult->resize(SUnits.size());
1784 DFSResult->compute(SUnits);
1785 ScheduledTrees.resize(DFSResult->getNumSubtrees());
1786}
1787
1788/// Compute the max cyclic critical path through the DAG. The scheduling DAG
1789/// only provides the critical path for single block loops. To handle loops that
1790/// span blocks, we could use the vreg path latencies provided by
1791/// MachineTraceMetrics instead. However, MachineTraceMetrics is not currently
1792/// available for use in the scheduler.
1793///
1794/// The cyclic path estimation identifies a def-use pair that crosses the back
1795/// edge and considers the depth and height of the nodes. For example, consider
1796/// the following instruction sequence where each instruction has unit latency
1797/// and defines an eponymous virtual register:
1798///
1799/// a->b(a,c)->c(b)->d(c)->exit
1800///
1801/// The cyclic critical path is a two cycles: b->c->b
1802/// The acyclic critical path is four cycles: a->b->c->d->exit
1803/// LiveOutHeight = height(c) = len(c->d->exit) = 2
1804/// LiveOutDepth = depth(c) + 1 = len(a->b->c) + 1 = 3
1805/// LiveInHeight = height(b) + 1 = len(b->c->d->exit) + 1 = 4
1806/// LiveInDepth = depth(b) = len(a->b) = 1
1807///
1808/// LiveOutDepth - LiveInDepth = 3 - 1 = 2
1809/// LiveInHeight - LiveOutHeight = 4 - 2 = 2
1810/// CyclicCriticalPath = min(2, 2) = 2
1811///
1812/// This could be relevant to PostRA scheduling, but is currently implemented
1813/// assuming LiveIntervals.
1815 // This only applies to single block loop.
1816 if (!BB->isSuccessor(BB))
1817 return 0;
1818
1819 unsigned MaxCyclicLatency = 0;
1820 // Visit each live out vreg def to find def/use pairs that cross iterations.
1821 for (const VRegMaskOrUnit &P : RPTracker.getPressure().LiveOutRegs) {
1822 if (!P.VRegOrUnit.isVirtualReg())
1823 continue;
1824 Register Reg = P.VRegOrUnit.asVirtualReg();
1825 const LiveInterval &LI = LIS->getInterval(Reg);
1826 const VNInfo *DefVNI = LI.getVNInfoBefore(LIS->getMBBEndIdx(BB));
1827 if (!DefVNI)
1828 continue;
1829
1830 MachineInstr *DefMI = LIS->getInstructionFromIndex(DefVNI->def);
1831 const SUnit *DefSU = getSUnit(DefMI);
1832 if (!DefSU)
1833 continue;
1834
1835 unsigned LiveOutHeight = DefSU->getHeight();
1836 unsigned LiveOutDepth = DefSU->getDepth() + DefSU->Latency;
1837 // Visit all local users of the vreg def.
1838 for (const VReg2SUnit &V2SU
1839 : make_range(VRegUses.find(Reg), VRegUses.end())) {
1840 SUnit *SU = V2SU.SU;
1841 if (SU == &ExitSU)
1842 continue;
1843
1844 // Only consider uses of the phi.
1845 LiveQueryResult LRQ = LI.Query(LIS->getInstructionIndex(*SU->getInstr()));
1846 if (!LRQ.valueIn()->isPHIDef())
1847 continue;
1848
1849 // Assume that a path spanning two iterations is a cycle, which could
1850 // overestimate in strange cases. This allows cyclic latency to be
1851 // estimated as the minimum slack of the vreg's depth or height.
1852 unsigned CyclicLatency = 0;
1853 if (LiveOutDepth > SU->getDepth())
1854 CyclicLatency = LiveOutDepth - SU->getDepth();
1855
1856 unsigned LiveInHeight = SU->getHeight() + DefSU->Latency;
1857 if (LiveInHeight > LiveOutHeight) {
1858 if (LiveInHeight - LiveOutHeight < CyclicLatency)
1859 CyclicLatency = LiveInHeight - LiveOutHeight;
1860 } else
1861 CyclicLatency = 0;
1862
1863 LLVM_DEBUG(dbgs() << "Cyclic Path: " << *DefSU << " -> " << *SU << " = "
1864 << CyclicLatency << "c\n");
1865 if (CyclicLatency > MaxCyclicLatency)
1866 MaxCyclicLatency = CyclicLatency;
1867 }
1868 }
1869 LLVM_DEBUG(dbgs() << "Cyclic Critical Path: " << MaxCyclicLatency << "c\n");
1870 return MaxCyclicLatency;
1871}
1872
1873/// Release ExitSU predecessors and setup scheduler queues. Re-position
1874/// the Top RP tracker in case the region beginning has changed.
1876 ArrayRef<SUnit*> BotRoots) {
1877 ScheduleDAGMI::initQueues(TopRoots, BotRoots);
1878 if (ShouldTrackPressure) {
1879 assert(TopRPTracker.getPos() == RegionBegin && "bad initial Top tracker");
1880 TopRPTracker.setPos(CurrentTop);
1881 }
1882}
1883
1884/// Move an instruction and update register pressure.
1885void ScheduleDAGMILive::scheduleMI(SUnit *SU, bool IsTopNode) {
1886 // Move the instruction to its new location in the instruction stream.
1887 MachineInstr *MI = SU->getInstr();
1888
1889 if (IsTopNode) {
1890 assert(SU->isTopReady() && "node still has unscheduled dependencies");
1891 if (&*CurrentTop == MI)
1893 else {
1895 TopRPTracker.setPos(MI);
1896 }
1897
1898 if (ShouldTrackPressure) {
1899 // Update top scheduled pressure.
1900 RegisterOperands RegOpers;
1901 RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks,
1902 /*IgnoreDead=*/false);
1904 // Adjust liveness and add missing dead+read-undef flags.
1905 RegOpers.adjustLaneLiveness(*LIS, MRI, *MI);
1906 } else {
1907 // Adjust for missing dead-def flags.
1908 RegOpers.detectDeadDefs(*MI, *LIS, MRI);
1909 }
1910
1911 TopRPTracker.advance(RegOpers);
1912 assert(TopRPTracker.getPos() == CurrentTop && "out of sync");
1913 LLVM_DEBUG(dbgs() << "Top Pressure: "; dumpRegSetPressure(
1914 TopRPTracker.getRegSetPressureAtPos(), TRI););
1915
1916 updateScheduledPressure(SU, TopRPTracker.getPressure().MaxSetPressure);
1917 }
1918 } else {
1919 assert(SU->isBottomReady() && "node still has unscheduled dependencies");
1922 if (&*priorII == MI)
1923 CurrentBottom = priorII;
1924 else {
1925 if (&*CurrentTop == MI) {
1926 CurrentTop = nextIfDebug(++CurrentTop, priorII);
1927 TopRPTracker.setPos(CurrentTop);
1928 }
1930 CurrentBottom = MI;
1932 }
1933 if (ShouldTrackPressure) {
1934 RegisterOperands RegOpers;
1935 RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks,
1936 /*IgnoreDead=*/false);
1938 // Adjust liveness and add missing dead+read-undef flags.
1939 RegOpers.adjustLaneLiveness(*LIS, MRI, *MI);
1940 } else {
1941 // Adjust for missing dead-def flags.
1942 RegOpers.detectDeadDefs(*MI, *LIS, MRI);
1943 }
1944
1945 if (BotRPTracker.getPos() != CurrentBottom)
1946 BotRPTracker.recedeSkipDebugValues();
1948 BotRPTracker.recede(RegOpers, &LiveUses);
1949 assert(BotRPTracker.getPos() == CurrentBottom && "out of sync");
1950 LLVM_DEBUG(dbgs() << "Bottom Pressure: "; dumpRegSetPressure(
1951 BotRPTracker.getRegSetPressureAtPos(), TRI););
1952
1953 updateScheduledPressure(SU, BotRPTracker.getPressure().MaxSetPressure);
1954 updatePressureDiffs(LiveUses);
1955 }
1956 }
1957}
1958
1959//===----------------------------------------------------------------------===//
1960// BaseMemOpClusterMutation - DAG post-processing to cluster loads or stores.
1961//===----------------------------------------------------------------------===//
1962
1963namespace {
1964
1965/// Post-process the DAG to create cluster edges between neighboring
1966/// loads or between neighboring stores.
1967class BaseMemOpClusterMutation : public ScheduleDAGMutation {
1968 struct MemOpInfo {
1969 SUnit *SU;
1971 int64_t Offset;
1972 LocationSize Width;
1973 bool OffsetIsScalable;
1974
1975 MemOpInfo(SUnit *SU, ArrayRef<const MachineOperand *> BaseOps,
1976 int64_t Offset, bool OffsetIsScalable, LocationSize Width)
1977 : SU(SU), BaseOps(BaseOps), Offset(Offset), Width(Width),
1978 OffsetIsScalable(OffsetIsScalable) {}
1979
1980 static bool Compare(const MachineOperand *const &A,
1981 const MachineOperand *const &B) {
1982 if (A->getType() != B->getType())
1983 return A->getType() < B->getType();
1984 if (A->isReg())
1985 return A->getReg() < B->getReg();
1986 if (A->isFI()) {
1987 const MachineFunction &MF = *A->getParent()->getParent()->getParent();
1988 const MachineFrameInfo &MFI = MF.getFrameInfo();
1990 bool StackGrowsDown = TFI.getStackGrowthDirection() ==
1992 bool AIsFixed = MFI.isFixedObjectIndex(A->getIndex());
1993 bool BIsFixed = MFI.isFixedObjectIndex(B->getIndex());
1994 // Sort fixed and non-fixed bases as separate groups, preserving the
1995 // existing frame-index ordering between the groups. Do not rely on
1996 // non-fixed object offsets before frame layout.
1997 if (AIsFixed != BIsFixed)
1998 return StackGrowsDown ? !AIsFixed : AIsFixed;
1999 if (AIsFixed) {
2000 // Fixed objects have explicit offsets, and targets may create their
2001 // frame indices in an order unrelated to those offsets. Sort by the
2002 // actual object offsets so target clustering hooks see fixed object
2003 // bases in address order.
2004 int64_t AOffset = MFI.getObjectOffset(A->getIndex());
2005 int64_t BOffset = MFI.getObjectOffset(B->getIndex());
2006 if (AOffset != BOffset)
2007 return AOffset < BOffset;
2008 }
2009 return StackGrowsDown ? A->getIndex() > B->getIndex()
2010 : A->getIndex() < B->getIndex();
2011 }
2012
2013 llvm_unreachable("MemOpClusterMutation only supports register or frame "
2014 "index bases.");
2015 }
2016
2017 bool operator<(const MemOpInfo &RHS) const {
2018 // FIXME: Don't compare everything twice. Maybe use C++20 three way
2019 // comparison instead when it's available.
2020 if (std::lexicographical_compare(BaseOps.begin(), BaseOps.end(),
2021 RHS.BaseOps.begin(), RHS.BaseOps.end(),
2022 Compare))
2023 return true;
2024 if (std::lexicographical_compare(RHS.BaseOps.begin(), RHS.BaseOps.end(),
2025 BaseOps.begin(), BaseOps.end(), Compare))
2026 return false;
2027 if (Offset != RHS.Offset)
2028 return Offset < RHS.Offset;
2029 return SU->NodeNum < RHS.SU->NodeNum;
2030 }
2031 };
2032
2033 const TargetInstrInfo *TII;
2034 const TargetRegisterInfo *TRI;
2035 bool IsLoad;
2036 bool ReorderWhileClustering;
2037
2038public:
2039 BaseMemOpClusterMutation(const TargetInstrInfo *tii,
2040 const TargetRegisterInfo *tri, bool IsLoad,
2041 bool ReorderWhileClustering)
2042 : TII(tii), TRI(tri), IsLoad(IsLoad),
2043 ReorderWhileClustering(ReorderWhileClustering) {}
2044
2045 void apply(ScheduleDAGInstrs *DAGInstrs) override;
2046
2047protected:
2048 void clusterNeighboringMemOps(ArrayRef<MemOpInfo> MemOps, bool FastCluster,
2049 ScheduleDAGInstrs *DAG);
2050 void collectMemOpRecords(std::vector<SUnit> &SUnits,
2051 SmallVectorImpl<MemOpInfo> &MemOpRecords);
2052 bool groupMemOps(ArrayRef<MemOpInfo> MemOps, ScheduleDAGInstrs *DAG,
2053 DenseMap<unsigned, SmallVector<MemOpInfo, 32>> &Groups);
2054};
2055
2056class StoreClusterMutation : public BaseMemOpClusterMutation {
2057public:
2058 StoreClusterMutation(const TargetInstrInfo *tii,
2059 const TargetRegisterInfo *tri,
2060 bool ReorderWhileClustering)
2061 : BaseMemOpClusterMutation(tii, tri, false, ReorderWhileClustering) {}
2062};
2063
2064class LoadClusterMutation : public BaseMemOpClusterMutation {
2065public:
2066 LoadClusterMutation(const TargetInstrInfo *tii, const TargetRegisterInfo *tri,
2067 bool ReorderWhileClustering)
2068 : BaseMemOpClusterMutation(tii, tri, true, ReorderWhileClustering) {}
2069};
2070
2071} // end anonymous namespace
2072
2073std::unique_ptr<ScheduleDAGMutation>
2075 const TargetRegisterInfo *TRI,
2076 bool ReorderWhileClustering) {
2077 return EnableMemOpCluster ? std::make_unique<LoadClusterMutation>(
2078 TII, TRI, ReorderWhileClustering)
2079 : nullptr;
2080}
2081
2082std::unique_ptr<ScheduleDAGMutation>
2084 const TargetRegisterInfo *TRI,
2085 bool ReorderWhileClustering) {
2086 return EnableMemOpCluster ? std::make_unique<StoreClusterMutation>(
2087 TII, TRI, ReorderWhileClustering)
2088 : nullptr;
2089}
2090
2091// Sorting all the loads/stores first, then for each load/store, checking the
2092// following load/store one by one, until reach the first non-dependent one and
2093// call target hook to see if they can cluster.
2094// If FastCluster is enabled, we assume that, all the loads/stores have been
2095// preprocessed and now, they didn't have dependencies on each other.
2096void BaseMemOpClusterMutation::clusterNeighboringMemOps(
2097 ArrayRef<MemOpInfo> MemOpRecords, bool FastCluster,
2098 ScheduleDAGInstrs *DAG) {
2099 // Keep track of the current cluster length and bytes for each SUnit.
2102
2103 // At this point, `MemOpRecords` array must hold atleast two mem ops. Try to
2104 // cluster mem ops collected within `MemOpRecords` array.
2105 for (unsigned Idx = 0, End = MemOpRecords.size(); Idx < (End - 1); ++Idx) {
2106 // Decision to cluster mem ops is taken based on target dependent logic
2107 auto MemOpa = MemOpRecords[Idx];
2108
2109 // Seek for the next load/store to do the cluster.
2110 unsigned NextIdx = Idx + 1;
2111 for (; NextIdx < End; ++NextIdx)
2112 // Skip if MemOpb has been clustered already or has dependency with
2113 // MemOpa.
2114 if (!SUnit2ClusterInfo.count(MemOpRecords[NextIdx].SU->NodeNum) &&
2115 (FastCluster ||
2116 (!DAG->IsReachable(MemOpRecords[NextIdx].SU, MemOpa.SU) &&
2117 !DAG->IsReachable(MemOpa.SU, MemOpRecords[NextIdx].SU))))
2118 break;
2119 if (NextIdx == End)
2120 continue;
2121
2122 auto MemOpb = MemOpRecords[NextIdx];
2123 unsigned ClusterLength = 2;
2124 unsigned CurrentClusterBytes = MemOpa.Width.getValue().getKnownMinValue() +
2125 MemOpb.Width.getValue().getKnownMinValue();
2126 auto It = SUnit2ClusterInfo.find(MemOpa.SU->NodeNum);
2127 if (It != SUnit2ClusterInfo.end()) {
2128 const auto &[Len, Bytes] = It->second;
2129 ClusterLength = Len + 1;
2130 CurrentClusterBytes = Bytes + MemOpb.Width.getValue().getKnownMinValue();
2131 }
2132
2133 if (!TII->shouldClusterMemOps(MemOpa.BaseOps, MemOpa.Offset,
2134 MemOpa.OffsetIsScalable, MemOpb.BaseOps,
2135 MemOpb.Offset, MemOpb.OffsetIsScalable,
2136 ClusterLength, CurrentClusterBytes))
2137 continue;
2138
2139 SUnit *SUa = MemOpa.SU;
2140 SUnit *SUb = MemOpb.SU;
2141
2142 if (!ReorderWhileClustering && SUa->NodeNum > SUb->NodeNum)
2143 std::swap(SUa, SUb);
2144
2145 // FIXME: Is this check really required?
2146 if (!DAG->addEdge(SUb, SDep(SUa, SDep::Cluster)))
2147 continue;
2148
2149 Clusters.unionSets(SUa, SUb);
2150 LLVM_DEBUG(dbgs() << "Cluster ld/st " << *SUa << " - " << *SUb << "\n");
2151 ++NumClustered;
2152
2153 if (IsLoad) {
2154 // Copy successor edges from SUa to SUb. Interleaving computation
2155 // dependent on SUa can prevent load combining due to register reuse.
2156 // Predecessor edges do not need to be copied from SUb to SUa since
2157 // nearby loads should have effectively the same inputs.
2158 for (const SDep &Succ : SUa->Succs) {
2159 if (Succ.getSUnit() == SUb)
2160 continue;
2161 LLVM_DEBUG(dbgs() << " Copy Succ SU(" << Succ.getSUnit()->NodeNum
2162 << ")\n");
2163 DAG->addEdge(Succ.getSUnit(), SDep(SUb, SDep::Artificial));
2164 }
2165 } else {
2166 // Copy predecessor edges from SUb to SUa to avoid the SUnits that
2167 // SUb dependent on scheduled in-between SUb and SUa. Successor edges
2168 // do not need to be copied from SUa to SUb since no one will depend
2169 // on stores.
2170 // Notice that, we don't need to care about the memory dependency as
2171 // we won't try to cluster them if they have any memory dependency.
2172 for (const SDep &Pred : SUb->Preds) {
2173 if (Pred.getSUnit() == SUa)
2174 continue;
2175 LLVM_DEBUG(dbgs() << " Copy Pred " << *Pred.getSUnit() << "\n");
2176 DAG->addEdge(SUa, SDep(Pred.getSUnit(), SDep::Artificial));
2177 }
2178 }
2179
2180 SUnit2ClusterInfo[MemOpb.SU->NodeNum] = {ClusterLength,
2181 CurrentClusterBytes};
2182
2183 LLVM_DEBUG(dbgs() << " Curr cluster length: " << ClusterLength
2184 << ", Curr cluster bytes: " << CurrentClusterBytes
2185 << "\n");
2186 }
2187
2188 // Add cluster group information.
2189 // Iterate over all of the equivalence sets.
2190 auto &AllClusters = DAG->getClusters();
2191 for (const EquivalenceClasses<SUnit *>::ECValue *I : Clusters) {
2192 if (!I->isLeader())
2193 continue;
2194 ClusterInfo Group;
2195 unsigned ClusterIdx = AllClusters.size();
2196 for (SUnit *MemberI : Clusters.members(*I)) {
2197 MemberI->ParentClusterIdx = ClusterIdx;
2198 Group.insert(MemberI);
2199 }
2200 AllClusters.push_back(Group);
2201 }
2202}
2203
2204void BaseMemOpClusterMutation::collectMemOpRecords(
2205 std::vector<SUnit> &SUnits, SmallVectorImpl<MemOpInfo> &MemOpRecords) {
2206 for (auto &SU : SUnits) {
2207 if ((IsLoad && !SU.getInstr()->mayLoad()) ||
2208 (!IsLoad && !SU.getInstr()->mayStore()))
2209 continue;
2210
2211 const MachineInstr &MI = *SU.getInstr();
2213 int64_t Offset;
2214 bool OffsetIsScalable;
2217 OffsetIsScalable, Width, TRI)) {
2218 if (!Width.hasValue())
2219 continue;
2220
2221 MemOpRecords.push_back(
2222 MemOpInfo(&SU, BaseOps, Offset, OffsetIsScalable, Width));
2223
2224 LLVM_DEBUG(dbgs() << "Num BaseOps: " << BaseOps.size() << ", Offset: "
2225 << Offset << ", OffsetIsScalable: " << OffsetIsScalable
2226 << ", Width: " << Width << "\n");
2227 }
2228#ifndef NDEBUG
2229 for (const auto *Op : BaseOps)
2230 assert(Op);
2231#endif
2232 }
2233}
2234
2235bool BaseMemOpClusterMutation::groupMemOps(
2238 bool FastCluster =
2240 MemOps.size() * DAG->SUnits.size() / 1000 > FastClusterThreshold;
2241
2242 for (const auto &MemOp : MemOps) {
2243 unsigned ChainPredID = DAG->SUnits.size();
2244 if (FastCluster) {
2245 for (const SDep &Pred : MemOp.SU->Preds) {
2246 // We only want to cluster the mem ops that have the same ctrl(non-data)
2247 // pred so that they didn't have ctrl dependency for each other. But for
2248 // store instrs, we can still cluster them if the pred is load instr.
2249 if ((Pred.isCtrl() &&
2250 (IsLoad ||
2251 (Pred.getSUnit() && Pred.getSUnit()->getInstr()->mayStore()))) &&
2252 !Pred.isArtificial()) {
2253 ChainPredID = Pred.getSUnit()->NodeNum;
2254 break;
2255 }
2256 }
2257 } else
2258 ChainPredID = 0;
2259
2260 Groups[ChainPredID].push_back(MemOp);
2261 }
2262 return FastCluster;
2263}
2264
2265/// Callback from DAG postProcessing to create cluster edges for loads/stores.
2266void BaseMemOpClusterMutation::apply(ScheduleDAGInstrs *DAG) {
2267 // Collect all the clusterable loads/stores
2268 SmallVector<MemOpInfo, 32> MemOpRecords;
2269 collectMemOpRecords(DAG->SUnits, MemOpRecords);
2270
2271 if (MemOpRecords.size() < 2)
2272 return;
2273
2274 // Put the loads/stores without dependency into the same group with some
2275 // heuristic if the DAG is too complex to avoid compiling time blow up.
2276 // Notice that, some fusion pair could be lost with this.
2278 bool FastCluster = groupMemOps(MemOpRecords, DAG, Groups);
2279
2280 for (auto &Group : Groups) {
2281 // Sorting the loads/stores, so that, we can stop the cluster as early as
2282 // possible.
2283 llvm::sort(Group.second);
2284
2285 // Trying to cluster all the neighboring loads/stores.
2286 clusterNeighboringMemOps(Group.second, FastCluster, DAG);
2287 }
2288}
2289
2290//===----------------------------------------------------------------------===//
2291// CopyConstrain - DAG post-processing to encourage copy elimination.
2292//===----------------------------------------------------------------------===//
2293
2294namespace {
2295
2296/// Post-process the DAG to create weak edges from all uses of a copy to
2297/// the one use that defines the copy's source vreg, most likely an induction
2298/// variable increment.
2299class CopyConstrain : public ScheduleDAGMutation {
2300 // Transient state.
2301 SlotIndex RegionBeginIdx;
2302
2303 // RegionEndIdx is the slot index of the last non-debug instruction in the
2304 // scheduling region. So we may have RegionBeginIdx == RegionEndIdx.
2305 SlotIndex RegionEndIdx;
2306
2307public:
2308 CopyConstrain(const TargetInstrInfo *, const TargetRegisterInfo *) {}
2309
2310 void apply(ScheduleDAGInstrs *DAGInstrs) override;
2311
2312protected:
2313 void constrainLocalCopy(SUnit *CopySU, ScheduleDAGMILive *DAG);
2314};
2315
2316} // end anonymous namespace
2317
2318std::unique_ptr<ScheduleDAGMutation>
2320 const TargetRegisterInfo *TRI) {
2321 return std::make_unique<CopyConstrain>(TII, TRI);
2322}
2323
2324/// constrainLocalCopy handles two possibilities:
2325/// 1) Local src:
2326/// I0: = dst
2327/// I1: src = ...
2328/// I2: = dst
2329/// I3: dst = src (copy)
2330/// (create pred->succ edges I0->I1, I2->I1)
2331///
2332/// 2) Local copy:
2333/// I0: dst = src (copy)
2334/// I1: = dst
2335/// I2: src = ...
2336/// I3: = dst
2337/// (create pred->succ edges I1->I2, I3->I2)
2338///
2339/// Although the MachineScheduler is currently constrained to single blocks,
2340/// this algorithm should handle extended blocks. An EBB is a set of
2341/// contiguously numbered blocks such that the previous block in the EBB is
2342/// always the single predecessor.
2343void CopyConstrain::constrainLocalCopy(SUnit *CopySU, ScheduleDAGMILive *DAG) {
2344 LiveIntervals *LIS = DAG->getLIS();
2345 MachineInstr *Copy = CopySU->getInstr();
2346
2347 // Check for pure vreg copies.
2348 const MachineOperand &SrcOp = Copy->getOperand(1);
2349 Register SrcReg = SrcOp.getReg();
2350 if (!SrcReg.isVirtual() || !SrcOp.readsReg())
2351 return;
2352
2353 const MachineOperand &DstOp = Copy->getOperand(0);
2354 Register DstReg = DstOp.getReg();
2355 if (!DstReg.isVirtual() || DstOp.isDead())
2356 return;
2357
2358 // Check if either the dest or source is local. If it's live across a back
2359 // edge, it's not local. Note that if both vregs are live across the back
2360 // edge, we cannot successfully contrain the copy without cyclic scheduling.
2361 // If both the copy's source and dest are local live intervals, then we
2362 // should treat the dest as the global for the purpose of adding
2363 // constraints. This adds edges from source's other uses to the copy.
2364 unsigned LocalReg = SrcReg;
2365 unsigned GlobalReg = DstReg;
2366 LiveInterval *LocalLI = &LIS->getInterval(LocalReg);
2367 if (!LocalLI->isLocal(RegionBeginIdx, RegionEndIdx)) {
2368 LocalReg = DstReg;
2369 GlobalReg = SrcReg;
2370 LocalLI = &LIS->getInterval(LocalReg);
2371 if (!LocalLI->isLocal(RegionBeginIdx, RegionEndIdx))
2372 return;
2373 }
2374 LiveInterval *GlobalLI = &LIS->getInterval(GlobalReg);
2375
2376 // Find the global segment after the start of the local LI.
2377 LiveInterval::iterator GlobalSegment = GlobalLI->find(LocalLI->beginIndex());
2378 // If GlobalLI does not overlap LocalLI->start, then a copy directly feeds a
2379 // local live range. We could create edges from other global uses to the local
2380 // start, but the coalescer should have already eliminated these cases, so
2381 // don't bother dealing with it.
2382 if (GlobalSegment == GlobalLI->end())
2383 return;
2384
2385 // If GlobalSegment is killed at the LocalLI->start, the call to find()
2386 // returned the next global segment. But if GlobalSegment overlaps with
2387 // LocalLI->start, then advance to the next segment. If a hole in GlobalLI
2388 // exists in LocalLI's vicinity, GlobalSegment will be the end of the hole.
2389 if (GlobalSegment->contains(LocalLI->beginIndex()))
2390 ++GlobalSegment;
2391
2392 if (GlobalSegment == GlobalLI->end())
2393 return;
2394
2395 // Check if GlobalLI contains a hole in the vicinity of LocalLI.
2396 if (GlobalSegment != GlobalLI->begin()) {
2397 // Two address defs have no hole.
2398 if (SlotIndex::isSameInstr(std::prev(GlobalSegment)->end,
2399 GlobalSegment->start)) {
2400 return;
2401 }
2402 // If the prior global segment may be defined by the same two-address
2403 // instruction that also defines LocalLI, then can't make a hole here.
2404 if (SlotIndex::isSameInstr(std::prev(GlobalSegment)->start,
2405 LocalLI->beginIndex())) {
2406 return;
2407 }
2408 // If GlobalLI has a prior segment, it must be live into the EBB. Otherwise
2409 // it would be a disconnected component in the live range.
2410 assert(std::prev(GlobalSegment)->start < LocalLI->beginIndex() &&
2411 "Disconnected LRG within the scheduling region.");
2412 }
2413 MachineInstr *GlobalDef = LIS->getInstructionFromIndex(GlobalSegment->start);
2414 if (!GlobalDef)
2415 return;
2416
2417 SUnit *GlobalSU = DAG->getSUnit(GlobalDef);
2418 if (!GlobalSU)
2419 return;
2420
2421 // GlobalDef is the bottom of the GlobalLI hole. Open the hole by
2422 // constraining the uses of the last local def to precede GlobalDef.
2423 SmallVector<SUnit*,8> LocalUses;
2424 const VNInfo *LastLocalVN = LocalLI->getVNInfoBefore(LocalLI->endIndex());
2425 MachineInstr *LastLocalDef = LIS->getInstructionFromIndex(LastLocalVN->def);
2426 SUnit *LastLocalSU = DAG->getSUnit(LastLocalDef);
2427 for (const SDep &Succ : LastLocalSU->Succs) {
2428 if (Succ.getKind() != SDep::Data || Succ.getReg() != LocalReg)
2429 continue;
2430 if (Succ.getSUnit() == GlobalSU)
2431 continue;
2432 if (!DAG->canAddEdge(GlobalSU, Succ.getSUnit()))
2433 return;
2434 LocalUses.push_back(Succ.getSUnit());
2435 }
2436 // Open the top of the GlobalLI hole by constraining any earlier global uses
2437 // to precede the start of LocalLI.
2438 SmallVector<SUnit*,8> GlobalUses;
2439 MachineInstr *FirstLocalDef =
2440 LIS->getInstructionFromIndex(LocalLI->beginIndex());
2441 SUnit *FirstLocalSU = DAG->getSUnit(FirstLocalDef);
2442 for (const SDep &Pred : GlobalSU->Preds) {
2443 if (Pred.getKind() != SDep::Anti || Pred.getReg() != GlobalReg)
2444 continue;
2445 if (Pred.getSUnit() == FirstLocalSU)
2446 continue;
2447 if (!DAG->canAddEdge(FirstLocalSU, Pred.getSUnit()))
2448 return;
2449 GlobalUses.push_back(Pred.getSUnit());
2450 }
2451 LLVM_DEBUG(dbgs() << "Constraining copy " << *CopySU << "\n");
2452 // Add the weak edges.
2453 for (SUnit *LU : LocalUses) {
2454 LLVM_DEBUG(dbgs() << " Local use SU(" << LU->NodeNum << ") -> SU("
2455 << GlobalSU->NodeNum << ")\n");
2456 DAG->addEdge(GlobalSU, SDep(LU, SDep::Weak));
2457 }
2458 for (SUnit *GU : GlobalUses) {
2459 LLVM_DEBUG(dbgs() << " Global use " << *GU << " -> " << *FirstLocalSU
2460 << "\n");
2461 DAG->addEdge(FirstLocalSU, SDep(GU, SDep::Weak));
2462 }
2463}
2464
2465/// Callback from DAG postProcessing to create weak edges to encourage
2466/// copy elimination.
2467void CopyConstrain::apply(ScheduleDAGInstrs *DAGInstrs) {
2468 ScheduleDAGMI *DAG = static_cast<ScheduleDAGMI*>(DAGInstrs);
2469 assert(DAG->hasVRegLiveness() && "Expect VRegs with LiveIntervals");
2470
2471 MachineBasicBlock::iterator FirstPos = nextIfDebug(DAG->begin(), DAG->end());
2472 if (FirstPos == DAG->end())
2473 return;
2474 RegionBeginIdx = DAG->getLIS()->getInstructionIndex(*FirstPos);
2475 RegionEndIdx = DAG->getLIS()->getInstructionIndex(
2476 *priorNonDebug(DAG->end(), DAG->begin()));
2477
2478 for (SUnit &SU : DAG->SUnits) {
2479 if (!SU.getInstr()->isCopy())
2480 continue;
2481
2482 constrainLocalCopy(&SU, static_cast<ScheduleDAGMILive*>(DAG));
2483 }
2484}
2485
2486//===----------------------------------------------------------------------===//
2487// MachineSchedStrategy helpers used by GenericScheduler, GenericPostScheduler
2488// and possibly other custom schedulers.
2489//===----------------------------------------------------------------------===//
2490
2491static const unsigned InvalidCycle = ~0U;
2492
2494
2495/// Given a Count of resource usage and a Latency value, return true if a
2496/// SchedBoundary becomes resource limited.
2497/// If we are checking after scheduling a node, we should return true when
2498/// we just reach the resource limit.
2499static bool checkResourceLimit(unsigned LFactor, unsigned Count,
2500 unsigned Latency, bool AfterSchedNode) {
2501 int ResCntFactor = (int)(Count - (Latency * LFactor));
2502 if (AfterSchedNode)
2503 return ResCntFactor >= (int)LFactor;
2504 else
2505 return ResCntFactor > (int)LFactor;
2506}
2507
2509 // A new HazardRec is created for each DAG and owned by SchedBoundary.
2510 // Destroying and reconstructing it is very expensive though. So keep
2511 // invalid, placeholder HazardRecs.
2512 if (HazardRec && HazardRec->isEnabled())
2513 HazardRec.reset();
2514 Available.clear();
2515 Pending.clear();
2516 CheckPending = false;
2517 CurrCycle = 0;
2518 CurrMOps = 0;
2519 MinReadyCycle = std::numeric_limits<unsigned>::max();
2520 ExpectedLatency = 0;
2521 DependentLatency = 0;
2522 RetiredMOps = 0;
2523 MaxExecutedResCount = 0;
2524 ZoneCritResIdx = 0;
2525 IsResourceLimited = false;
2526 ReservedCycles.clear();
2527 ReservedResourceSegments.clear();
2528 ReservedCyclesIndex.clear();
2529 ResourceGroupSubUnitMasks.clear();
2530#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2531 // Track the maximum number of stall cycles that could arise either from the
2532 // latency of a DAG edge or the number of cycles that a processor resource is
2533 // reserved (SchedBoundary::ReservedCycles).
2534 MaxObservedStall = 0;
2535#endif
2536 // Reserve a zero-count for invalid CritResIdx.
2537 ExecutedResCounts.resize(1);
2538 assert(!ExecutedResCounts[0] && "nonzero count for bad resource");
2539}
2540
2542init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel) {
2543 reset();
2544 if (!SchedModel->hasInstrSchedModel())
2545 return;
2546 RemainingCounts.resize(SchedModel->getNumProcResourceKinds());
2547 for (SUnit &SU : DAG->SUnits) {
2548 const MCSchedClassDesc *SC = DAG->getSchedClass(&SU);
2549 RemIssueCount += SchedModel->getNumMicroOps(SU.getInstr(), SC)
2550 * SchedModel->getMicroOpFactor();
2552 PI = SchedModel->getWriteProcResBegin(SC),
2553 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
2554 unsigned PIdx = PI->ProcResourceIdx;
2555 unsigned Factor = SchedModel->getResourceFactor(PIdx);
2556 assert(PI->ReleaseAtCycle >= PI->AcquireAtCycle);
2557 RemainingCounts[PIdx] +=
2558 (Factor * (PI->ReleaseAtCycle - PI->AcquireAtCycle));
2559 }
2560 }
2561}
2562
2564init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, SchedRemainder *rem) {
2565 reset();
2566 DAG = dag;
2567 SchedModel = smodel;
2568 Rem = rem;
2569 if (SchedModel->hasInstrSchedModel()) {
2570 unsigned ResourceCount = SchedModel->getNumProcResourceKinds();
2571 ReservedCyclesIndex.resize(ResourceCount);
2572 ExecutedResCounts.resize(ResourceCount);
2573 ResourceGroupSubUnitMasks.resize(ResourceCount, APInt(ResourceCount, 0));
2574 unsigned NumUnits = 0;
2575
2576 for (unsigned i = 0; i < ResourceCount; ++i) {
2577 ReservedCyclesIndex[i] = NumUnits;
2578 NumUnits += SchedModel->getProcResource(i)->NumUnits;
2579 if (isReservedGroup(i)) {
2580 auto SubUnits = SchedModel->getProcResource(i)->SubUnitsIdxBegin;
2581 for (unsigned U = 0, UE = SchedModel->getProcResource(i)->NumUnits;
2582 U != UE; ++U)
2583 ResourceGroupSubUnitMasks[i].setBit(SubUnits[U]);
2584 }
2585 }
2586
2587 ReservedCycles.resize(NumUnits, InvalidCycle);
2588 }
2589}
2590
2591/// Compute the stall cycles based on this SUnit's ready time. Heuristics treat
2592/// these "soft stalls" differently than the hard stall cycles based on CPU
2593/// resources and computed by checkHazard(). A fully in-order model
2594/// (MicroOpBufferSize==0) will not make use of this since instructions are not
2595/// available for scheduling until they are ready. However, a weaker in-order
2596/// model may use this for heuristics. For example, if a processor has in-order
2597/// behavior when reading certain resources, this may come into play.
2599 if (!SU->isUnbuffered)
2600 return 0;
2601
2602 unsigned ReadyCycle = (isTop() ? SU->TopReadyCycle : SU->BotReadyCycle);
2603 if (ReadyCycle > CurrCycle)
2604 return ReadyCycle - CurrCycle;
2605 return 0;
2606}
2607
2608/// Compute the next cycle at which the given processor resource unit
2609/// can be scheduled.
2611 unsigned ReleaseAtCycle,
2612 unsigned AcquireAtCycle) {
2613 if (SchedModel && SchedModel->enableIntervals()) {
2614 if (isTop())
2615 return ReservedResourceSegments[InstanceIdx].getFirstAvailableAtFromTop(
2616 CurrCycle, AcquireAtCycle, ReleaseAtCycle);
2617
2618 return ReservedResourceSegments[InstanceIdx].getFirstAvailableAtFromBottom(
2619 CurrCycle, AcquireAtCycle, ReleaseAtCycle);
2620 }
2621
2622 unsigned NextUnreserved = ReservedCycles[InstanceIdx];
2623 // If this resource has never been used, always return cycle zero.
2624 if (NextUnreserved == InvalidCycle)
2625 return CurrCycle;
2626 // For bottom-up scheduling add the cycles needed for the current operation.
2627 if (!isTop())
2628 NextUnreserved = std::max(CurrCycle, NextUnreserved + ReleaseAtCycle);
2629 return NextUnreserved;
2630}
2631
2632/// Compute the next cycle at which the given processor resource can be
2633/// scheduled. Returns the next cycle and the index of the processor resource
2634/// instance in the reserved cycles vector.
2635std::pair<unsigned, unsigned>
2637 unsigned ReleaseAtCycle,
2638 unsigned AcquireAtCycle) {
2640 LLVM_DEBUG(dbgs() << " Resource booking (@" << CurrCycle << "c): \n");
2642 LLVM_DEBUG(dbgs() << " getNextResourceCycle (@" << CurrCycle << "c): \n");
2643 }
2644 unsigned MinNextUnreserved = InvalidCycle;
2645 unsigned InstanceIdx = 0;
2646 unsigned StartIndex = ReservedCyclesIndex[PIdx];
2647 unsigned NumberOfInstances = SchedModel->getProcResource(PIdx)->NumUnits;
2648 assert(NumberOfInstances > 0 &&
2649 "Cannot have zero instances of a ProcResource");
2650
2651 if (isReservedGroup(PIdx)) {
2652 // If any subunits are used by the instruction, report that the
2653 // subunits of the resource group are available at the first cycle
2654 // in which the unit is available, effectively removing the group
2655 // record from hazarding and basing the hazarding decisions on the
2656 // subunit records. Otherwise, choose the first available instance
2657 // from among the subunits. Specifications which assign cycles to
2658 // both the subunits and the group or which use an unbuffered
2659 // group with buffered subunits will appear to schedule
2660 // strangely. In the first case, the additional cycles for the
2661 // group will be ignored. In the second, the group will be
2662 // ignored entirely.
2663 for (const MCWriteProcResEntry &PE :
2664 make_range(SchedModel->getWriteProcResBegin(SC),
2665 SchedModel->getWriteProcResEnd(SC)))
2666 if (ResourceGroupSubUnitMasks[PIdx][PE.ProcResourceIdx])
2667 return std::make_pair(getNextResourceCycleByInstance(
2668 StartIndex, ReleaseAtCycle, AcquireAtCycle),
2669 StartIndex);
2670
2671 auto SubUnits = SchedModel->getProcResource(PIdx)->SubUnitsIdxBegin;
2672 for (unsigned I = 0, End = NumberOfInstances; I < End; ++I) {
2673 unsigned NextUnreserved, NextInstanceIdx;
2674 std::tie(NextUnreserved, NextInstanceIdx) =
2675 getNextResourceCycle(SC, SubUnits[I], ReleaseAtCycle, AcquireAtCycle);
2676 if (MinNextUnreserved > NextUnreserved) {
2677 InstanceIdx = NextInstanceIdx;
2678 MinNextUnreserved = NextUnreserved;
2679 }
2680 }
2681 return std::make_pair(MinNextUnreserved, InstanceIdx);
2682 }
2683
2684 for (unsigned I = StartIndex, End = StartIndex + NumberOfInstances; I < End;
2685 ++I) {
2686 unsigned NextUnreserved =
2687 getNextResourceCycleByInstance(I, ReleaseAtCycle, AcquireAtCycle);
2689 LLVM_DEBUG(dbgs() << " Instance " << I - StartIndex << " available @"
2690 << NextUnreserved << "c\n");
2691 if (MinNextUnreserved > NextUnreserved) {
2692 InstanceIdx = I;
2693 MinNextUnreserved = NextUnreserved;
2694 }
2695 }
2697 LLVM_DEBUG(dbgs() << " selecting " << SchedModel->getResourceName(PIdx)
2698 << "[" << InstanceIdx - StartIndex << "]"
2699 << " available @" << MinNextUnreserved << "c"
2700 << "\n");
2701 return std::make_pair(MinNextUnreserved, InstanceIdx);
2702}
2703
2704/// Does this SU have a hazard within the current instruction group.
2705///
2706/// The scheduler supports two modes of hazard recognition. The first is the
2707/// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that
2708/// supports highly complicated in-order reservation tables
2709/// (ScoreboardHazardRecognizer) and arbitrary target-specific logic.
2710///
2711/// The second is a streamlined mechanism that checks for hazards based on
2712/// simple counters that the scheduler itself maintains. It explicitly checks
2713/// for instruction dispatch limitations, including the number of micro-ops that
2714/// can dispatch per cycle.
2715///
2716/// TODO: Also check whether the SU must start a new group.
2718 if (HazardRec->isEnabled()
2719 && HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard) {
2721 << "hazard: " << *SU << " reported by HazardRec\n");
2722 return true;
2723 }
2724
2725 unsigned uops = SchedModel->getNumMicroOps(SU->getInstr());
2726 if ((CurrMOps > 0) && (CurrMOps + uops > SchedModel->getIssueWidth())) {
2727 LLVM_DEBUG(dbgs().indent(2) << "hazard: " << *SU << " uops=" << uops
2728 << ", CurrMOps = " << CurrMOps << ", "
2729 << "CurrMOps + uops > issue width of "
2730 << SchedModel->getIssueWidth() << "\n");
2731 return true;
2732 }
2733
2734 if (CurrMOps > 0 &&
2735 ((isTop() && SchedModel->mustBeginGroup(SU->getInstr())) ||
2736 (!isTop() && SchedModel->mustEndGroup(SU->getInstr())))) {
2737 LLVM_DEBUG(dbgs().indent(2) << "hazard: " << *SU << " must "
2738 << (isTop() ? "begin" : "end") << " group\n");
2739 return true;
2740 }
2741
2742 if (SchedModel->hasInstrSchedModel() && SU->hasReservedResource) {
2743 const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
2744 for (const MCWriteProcResEntry &PE :
2745 make_range(SchedModel->getWriteProcResBegin(SC),
2746 SchedModel->getWriteProcResEnd(SC))) {
2747 unsigned ResIdx = PE.ProcResourceIdx;
2748 unsigned ReleaseAtCycle = PE.ReleaseAtCycle;
2749 unsigned AcquireAtCycle = PE.AcquireAtCycle;
2750 unsigned NRCycle, InstanceIdx;
2751 std::tie(NRCycle, InstanceIdx) =
2752 getNextResourceCycle(SC, ResIdx, ReleaseAtCycle, AcquireAtCycle);
2753 if (NRCycle > CurrCycle) {
2754#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2755 MaxObservedStall = std::max(ReleaseAtCycle, MaxObservedStall);
2756#endif
2758 << "hazard: " << *SU << " "
2759 << SchedModel->getResourceName(ResIdx) << '['
2760 << InstanceIdx - ReservedCyclesIndex[ResIdx] << ']' << "="
2761 << NRCycle << "c, is later than "
2762 << "CurrCycle = " << CurrCycle << "c\n");
2763 return true;
2764 }
2765 }
2766 }
2767 return false;
2768}
2769
2770// Find the unscheduled node in ReadySUs with the highest latency.
2773 SUnit *LateSU = nullptr;
2774 unsigned RemLatency = 0;
2775 for (SUnit *SU : ReadySUs) {
2776 unsigned L = getUnscheduledLatency(SU);
2777 if (L > RemLatency) {
2778 RemLatency = L;
2779 LateSU = SU;
2780 }
2781 }
2782 if (LateSU) {
2783 LLVM_DEBUG(dbgs() << Available.getName() << " RemLatency " << *LateSU << " "
2784 << RemLatency << "c\n");
2785 }
2786 return RemLatency;
2787}
2788
2789// Count resources in this zone and the remaining unscheduled
2790// instruction. Return the max count, scaled. Set OtherCritIdx to the critical
2791// resource index, or zero if the zone is issue limited.
2793getOtherResourceCount(unsigned &OtherCritIdx) {
2794 OtherCritIdx = 0;
2795 if (!SchedModel->hasInstrSchedModel())
2796 return 0;
2797
2798 unsigned OtherCritCount = Rem->RemIssueCount
2799 + (RetiredMOps * SchedModel->getMicroOpFactor());
2800 LLVM_DEBUG(dbgs() << " " << Available.getName() << " + Remain MOps: "
2801 << OtherCritCount / SchedModel->getMicroOpFactor() << '\n');
2802 for (unsigned PIdx = 1, PEnd = SchedModel->getNumProcResourceKinds();
2803 PIdx != PEnd; ++PIdx) {
2804 unsigned OtherCount = getResourceCount(PIdx) + Rem->RemainingCounts[PIdx];
2805 if (OtherCount > OtherCritCount) {
2806 OtherCritCount = OtherCount;
2807 OtherCritIdx = PIdx;
2808 }
2809 }
2810 if (OtherCritIdx) {
2811 LLVM_DEBUG(
2812 dbgs() << " " << Available.getName() << " + Remain CritRes: "
2813 << OtherCritCount / SchedModel->getResourceFactor(OtherCritIdx)
2814 << " " << SchedModel->getResourceName(OtherCritIdx) << "\n");
2815 }
2816 return OtherCritCount;
2817}
2818
2819void SchedBoundary::releaseNode(SUnit *SU, unsigned ReadyCycle, bool InPQueue,
2820 unsigned Idx) {
2821 assert(SU->getInstr() && "Scheduled SUnit must have instr");
2822
2823#if LLVM_ENABLE_ABI_BREAKING_CHECKS
2824 // ReadyCycle was been bumped up to the CurrCycle when this node was
2825 // scheduled, but CurrCycle may have been eagerly advanced immediately after
2826 // scheduling, so may now be greater than ReadyCycle.
2827 if (ReadyCycle > CurrCycle)
2828 MaxObservedStall = std::max(ReadyCycle - CurrCycle, MaxObservedStall);
2829#endif
2830
2831 if (ReadyCycle < MinReadyCycle)
2832 MinReadyCycle = ReadyCycle;
2833
2834 // Check for interlocks first. For the purpose of other heuristics, an
2835 // instruction that cannot issue appears as if it's not in the ReadyQueue.
2836 bool IsBuffered = SchedModel->getMicroOpBufferSize() != 0;
2837 bool HazardDetected = !IsBuffered && ReadyCycle > CurrCycle;
2838 if (HazardDetected)
2840 << "hazard: " << *SU << " ReadyCycle = " << ReadyCycle
2841 << " is later than CurrCycle = " << CurrCycle
2842 << " on an unbuffered resource" << "\n");
2843 else
2844 HazardDetected = checkHazard(SU);
2845
2846 if (!HazardDetected && Available.size() >= ReadyListLimit) {
2847 HazardDetected = true;
2848 LLVM_DEBUG(dbgs().indent(2) << "hazard: Available Q is full (size: "
2849 << Available.size() << ")\n");
2850 }
2851
2852 if (!HazardDetected) {
2853 Available.push(SU);
2854 LLVM_DEBUG(dbgs().indent(2) << "Move " << *SU << " into Available Q\n");
2855
2856 if (InPQueue)
2857 Pending.remove(Pending.begin() + Idx);
2858 return;
2859 }
2860
2861 if (!InPQueue)
2862 Pending.push(SU);
2863}
2864
2865/// Move the boundary of scheduled code by one cycle.
2866void SchedBoundary::bumpCycle(unsigned NextCycle) {
2867 if (SchedModel->getMicroOpBufferSize() == 0) {
2868 assert(MinReadyCycle < std::numeric_limits<unsigned>::max() &&
2869 "MinReadyCycle uninitialized");
2870 if (MinReadyCycle > NextCycle)
2871 NextCycle = MinReadyCycle;
2872 }
2873 // Update the current micro-ops, which will issue in the next cycle.
2874 unsigned DecMOps = SchedModel->getIssueWidth() * (NextCycle - CurrCycle);
2875 CurrMOps = (CurrMOps <= DecMOps) ? 0 : CurrMOps - DecMOps;
2876
2877 // Decrement DependentLatency based on the next cycle.
2878 if ((NextCycle - CurrCycle) > DependentLatency)
2879 DependentLatency = 0;
2880 else
2881 DependentLatency -= (NextCycle - CurrCycle);
2882
2883 if (!HazardRec->isEnabled()) {
2884 // Bypass HazardRec virtual calls.
2885 CurrCycle = NextCycle;
2886 } else {
2887 // Bypass getHazardType calls in case of long latency.
2888 for (; CurrCycle != NextCycle; ++CurrCycle) {
2889 if (isTop())
2890 HazardRec->AdvanceCycle();
2891 else
2892 HazardRec->RecedeCycle();
2893 }
2894 }
2895 CheckPending = true;
2896 IsResourceLimited =
2897 checkResourceLimit(SchedModel->getLatencyFactor(), getCriticalCount(),
2898 getScheduledLatency(), true);
2899
2900 LLVM_DEBUG(dbgs() << "Cycle: " << CurrCycle << ' ' << Available.getName()
2901 << '\n');
2902}
2903
2904void SchedBoundary::incExecutedResources(unsigned PIdx, unsigned Count) {
2905 ExecutedResCounts[PIdx] += Count;
2906 if (ExecutedResCounts[PIdx] > MaxExecutedResCount)
2907 MaxExecutedResCount = ExecutedResCounts[PIdx];
2908}
2909
2910/// Add the given processor resource to this scheduled zone.
2911///
2912/// \param ReleaseAtCycle indicates the number of consecutive (non-pipelined)
2913/// cycles during which this resource is released.
2914///
2915/// \param AcquireAtCycle indicates the number of consecutive (non-pipelined)
2916/// cycles at which the resource is aquired after issue (assuming no stalls).
2917///
2918/// \return the next cycle at which the instruction may execute without
2919/// oversubscribing resources.
2920unsigned SchedBoundary::countResource(const MCSchedClassDesc *SC, unsigned PIdx,
2921 unsigned ReleaseAtCycle,
2922 unsigned NextCycle,
2923 unsigned AcquireAtCycle) {
2924 unsigned Factor = SchedModel->getResourceFactor(PIdx);
2925 unsigned Count = Factor * (ReleaseAtCycle- AcquireAtCycle);
2926 LLVM_DEBUG(dbgs() << " " << SchedModel->getResourceName(PIdx) << " +"
2927 << ReleaseAtCycle << "x" << Factor << "u\n");
2928
2929 // Update Executed resources counts.
2931 assert(Rem->RemainingCounts[PIdx] >= Count && "resource double counted");
2932 Rem->RemainingCounts[PIdx] -= Count;
2933
2934 // Check if this resource exceeds the current critical resource. If so, it
2935 // becomes the critical resource.
2936 if (ZoneCritResIdx != PIdx && (getResourceCount(PIdx) > getCriticalCount())) {
2937 ZoneCritResIdx = PIdx;
2938 LLVM_DEBUG(dbgs() << " *** Critical resource "
2939 << SchedModel->getResourceName(PIdx) << ": "
2940 << getResourceCount(PIdx) / SchedModel->getLatencyFactor()
2941 << "c\n");
2942 }
2943 // For reserved resources, record the highest cycle using the resource.
2944 unsigned NextAvailable, InstanceIdx;
2945 std::tie(NextAvailable, InstanceIdx) =
2946 getNextResourceCycle(SC, PIdx, ReleaseAtCycle, AcquireAtCycle);
2947 if (NextAvailable > CurrCycle) {
2948 LLVM_DEBUG(dbgs() << " Resource conflict: "
2949 << SchedModel->getResourceName(PIdx)
2950 << '[' << InstanceIdx - ReservedCyclesIndex[PIdx] << ']'
2951 << " reserved until @" << NextAvailable << "\n");
2952 }
2953 return NextAvailable;
2954}
2955
2956/// Move the boundary of scheduled code by one SUnit.
2958 // checkHazard should prevent scheduling multiple instructions per cycle that
2959 // exceed the issue width.
2960 const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
2961 unsigned IncMOps = SchedModel->getNumMicroOps(SU->getInstr());
2962 assert(
2963 (CurrMOps == 0 || (CurrMOps + IncMOps) <= SchedModel->getIssueWidth()) &&
2964 "Cannot schedule this instruction's MicroOps in the current cycle.");
2965
2966 unsigned ReadyCycle = (isTop() ? SU->TopReadyCycle : SU->BotReadyCycle);
2967 LLVM_DEBUG(dbgs() << " Ready @" << ReadyCycle << "c\n");
2968
2969 unsigned NextCycle = CurrCycle;
2970 switch (SchedModel->getMicroOpBufferSize()) {
2971 case 0:
2972 assert(ReadyCycle <= CurrCycle && "Broken PendingQueue");
2973 break;
2974 case 1:
2975 if (ReadyCycle > NextCycle) {
2976 NextCycle = ReadyCycle;
2977 LLVM_DEBUG(dbgs() << " *** Stall until: " << ReadyCycle << "\n");
2978 }
2979 break;
2980 default:
2981 // We don't currently model the OOO reorder buffer, so consider all
2982 // scheduled MOps to be "retired". We do loosely model in-order resource
2983 // latency. If this instruction uses an in-order resource, account for any
2984 // likely stall cycles.
2985 if (SU->isUnbuffered && ReadyCycle > NextCycle)
2986 NextCycle = ReadyCycle;
2987 break;
2988 }
2989 RetiredMOps += IncMOps;
2990
2991 // Update resource counts and critical resource.
2992 if (SchedModel->hasInstrSchedModel()) {
2993 unsigned DecRemIssue = IncMOps * SchedModel->getMicroOpFactor();
2994 assert(Rem->RemIssueCount >= DecRemIssue && "MOps double counted");
2995 Rem->RemIssueCount -= DecRemIssue;
2996 if (ZoneCritResIdx) {
2997 // Scale scheduled micro-ops for comparing with the critical resource.
2998 unsigned ScaledMOps =
2999 RetiredMOps * SchedModel->getMicroOpFactor();
3000
3001 // If scaled micro-ops are now more than the previous critical resource by
3002 // a full cycle, then micro-ops issue becomes critical.
3003 if ((int)(ScaledMOps - getResourceCount(ZoneCritResIdx))
3004 >= (int)SchedModel->getLatencyFactor()) {
3005 ZoneCritResIdx = 0;
3006 LLVM_DEBUG(dbgs() << " *** Critical resource NumMicroOps: "
3007 << ScaledMOps / SchedModel->getLatencyFactor()
3008 << "c\n");
3009 }
3010 }
3012 PI = SchedModel->getWriteProcResBegin(SC),
3013 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
3014 unsigned RCycle =
3015 countResource(SC, PI->ProcResourceIdx, PI->ReleaseAtCycle, NextCycle,
3016 PI->AcquireAtCycle);
3017 if (RCycle > NextCycle)
3018 NextCycle = RCycle;
3019 }
3020 if (SU->hasReservedResource) {
3021 // For reserved resources, record the highest cycle using the resource.
3022 // For top-down scheduling, this is the cycle in which we schedule this
3023 // instruction plus the number of cycles the operations reserves the
3024 // resource. For bottom-up is it simply the instruction's cycle.
3026 PI = SchedModel->getWriteProcResBegin(SC),
3027 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
3028 unsigned PIdx = PI->ProcResourceIdx;
3029 if (SchedModel->getResourceBufferSize(PIdx) == 0) {
3030
3031 if (SchedModel && SchedModel->enableIntervals()) {
3032 unsigned ReservedUntil, InstanceIdx;
3033 std::tie(ReservedUntil, InstanceIdx) = getNextResourceCycle(
3034 SC, PIdx, PI->ReleaseAtCycle, PI->AcquireAtCycle);
3035 if (isTop()) {
3036 ReservedResourceSegments[InstanceIdx].add(
3038 NextCycle, PI->AcquireAtCycle, PI->ReleaseAtCycle),
3040 } else {
3041 ReservedResourceSegments[InstanceIdx].add(
3043 NextCycle, PI->AcquireAtCycle, PI->ReleaseAtCycle),
3045 }
3046 } else {
3047
3048 unsigned ReservedUntil, InstanceIdx;
3049 std::tie(ReservedUntil, InstanceIdx) = getNextResourceCycle(
3050 SC, PIdx, PI->ReleaseAtCycle, PI->AcquireAtCycle);
3051 if (isTop()) {
3052 ReservedCycles[InstanceIdx] =
3053 std::max(ReservedUntil, NextCycle + PI->ReleaseAtCycle);
3054 } else
3055 ReservedCycles[InstanceIdx] = NextCycle;
3056 }
3057 }
3058 }
3059 }
3060 }
3061 // Update ExpectedLatency and DependentLatency.
3062 unsigned &TopLatency = isTop() ? ExpectedLatency : DependentLatency;
3063 unsigned &BotLatency = isTop() ? DependentLatency : ExpectedLatency;
3064 if (SU->getDepth() > TopLatency) {
3065 TopLatency = SU->getDepth();
3066 LLVM_DEBUG(dbgs() << " " << Available.getName() << " TopLatency " << *SU
3067 << " " << TopLatency << "c\n");
3068 }
3069 if (SU->getHeight() > BotLatency) {
3070 BotLatency = SU->getHeight();
3071 LLVM_DEBUG(dbgs() << " " << Available.getName() << " BotLatency " << *SU
3072 << " " << BotLatency << "c\n");
3073 }
3074 // If we stall for any reason, bump the cycle.
3075 if (NextCycle > CurrCycle)
3076 bumpCycle(NextCycle);
3077 else
3078 // After updating ZoneCritResIdx and ExpectedLatency, check if we're
3079 // resource limited. If a stall occurred, bumpCycle does this.
3080 IsResourceLimited =
3081 checkResourceLimit(SchedModel->getLatencyFactor(), getCriticalCount(),
3082 getScheduledLatency(), true);
3083
3084 // Update the reservation table.
3085 if (HazardRec->isEnabled()) {
3086 if (!isTop() && SU->isCall) {
3087 // Calls are scheduled with their preceding instructions. For bottom-up
3088 // scheduling, clear the pipeline state before emitting.
3089 HazardRec->Reset();
3090 }
3091 HazardRec->EmitInstruction(SU);
3092 // Scheduling an instruction may have made pending instructions available.
3093 CheckPending = true;
3094 }
3095
3096 // Update CurrMOps after calling bumpCycle to handle stalls, since bumpCycle
3097 // resets CurrMOps. Loop to handle instructions with more MOps than issue in
3098 // one cycle. Since we commonly reach the max MOps here, opportunistically
3099 // bump the cycle to avoid uselessly checking everything in the readyQ.
3100 CurrMOps += IncMOps;
3101
3102 // Bump the cycle count for issue group constraints.
3103 // This must be done after NextCycle has been adjust for all other stalls.
3104 // Calling bumpCycle(X) will reduce CurrMOps by one issue group and set
3105 // currCycle to X.
3106 if ((isTop() && SchedModel->mustEndGroup(SU->getInstr())) ||
3107 (!isTop() && SchedModel->mustBeginGroup(SU->getInstr()))) {
3108 LLVM_DEBUG(dbgs() << " Bump cycle to " << (isTop() ? "end" : "begin")
3109 << " group\n");
3110 bumpCycle(++NextCycle);
3111 }
3112
3113 while (CurrMOps >= SchedModel->getIssueWidth()) {
3114 LLVM_DEBUG(dbgs() << " *** Max MOps " << CurrMOps << " at cycle "
3115 << CurrCycle << '\n');
3116 bumpCycle(++NextCycle);
3117 }
3119}
3120
3121/// Release pending ready nodes in to the available queue. This makes them
3122/// visible to heuristics.
3124 // If the available queue is empty, it is safe to reset MinReadyCycle.
3125 if (Available.empty())
3126 MinReadyCycle = std::numeric_limits<unsigned>::max();
3127
3128 // Check to see if any of the pending instructions are ready to issue. If
3129 // so, add them to the available queue.
3130 for (unsigned I = 0, E = Pending.size(); I < E; ++I) {
3131 SUnit *SU = *(Pending.begin() + I);
3132 unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle;
3133
3134 LLVM_DEBUG(dbgs() << "Checking pending node " << *SU << "\n");
3135
3136 if (ReadyCycle < MinReadyCycle)
3137 MinReadyCycle = ReadyCycle;
3138
3139 if (Available.size() >= ReadyListLimit)
3140 break;
3141
3142 releaseNode(SU, ReadyCycle, true, I);
3143 if (E != Pending.size()) {
3144 --I;
3145 --E;
3146 }
3147 }
3148 CheckPending = false;
3149}
3150
3151/// Remove SU from the ready set for this boundary.
3153 if (Available.isInQueue(SU))
3154 Available.remove(Available.find(SU));
3155 else {
3156 assert(Pending.isInQueue(SU) && "bad ready count");
3157 Pending.remove(Pending.find(SU));
3158 }
3159}
3160
3161/// If this queue only has one ready candidate, return it. As a side effect,
3162/// defer any nodes that now hit a hazard, and advance the cycle until at least
3163/// one node is ready. If multiple instructions are ready, return NULL.
3165 if (CheckPending)
3167
3168 // Defer any ready instrs that now have a hazard.
3169 for (ReadyQueue::iterator I = Available.begin(); I != Available.end();) {
3170 if (checkHazard(*I)) {
3171 Pending.push(*I);
3172 I = Available.remove(I);
3173 continue;
3174 }
3175 ++I;
3176 }
3177 for (unsigned i = 0; Available.empty(); ++i) {
3178// FIXME: Re-enable assert once PR20057 is resolved.
3179// assert(i <= (HazardRec->getMaxLookAhead() + MaxObservedStall) &&
3180// "permanent hazard");
3181 (void)i;
3182 bumpCycle(CurrCycle + 1);
3184 }
3185
3186 LLVM_DEBUG(Pending.dump());
3187 LLVM_DEBUG(Available.dump());
3188
3189 if (Available.size() == 1)
3190 return *Available.begin();
3191 return nullptr;
3192}
3193
3194#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3195
3196/// Dump the content of the \ref ReservedCycles vector for the
3197/// resources that are used in the basic block.
3198///
3200 if (!SchedModel->hasInstrSchedModel())
3201 return;
3202
3203 unsigned ResourceCount = SchedModel->getNumProcResourceKinds();
3204 unsigned StartIdx = 0;
3205
3206 for (unsigned ResIdx = 0; ResIdx < ResourceCount; ++ResIdx) {
3207 const unsigned NumUnits = SchedModel->getProcResource(ResIdx)->NumUnits;
3208 std::string ResName = SchedModel->getResourceName(ResIdx);
3209 for (unsigned UnitIdx = 0; UnitIdx < NumUnits; ++UnitIdx) {
3210 dbgs() << ResName << "(" << UnitIdx << ") = ";
3211 if (SchedModel && SchedModel->enableIntervals()) {
3212 if (ReservedResourceSegments.count(StartIdx + UnitIdx))
3213 dbgs() << ReservedResourceSegments.at(StartIdx + UnitIdx);
3214 else
3215 dbgs() << "{ }\n";
3216 } else
3217 dbgs() << ReservedCycles[StartIdx + UnitIdx] << "\n";
3218 }
3219 StartIdx += NumUnits;
3220 }
3221}
3222
3223// This is useful information to dump after bumpNode.
3224// Note that the Queue contents are more useful before pickNodeFromQueue.
3226 unsigned ResFactor;
3227 unsigned ResCount;
3228 if (ZoneCritResIdx) {
3229 ResFactor = SchedModel->getResourceFactor(ZoneCritResIdx);
3230 ResCount = getResourceCount(ZoneCritResIdx);
3231 } else {
3232 ResFactor = SchedModel->getMicroOpFactor();
3233 ResCount = RetiredMOps * ResFactor;
3234 }
3235 unsigned LFactor = SchedModel->getLatencyFactor();
3236 dbgs() << Available.getName() << " @" << CurrCycle << "c\n"
3237 << " Retired: " << RetiredMOps;
3238 dbgs() << "\n Executed: " << getExecutedCount() / LFactor << "c";
3239 dbgs() << "\n Critical: " << ResCount / LFactor << "c, "
3240 << ResCount / ResFactor << " "
3241 << SchedModel->getResourceName(ZoneCritResIdx)
3242 << "\n ExpectedLatency: " << ExpectedLatency << "c\n"
3243 << (IsResourceLimited ? " - Resource" : " - Latency")
3244 << " limited.\n";
3247}
3248#endif
3249
3250//===----------------------------------------------------------------------===//
3251// GenericScheduler - Generic implementation of MachineSchedStrategy.
3252//===----------------------------------------------------------------------===//
3253
3257 if (!Policy.ReduceResIdx && !Policy.DemandResIdx)
3258 return;
3259
3260 const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
3262 PI = SchedModel->getWriteProcResBegin(SC),
3263 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
3264 if (PI->ProcResourceIdx == Policy.ReduceResIdx)
3265 ResDelta.CritResources += PI->ReleaseAtCycle;
3266 if (PI->ProcResourceIdx == Policy.DemandResIdx)
3267 ResDelta.DemandedResources += PI->ReleaseAtCycle;
3268 }
3269}
3270
3271/// Returns true if the current cycle plus remaning latency is greater than
3272/// the critical path in the scheduling region.
3273bool GenericSchedulerBase::shouldReduceLatency(const CandPolicy &Policy,
3274 SchedBoundary &CurrZone,
3275 bool ComputeRemLatency,
3276 unsigned &RemLatency) const {
3277 // The current cycle is already greater than the critical path, so we are
3278 // already latency limited and don't need to compute the remaining latency.
3279 if (CurrZone.getCurrCycle() > Rem.CriticalPath)
3280 return true;
3281
3282 // If we haven't scheduled anything yet, then we aren't latency limited.
3283 if (CurrZone.getCurrCycle() == 0)
3284 return false;
3285
3286 if (ComputeRemLatency)
3287 RemLatency = computeRemLatency(CurrZone);
3288
3289 return RemLatency + CurrZone.getCurrCycle() > Rem.CriticalPath;
3290}
3291
3292/// Set the CandPolicy given a scheduling zone given the current resources and
3293/// latencies inside and outside the zone.
3295 SchedBoundary &CurrZone,
3296 SchedBoundary *OtherZone) {
3297 // Apply preemptive heuristics based on the total latency and resources
3298 // inside and outside this zone. Potential stalls should be considered before
3299 // following this policy.
3300
3301 // Compute the critical resource outside the zone.
3302 unsigned OtherCritIdx = 0;
3303 unsigned OtherCount =
3304 OtherZone ? OtherZone->getOtherResourceCount(OtherCritIdx) : 0;
3305
3306 bool OtherResLimited = false;
3307 unsigned RemLatency = 0;
3308 bool RemLatencyComputed = false;
3309 if (SchedModel->hasInstrSchedModel() && OtherCount != 0) {
3310 RemLatency = computeRemLatency(CurrZone);
3311 RemLatencyComputed = true;
3312 OtherResLimited = checkResourceLimit(SchedModel->getLatencyFactor(),
3313 OtherCount, RemLatency, false);
3314 }
3315
3316 // Schedule aggressively for latency in PostRA mode. We don't check for
3317 // acyclic latency during PostRA, and highly out-of-order processors will
3318 // skip PostRA scheduling.
3319 if (!OtherResLimited &&
3320 (IsPostRA || shouldReduceLatency(Policy, CurrZone, !RemLatencyComputed,
3321 RemLatency))) {
3322 Policy.ReduceLatency |= true;
3323 LLVM_DEBUG(dbgs() << " " << CurrZone.Available.getName()
3324 << " RemainingLatency " << RemLatency << " + "
3325 << CurrZone.getCurrCycle() << "c > CritPath "
3326 << Rem.CriticalPath << "\n");
3327 }
3328 // If the same resource is limiting inside and outside the zone, do nothing.
3329 if (CurrZone.getZoneCritResIdx() == OtherCritIdx)
3330 return;
3331
3332 LLVM_DEBUG(if (CurrZone.isResourceLimited()) {
3333 dbgs() << " " << CurrZone.Available.getName() << " ResourceLimited: "
3334 << SchedModel->getResourceName(CurrZone.getZoneCritResIdx()) << "\n";
3335 } if (OtherResLimited) dbgs()
3336 << " RemainingLimit: "
3337 << SchedModel->getResourceName(OtherCritIdx) << "\n";
3338 if (!CurrZone.isResourceLimited() && !OtherResLimited) dbgs()
3339 << " Latency limited both directions.\n");
3340
3341 if (CurrZone.isResourceLimited() && !Policy.ReduceResIdx)
3342 Policy.ReduceResIdx = CurrZone.getZoneCritResIdx();
3343
3344 if (OtherResLimited)
3345 Policy.DemandResIdx = OtherCritIdx;
3346}
3347
3348#ifndef NDEBUG
3351 // clang-format off
3352 switch (Reason) {
3353 case NoCand: return "NOCAND ";
3354 case Only1: return "ONLY1 ";
3355 case PhysReg: return "PHYS-REG ";
3356 case RegExcess: return "REG-EXCESS";
3357 case RegCritical: return "REG-CRIT ";
3358 case Stall: return "STALL ";
3359 case Cluster: return "CLUSTER ";
3360 case Weak: return "WEAK ";
3361 case RegMax: return "REG-MAX ";
3362 case ResourceReduce: return "RES-REDUCE";
3363 case ResourceDemand: return "RES-DEMAND";
3364 case TopDepthReduce: return "TOP-DEPTH ";
3365 case TopPathReduce: return "TOP-PATH ";
3366 case BotHeightReduce:return "BOT-HEIGHT";
3367 case BotPathReduce: return "BOT-PATH ";
3368 case NodeOrder: return "ORDER ";
3369 case FirstValid: return "FIRST ";
3370 };
3371 // clang-format on
3372 llvm_unreachable("Unknown reason!");
3373}
3374
3377 unsigned ResIdx = 0;
3378 unsigned Latency = 0;
3379 switch (Cand.Reason) {
3380 default:
3381 break;
3382 case RegExcess:
3383 P = Cand.RPDelta.Excess;
3384 break;
3385 case RegCritical:
3386 P = Cand.RPDelta.CriticalMax;
3387 break;
3388 case RegMax:
3389 P = Cand.RPDelta.CurrentMax;
3390 break;
3391 case ResourceReduce:
3392 ResIdx = Cand.Policy.ReduceResIdx;
3393 break;
3394 case ResourceDemand:
3395 ResIdx = Cand.Policy.DemandResIdx;
3396 break;
3397 case TopDepthReduce:
3398 Latency = Cand.SU->getDepth();
3399 break;
3400 case TopPathReduce:
3401 Latency = Cand.SU->getHeight();
3402 break;
3403 case BotHeightReduce:
3404 Latency = Cand.SU->getHeight();
3405 break;
3406 case BotPathReduce:
3407 Latency = Cand.SU->getDepth();
3408 break;
3409 }
3410 dbgs() << " Cand " << *Cand.SU << " " << getReasonStr(Cand.Reason);
3411 if (P.isValid())
3412 dbgs() << " " << TRI->getRegPressureSetName(P.getPSet())
3413 << ":" << P.getUnitInc() << " ";
3414 else
3415 dbgs() << " ";
3416 if (ResIdx)
3417 dbgs() << " " << SchedModel->getProcResource(ResIdx)->Name << " ";
3418 else
3419 dbgs() << " ";
3420 if (Latency)
3421 dbgs() << " " << Latency << " cycles ";
3422 else
3423 dbgs() << " ";
3424 dbgs() << '\n';
3425}
3426#endif
3427
3428/// Compute remaining latency. We need this both to determine whether the
3429/// overall schedule has become latency-limited and whether the instructions
3430/// outside this zone are resource or latency limited.
3431///
3432/// The "dependent" latency is updated incrementally during scheduling as the
3433/// max height/depth of scheduled nodes minus the cycles since it was
3434/// scheduled:
3435/// DLat = max (N.depth - (CurrCycle - N.ReadyCycle) for N in Zone
3436///
3437/// The "independent" latency is the max ready queue depth:
3438/// ILat = max N.depth for N in Available|Pending
3439///
3440/// RemainingLatency is the greater of independent and dependent latency.
3441///
3442/// These computations are expensive, especially in DAGs with many edges, so
3443/// only do them if necessary.
3445 unsigned RemLatency = CurrZone.getDependentLatency();
3446 RemLatency = std::max(RemLatency,
3447 CurrZone.findMaxLatency(CurrZone.Available.elements()));
3448 RemLatency = std::max(RemLatency,
3449 CurrZone.findMaxLatency(CurrZone.Pending.elements()));
3450 return RemLatency;
3451}
3452
3453/// Return true if this heuristic determines order.
3454/// TODO: Consider refactor return type of these functions as integer or enum,
3455/// as we may need to differentiate whether TryCand is better than Cand.
3456bool llvm::tryLess(int TryVal, int CandVal,
3460 if (TryVal < CandVal) {
3461 TryCand.Reason = Reason;
3462 return true;
3463 }
3464 if (TryVal > CandVal) {
3465 if (Cand.Reason > Reason)
3466 Cand.Reason = Reason;
3467 return true;
3468 }
3469 return false;
3470}
3471
3472bool llvm::tryGreater(int TryVal, int CandVal,
3476 if (TryVal > CandVal) {
3477 TryCand.Reason = Reason;
3478 return true;
3479 }
3480 if (TryVal < CandVal) {
3481 if (Cand.Reason > Reason)
3482 Cand.Reason = Reason;
3483 return true;
3484 }
3485 return false;
3486}
3487
3490 SchedBoundary &Zone) {
3491 if (Zone.isTop()) {
3492 // Prefer the candidate with the lesser depth, but only if one of them has
3493 // depth greater than the total latency scheduled so far, otherwise either
3494 // of them could be scheduled now with no stall.
3495 if (std::max(TryCand.SU->getDepth(), Cand.SU->getDepth()) >
3496 Zone.getScheduledLatency()) {
3497 if (tryLess(TryCand.SU->getDepth(), Cand.SU->getDepth(),
3499 return true;
3500 }
3501 if (tryGreater(TryCand.SU->getHeight(), Cand.SU->getHeight(),
3503 return true;
3504 } else {
3505 // Prefer the candidate with the lesser height, but only if one of them has
3506 // height greater than the total latency scheduled so far, otherwise either
3507 // of them could be scheduled now with no stall.
3508 if (std::max(TryCand.SU->getHeight(), Cand.SU->getHeight()) >
3509 Zone.getScheduledLatency()) {
3510 if (tryLess(TryCand.SU->getHeight(), Cand.SU->getHeight(),
3512 return true;
3513 }
3514 if (tryGreater(TryCand.SU->getDepth(), Cand.SU->getDepth(),
3516 return true;
3517 }
3518 return false;
3519}
3520
3521static void tracePick(const SUnit *SU,
3523 const bool IsTop, const bool IsPostRA = false) {
3524 assert(SU && "SU must not be null for tracing");
3525 LLVM_DEBUG(dbgs() << "Pick " << (IsTop ? "Top " : "Bot ") << "Cand " << *SU
3526 << " " << GenericSchedulerBase::getReasonStr(Reason) << " ["
3527 << (IsPostRA ? "post-RA" : "pre-RA") << "]\n");
3528
3529 if (IsPostRA) {
3530 if (IsTop)
3531 NumTopPostRA++;
3532 else
3533 NumBotPostRA++;
3534
3535 switch (Reason) {
3537 NumNoCandPostRA++;
3538 return;
3540 NumOnly1PostRA++;
3541 return;
3543 NumPhysRegPostRA++;
3544 return;
3546 NumRegExcessPostRA++;
3547 return;
3549 NumRegCriticalPostRA++;
3550 return;
3552 NumStallPostRA++;
3553 return;
3555 NumClusterPostRA++;
3556 return;
3558 NumWeakPostRA++;
3559 return;
3561 NumRegMaxPostRA++;
3562 return;
3564 NumResourceReducePostRA++;
3565 return;
3567 NumResourceDemandPostRA++;
3568 return;
3570 NumTopDepthReducePostRA++;
3571 return;
3573 NumTopPathReducePostRA++;
3574 return;
3576 NumBotHeightReducePostRA++;
3577 return;
3579 NumBotPathReducePostRA++;
3580 return;
3582 NumNodeOrderPostRA++;
3583 return;
3585 NumFirstValidPostRA++;
3586 return;
3587 };
3588 } else {
3589 if (IsTop)
3590 NumTopPreRA++;
3591 else
3592 NumBotPreRA++;
3593
3594 switch (Reason) {
3596 NumNoCandPreRA++;
3597 return;
3599 NumOnly1PreRA++;
3600 return;
3602 NumPhysRegPreRA++;
3603 return;
3605 NumRegExcessPreRA++;
3606 return;
3608 NumRegCriticalPreRA++;
3609 return;
3611 NumStallPreRA++;
3612 return;
3614 NumClusterPreRA++;
3615 return;
3617 NumWeakPreRA++;
3618 return;
3620 NumRegMaxPreRA++;
3621 return;
3623 NumResourceReducePreRA++;
3624 return;
3626 NumResourceDemandPreRA++;
3627 return;
3629 NumTopDepthReducePreRA++;
3630 return;
3632 NumTopPathReducePreRA++;
3633 return;
3635 NumBotHeightReducePreRA++;
3636 return;
3638 NumBotPathReducePreRA++;
3639 return;
3641 NumNodeOrderPreRA++;
3642 return;
3644 NumFirstValidPreRA++;
3645 return;
3646 };
3647 }
3648 llvm_unreachable("Unknown reason!");
3649}
3650
3652 const bool IsPostRA = false) {
3653 tracePick(Cand.SU, Cand.Reason, Cand.AtTop, IsPostRA);
3654}
3655
3657 assert(dag->hasVRegLiveness() &&
3658 "(PreRA)GenericScheduler needs vreg liveness");
3659 DAG = static_cast<ScheduleDAGMILive*>(dag);
3660 SchedModel = DAG->getSchedModel();
3661 TRI = DAG->TRI;
3662
3663 if (RegionPolicy.ComputeDFSResult)
3664 DAG->computeDFSResult();
3665
3666 Rem.init(DAG, SchedModel);
3667 Top.init(DAG, SchedModel, &Rem);
3668 Bot.init(DAG, SchedModel, &Rem);
3669
3670 // Initialize resource counts.
3671
3672 // Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
3673 // are disabled, then these HazardRecs will be disabled.
3674 const InstrItineraryData *Itin = SchedModel->getInstrItineraries();
3675 if (!Top.HazardRec)
3676 Top.HazardRec.reset(DAG->TII->CreateTargetMIHazardRecognizer(Itin, DAG));
3677 if (!Bot.HazardRec)
3678 Bot.HazardRec.reset(DAG->TII->CreateTargetMIHazardRecognizer(Itin, DAG));
3679 TopCand.SU = nullptr;
3680 BotCand.SU = nullptr;
3681
3684}
3685
3686/// Initialize the per-region scheduling policy.
3689 unsigned NumRegionInstrs) {
3690 const MachineFunction &MF = *Begin->getMF();
3691 const TargetLowering *TLI = MF.getSubtarget().getTargetLowering();
3692
3693 // Avoid setting up the register pressure tracker for small regions to save
3694 // compile time. As a rough heuristic, only track pressure when the number of
3695 // schedulable instructions exceeds half the allocatable integer register file
3696 // that is the largest legal integer regiser type.
3697 RegionPolicy.ShouldTrackPressure = true;
3698 for (unsigned VT = MVT::i64; VT > (unsigned)MVT::i1; --VT) {
3700 if (TLI->isTypeLegal(LegalIntVT)) {
3701 unsigned NIntRegs = Context->RegClassInfo->getNumAllocatableRegs(
3702 TLI->getRegClassFor(LegalIntVT));
3703 RegionPolicy.ShouldTrackPressure = NumRegionInstrs > (NIntRegs / 2);
3704 break;
3705 }
3706 }
3707
3708 // For generic targets, we default to bottom-up, because it's simpler and more
3709 // compile-time optimizations have been implemented in that direction.
3710 RegionPolicy.OnlyBottomUp = true;
3711
3712 // Allow the subtarget to override default policy.
3713 SchedRegion Region(Begin, End, NumRegionInstrs);
3715
3716 // After subtarget overrides, apply command line options.
3717 if (!EnableRegPressure) {
3718 RegionPolicy.ShouldTrackPressure = false;
3719 RegionPolicy.ShouldTrackLaneMasks = false;
3720 }
3721
3723 RegionPolicy.OnlyTopDown = true;
3724 RegionPolicy.OnlyBottomUp = false;
3725 } else if (PreRADirection == MISched::BottomUp) {
3726 RegionPolicy.OnlyTopDown = false;
3727 RegionPolicy.OnlyBottomUp = true;
3728 } else if (PreRADirection == MISched::Bidirectional) {
3729 RegionPolicy.OnlyBottomUp = false;
3730 RegionPolicy.OnlyTopDown = false;
3731 }
3732
3733 BotIdx = NumRegionInstrs - 1;
3734 this->NumRegionInstrs = NumRegionInstrs;
3735}
3736
3738 // Cannot completely remove virtual function even in release mode.
3739#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3740 dbgs() << "GenericScheduler RegionPolicy: "
3741 << " ShouldTrackPressure=" << RegionPolicy.ShouldTrackPressure
3742 << " OnlyTopDown=" << RegionPolicy.OnlyTopDown
3743 << " OnlyBottomUp=" << RegionPolicy.OnlyBottomUp
3744 << "\n";
3745#endif
3746}
3747
3748/// Set IsAcyclicLatencyLimited if the acyclic path is longer than the cyclic
3749/// critical path by more cycles than it takes to drain the instruction buffer.
3750/// We estimate an upper bounds on in-flight instructions as:
3751///
3752/// CyclesPerIteration = max( CyclicPath, Loop-Resource-Height )
3753/// InFlightIterations = AcyclicPath / CyclesPerIteration
3754/// InFlightResources = InFlightIterations * LoopResources
3755///
3756/// TODO: Check execution resources in addition to IssueCount.
3758 if (Rem.CyclicCritPath == 0 || Rem.CyclicCritPath >= Rem.CriticalPath)
3759 return;
3760
3761 // Scaled number of cycles per loop iteration.
3762 unsigned IterCount =
3763 std::max(Rem.CyclicCritPath * SchedModel->getLatencyFactor(),
3764 Rem.RemIssueCount);
3765 // Scaled acyclic critical path.
3766 unsigned AcyclicCount = Rem.CriticalPath * SchedModel->getLatencyFactor();
3767 // InFlightCount = (AcyclicPath / IterCycles) * InstrPerLoop
3768 unsigned InFlightCount =
3769 (AcyclicCount * Rem.RemIssueCount + IterCount-1) / IterCount;
3770 unsigned BufferLimit =
3771 SchedModel->getMicroOpBufferSize() * SchedModel->getMicroOpFactor();
3772
3773 Rem.IsAcyclicLatencyLimited = InFlightCount > BufferLimit;
3774
3775 LLVM_DEBUG(
3776 dbgs() << "IssueCycles="
3777 << Rem.RemIssueCount / SchedModel->getLatencyFactor() << "c "
3778 << "IterCycles=" << IterCount / SchedModel->getLatencyFactor()
3779 << "c NumIters=" << (AcyclicCount + IterCount - 1) / IterCount
3780 << " InFlight=" << InFlightCount / SchedModel->getMicroOpFactor()
3781 << "m BufferLim=" << SchedModel->getMicroOpBufferSize() << "m\n";
3782 if (Rem.IsAcyclicLatencyLimited) dbgs() << " ACYCLIC LATENCY LIMIT\n");
3783}
3784
3786 Rem.CriticalPath = DAG->ExitSU.getDepth();
3787
3788 // Some roots may not feed into ExitSU. Check all of them in case.
3789 for (const SUnit *SU : Bot.Available) {
3790 if (SU->getDepth() > Rem.CriticalPath)
3791 Rem.CriticalPath = SU->getDepth();
3792 }
3793 LLVM_DEBUG(dbgs() << "Critical Path(GS-RR ): " << Rem.CriticalPath << '\n');
3795 errs() << "Critical Path(GS-RR ): " << Rem.CriticalPath << " \n";
3796 }
3797
3798 if (EnableCyclicPath && SchedModel->getMicroOpBufferSize() > 0) {
3799 Rem.CyclicCritPath = DAG->computeCyclicCriticalPath();
3801 }
3802}
3803
3804bool llvm::tryPressure(const PressureChange &TryP, const PressureChange &CandP,
3808 const TargetRegisterInfo *TRI,
3809 const MachineFunction &MF) {
3810 // If one candidate decreases and the other increases, go with it.
3811 // Invalid candidates have UnitInc==0.
3812 if (tryGreater(TryP.getUnitInc() < 0, CandP.getUnitInc() < 0, TryCand, Cand,
3813 Reason)) {
3814 return true;
3815 }
3816 // Do not compare the magnitude of pressure changes between top and bottom
3817 // boundary.
3818 if (Cand.AtTop != TryCand.AtTop)
3819 return false;
3820
3821 // If both candidates affect the same set in the same boundary, go with the
3822 // smallest increase.
3823 unsigned TryPSet = TryP.getPSetOrMax();
3824 unsigned CandPSet = CandP.getPSetOrMax();
3825 if (TryPSet == CandPSet) {
3826 return tryLess(TryP.getUnitInc(), CandP.getUnitInc(), TryCand, Cand,
3827 Reason);
3828 }
3829
3830 int TryRank = TryP.isValid() ? TRI->getRegPressureSetScore(MF, TryPSet) :
3831 std::numeric_limits<int>::max();
3832
3833 int CandRank = CandP.isValid() ? TRI->getRegPressureSetScore(MF, CandPSet) :
3834 std::numeric_limits<int>::max();
3835
3836 // If the candidates are decreasing pressure, reverse priority.
3837 if (TryP.getUnitInc() < 0)
3838 std::swap(TryRank, CandRank);
3839 return tryGreater(TryRank, CandRank, TryCand, Cand, Reason);
3840}
3841
3842unsigned llvm::getWeakLeft(const SUnit *SU, bool isTop) {
3843 return (isTop) ? SU->WeakPredsLeft : SU->WeakSuccsLeft;
3844}
3845
3846/// Minimize physical register live ranges. Regalloc wants them adjacent to
3847/// their physreg def/use.
3848///
3849/// FIXME: This is an unnecessary check on the critical path. Most are root/leaf
3850/// copies which can be prescheduled. The rest (e.g. x86 MUL) could be bundled
3851/// with the operation that produces or consumes the physreg. We'll do this when
3852/// regalloc has support for parallel copies.
3853int llvm::biasPhysReg(const SUnit *SU, bool isTop, bool BiasPRegsExtra) {
3854 const MachineInstr *MI = SU->getInstr();
3855
3856 if (MI->isCopy()) {
3857 unsigned ScheduledOper = isTop ? 1 : 0;
3858 unsigned UnscheduledOper = isTop ? 0 : 1;
3859 // If we have already scheduled the physreg produce/consumer, immediately
3860 // schedule the copy.
3861 if (MI->getOperand(ScheduledOper).getReg().isPhysical())
3862 return 1;
3863 // If the physreg is at the boundary, defer it. Otherwise schedule it
3864 // immediately to free the dependent. We can hoist the copy later.
3865 bool AtBoundary = isTop ? !SU->NumSuccsLeft : !SU->NumPredsLeft;
3866 if (MI->getOperand(UnscheduledOper).getReg().isPhysical())
3867 return AtBoundary ? -1 : 1;
3868 }
3869
3870 if (MI->isMoveImmediate()) {
3871 // If we have a move immediate and all successors have been assigned, bias
3872 // towards scheduling this later. Make sure all register defs are to
3873 // physical registers.
3874 bool DoBias = true;
3875 for (const MachineOperand &Op : MI->defs()) {
3876 if (Op.isReg() && !Op.getReg().isPhysical()) {
3877 DoBias = false;
3878 break;
3879 }
3880 }
3881
3882 if (DoBias)
3883 return isTop ? -1 : 1;
3884 }
3885
3886 if (BiasPRegsExtra && !isTop && MI->getNumExplicitDefs() == 1)
3887 // Register coalescer will create cases of e.g. Load Address of a frame
3888 // index directly into a physreg.
3889 return MI->getOperand(0).getReg().isPhysical();
3890
3891 return 0;
3892}
3893
3896 SchedBoundary *Zone, bool BiasPRegsExtra) {
3897 int TryCandPRegBias = biasPhysReg(TryCand.SU, TryCand.AtTop, BiasPRegsExtra);
3898 int CandPRegBias = biasPhysReg(Cand.SU, Cand.AtTop, BiasPRegsExtra);
3899 if (tryGreater(TryCandPRegBias, CandPRegBias, TryCand, Cand,
3901 return true;
3902 if (BiasPRegsExtra && Zone != nullptr && TryCandPRegBias &&
3903 TryCandPRegBias == CandPRegBias) {
3904 // Both biased same way - maintain their input order.
3905 if (Zone->isTop())
3906 tryLess(TryCand.SU->NodeNum, Cand.SU->NodeNum, TryCand, Cand,
3908 else
3909 tryGreater(TryCand.SU->NodeNum, Cand.SU->NodeNum, TryCand, Cand,
3911 return true;
3912 }
3913 return false;
3914}
3915
3917 bool AtTop,
3918 const RegPressureTracker &RPTracker,
3919 RegPressureTracker &TempTracker) {
3920 Cand.SU = SU;
3921 Cand.AtTop = AtTop;
3922 if (DAG->isTrackingPressure()) {
3923 if (AtTop) {
3924 TempTracker.getMaxDownwardPressureDelta(
3925 Cand.SU->getInstr(),
3926 Cand.RPDelta,
3927 DAG->getRegionCriticalPSets(),
3928 DAG->getRegPressure().MaxSetPressure);
3929 } else {
3930 if (VerifyScheduling) {
3931 TempTracker.getMaxUpwardPressureDelta(
3932 Cand.SU->getInstr(),
3933 &DAG->getPressureDiff(Cand.SU),
3934 Cand.RPDelta,
3935 DAG->getRegionCriticalPSets(),
3936 DAG->getRegPressure().MaxSetPressure);
3937 } else {
3938 RPTracker.getUpwardPressureDelta(
3939 Cand.SU->getInstr(),
3940 DAG->getPressureDiff(Cand.SU),
3941 Cand.RPDelta,
3942 DAG->getRegionCriticalPSets(),
3943 DAG->getRegPressure().MaxSetPressure);
3944 }
3945 }
3946 }
3947 LLVM_DEBUG(if (Cand.RPDelta.Excess.isValid()) dbgs()
3948 << " Try " << *Cand.SU << " "
3949 << TRI->getRegPressureSetName(Cand.RPDelta.Excess.getPSet()) << ":"
3950 << Cand.RPDelta.Excess.getUnitInc() << "\n");
3951}
3952
3953/// Apply a set of heuristics to a new candidate. Heuristics are currently
3954/// hierarchical. This may be more efficient than a graduated cost model because
3955/// we don't need to evaluate all aspects of the model for each node in the
3956/// queue. But it's really done to make the heuristics easier to debug and
3957/// statistically analyze.
3958///
3959/// \param Cand provides the policy and current best candidate.
3960/// \param TryCand refers to the next SUnit candidate, otherwise uninitialized.
3961/// \param Zone describes the scheduled zone that we are extending, or nullptr
3962/// if Cand is from a different zone than TryCand.
3963/// \return \c true if TryCand is better than Cand (Reason is NOT NoCand)
3965 SchedCandidate &TryCand,
3966 SchedBoundary *Zone) const {
3967 // Initialize the candidate if needed.
3968 if (!Cand.isValid()) {
3969 TryCand.Reason = FirstValid;
3970 return true;
3971 }
3972
3973 // Bias PhysReg Defs and copies to their uses and defined respectively.
3974 if (tryBiasPhysRegs(TryCand, Cand, Zone, RegionPolicy.BiasPRegsExtra))
3975 return TryCand.Reason != NoCand;
3976
3977 // Avoid exceeding the target's limit.
3978 if (DAG->isTrackingPressure() && tryPressure(TryCand.RPDelta.Excess,
3979 Cand.RPDelta.Excess,
3980 TryCand, Cand, RegExcess, TRI,
3981 DAG->MF))
3982 return TryCand.Reason != NoCand;
3983
3984 // Avoid increasing the max critical pressure in the scheduled region.
3985 if (DAG->isTrackingPressure() && tryPressure(TryCand.RPDelta.CriticalMax,
3986 Cand.RPDelta.CriticalMax,
3987 TryCand, Cand, RegCritical, TRI,
3988 DAG->MF))
3989 return TryCand.Reason != NoCand;
3990
3991 // We only compare a subset of features when comparing nodes between
3992 // Top and Bottom boundary. Some properties are simply incomparable, in many
3993 // other instances we should only override the other boundary if something
3994 // is a clear good pick on one boundary. Skip heuristics that are more
3995 // "tie-breaking" in nature.
3996 bool SameBoundary = Zone != nullptr;
3997 if (SameBoundary) {
3998 // For loops that are acyclic path limited, aggressively schedule for
3999 // latency. Within an single cycle, whenever CurrMOps > 0, allow normal
4000 // heuristics to take precedence.
4001 if (Rem.IsAcyclicLatencyLimited && !Zone->getCurrMOps() &&
4002 tryLatency(TryCand, Cand, *Zone))
4003 return TryCand.Reason != NoCand;
4004
4005 // Prioritize instructions that read unbuffered resources by stall cycles.
4006 if (tryLess(Zone->getLatencyStallCycles(TryCand.SU),
4007 Zone->getLatencyStallCycles(Cand.SU), TryCand, Cand, Stall))
4008 return TryCand.Reason != NoCand;
4009 }
4010
4011 // Keep clustered nodes together to encourage downstream peephole
4012 // optimizations which may reduce resource requirements.
4013 //
4014 // This is a best effort to set things up for a post-RA pass. Optimizations
4015 // like generating loads of multiple registers should ideally be done within
4016 // the scheduler pass by combining the loads during DAG postprocessing.
4017 unsigned CandZoneCluster = Cand.AtTop ? TopClusterID : BotClusterID;
4018 unsigned TryCandZoneCluster = TryCand.AtTop ? TopClusterID : BotClusterID;
4019 bool CandIsClusterSucc =
4020 isTheSameCluster(CandZoneCluster, Cand.SU->ParentClusterIdx);
4021 bool TryCandIsClusterSucc =
4022 isTheSameCluster(TryCandZoneCluster, TryCand.SU->ParentClusterIdx);
4023
4024 if (tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
4025 Cluster))
4026 return TryCand.Reason != NoCand;
4027
4028 if (SameBoundary) {
4029 // Weak edges are for clustering and other constraints.
4030 if (tryLess(getWeakLeft(TryCand.SU, TryCand.AtTop),
4031 getWeakLeft(Cand.SU, Cand.AtTop),
4032 TryCand, Cand, Weak))
4033 return TryCand.Reason != NoCand;
4034 }
4035
4036 // Avoid increasing the max pressure of the entire region.
4037 if (DAG->isTrackingPressure() && tryPressure(TryCand.RPDelta.CurrentMax,
4038 Cand.RPDelta.CurrentMax,
4039 TryCand, Cand, RegMax, TRI,
4040 DAG->MF))
4041 return TryCand.Reason != NoCand;
4042
4043 if (SameBoundary) {
4044 // Avoid critical resource consumption and balance the schedule.
4047 TryCand, Cand, ResourceReduce))
4048 return TryCand.Reason != NoCand;
4051 TryCand, Cand, ResourceDemand))
4052 return TryCand.Reason != NoCand;
4053
4054 // Avoid serializing long latency dependence chains.
4055 // For acyclic path limited loops, latency was already checked above.
4056 if (!RegionPolicy.DisableLatencyHeuristic && TryCand.Policy.ReduceLatency &&
4057 !Rem.IsAcyclicLatencyLimited && tryLatency(TryCand, Cand, *Zone))
4058 return TryCand.Reason != NoCand;
4059
4060 // Fall through to original instruction order.
4061 if ((Zone->isTop() && TryCand.SU->NodeNum < Cand.SU->NodeNum)
4062 || (!Zone->isTop() && TryCand.SU->NodeNum > Cand.SU->NodeNum)) {
4063 TryCand.Reason = NodeOrder;
4064 return true;
4065 }
4066 }
4067
4068 return false;
4069}
4070
4071/// Pick the best candidate from the queue.
4072///
4073/// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during
4074/// DAG building. To adjust for the current scheduling location we need to
4075/// maintain the number of vreg uses remaining to be top-scheduled.
4077 const CandPolicy &ZonePolicy,
4078 const RegPressureTracker &RPTracker,
4079 SchedCandidate &Cand) {
4080 // getMaxPressureDelta temporarily modifies the tracker.
4081 RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker);
4082
4083 ReadyQueue &Q = Zone.Available;
4084 for (SUnit *SU : Q) {
4085
4086 SchedCandidate TryCand(ZonePolicy);
4087 initCandidate(TryCand, SU, Zone.isTop(), RPTracker, TempTracker);
4088 // Pass SchedBoundary only when comparing nodes from the same boundary.
4089 SchedBoundary *ZoneArg = Cand.AtTop == TryCand.AtTop ? &Zone : nullptr;
4090 if (tryCandidate(Cand, TryCand, ZoneArg)) {
4091 // Initialize resource delta if needed in case future heuristics query it.
4092 if (TryCand.ResDelta == SchedResourceDelta())
4094 Cand.setBest(TryCand);
4096 }
4097 }
4098}
4099
4100/// Pick the best candidate node from either the top or bottom queue.
4102 // Schedule as far as possible in the direction of no choice. This is most
4103 // efficient, but also provides the best heuristics for CriticalPSets.
4104 if (SUnit *SU = Bot.pickOnlyChoice()) {
4105 IsTopNode = false;
4106 tracePick(SU, Only1, /*IsTopNode=*/false);
4107 return SU;
4108 }
4109 if (SUnit *SU = Top.pickOnlyChoice()) {
4110 IsTopNode = true;
4111 tracePick(SU, Only1, /*IsTopNode=*/true);
4112 return SU;
4113 }
4114 // Set the bottom-up policy based on the state of the current bottom zone and
4115 // the instructions outside the zone, including the top zone.
4116 CandPolicy BotPolicy;
4117 setPolicy(BotPolicy, /*IsPostRA=*/false, Bot, &Top);
4118 // Set the top-down policy based on the state of the current top zone and
4119 // the instructions outside the zone, including the bottom zone.
4120 CandPolicy TopPolicy;
4121 setPolicy(TopPolicy, /*IsPostRA=*/false, Top, &Bot);
4122
4123 // See if BotCand is still valid (because we previously scheduled from Top).
4124 LLVM_DEBUG(dbgs() << "Picking from Bot:\n");
4125 if (!BotCand.isValid() || BotCand.SU->isScheduled ||
4126 BotCand.Policy != BotPolicy) {
4127 BotCand.reset(CandPolicy());
4128 pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), BotCand);
4129 assert(BotCand.Reason != NoCand && "failed to find the first candidate");
4130 } else {
4132#ifndef NDEBUG
4133 if (VerifyScheduling) {
4134 SchedCandidate TCand;
4135 TCand.reset(CandPolicy());
4136 pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), TCand);
4137 assert(TCand.SU == BotCand.SU &&
4138 "Last pick result should correspond to re-picking right now");
4139 }
4140#endif
4141 }
4142
4143 // Check if the top Q has a better candidate.
4144 LLVM_DEBUG(dbgs() << "Picking from Top:\n");
4145 if (!TopCand.isValid() || TopCand.SU->isScheduled ||
4146 TopCand.Policy != TopPolicy) {
4147 TopCand.reset(CandPolicy());
4148 pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TopCand);
4149 assert(TopCand.Reason != NoCand && "failed to find the first candidate");
4150 } else {
4152#ifndef NDEBUG
4153 if (VerifyScheduling) {
4154 SchedCandidate TCand;
4155 TCand.reset(CandPolicy());
4156 pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TCand);
4157 assert(TCand.SU == TopCand.SU &&
4158 "Last pick result should correspond to re-picking right now");
4159 }
4160#endif
4161 }
4162
4163 // Pick best from BotCand and TopCand.
4164 assert(BotCand.isValid());
4165 assert(TopCand.isValid());
4166 SchedCandidate Cand = BotCand;
4167 TopCand.Reason = NoCand;
4168 if (tryCandidate(Cand, TopCand, nullptr)) {
4169 Cand.setBest(TopCand);
4171 }
4172
4173 IsTopNode = Cand.AtTop;
4174 tracePick(Cand);
4175 return Cand.SU;
4176}
4177
4178/// Pick the best node to balance the schedule. Implements MachineSchedStrategy.
4180 if (DAG->top() == DAG->bottom()) {
4181 assert(Top.Available.empty() && Top.Pending.empty() &&
4182 Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
4183 return nullptr;
4184 }
4185 SUnit *SU;
4186 if (RegionPolicy.OnlyTopDown) {
4187 SU = Top.pickOnlyChoice();
4188 if (SU) {
4189 tracePick(SU, Only1, /*IsTopNode=*/true);
4190 } else {
4191 CandPolicy NoPolicy;
4192 TopCand.reset(NoPolicy);
4193 pickNodeFromQueue(Top, NoPolicy, DAG->getTopRPTracker(), TopCand);
4194 assert(TopCand.Reason != NoCand && "failed to find a candidate");
4196 SU = TopCand.SU;
4197 }
4198 IsTopNode = true;
4199 } else if (RegionPolicy.OnlyBottomUp) {
4200 SU = Bot.pickOnlyChoice();
4201 if (SU) {
4202 tracePick(SU, Only1, /*IsTopNode=*/false);
4203 } else {
4204 CandPolicy NoPolicy;
4205 BotCand.reset(NoPolicy);
4206 pickNodeFromQueue(Bot, NoPolicy, DAG->getBotRPTracker(), BotCand);
4207 assert(BotCand.Reason != NoCand && "failed to find a candidate");
4209 SU = BotCand.SU;
4210 }
4211 IsTopNode = false;
4212 } else {
4213 SU = pickNodeBidirectional(IsTopNode);
4214 }
4215 assert(!SU->isScheduled && "SUnit scheduled twice.");
4216
4217 // If IsTopNode, then SU is in Top.Available and must be removed. Otherwise,
4218 // if isTopReady(), then SU is in either Top.Available or Top.Pending.
4219 // If !IsTopNode, then SU is in Bot.Available and must be removed. Otherwise,
4220 // if isBottomReady(), then SU is in either Bot.Available or Bot.Pending.
4221 //
4222 // It is coincidental when !IsTopNode && isTopReady or when IsTopNode &&
4223 // isBottomReady. That is, it didn't factor into the decision to choose SU
4224 // because it isTopReady or isBottomReady, respectively. In fact, if the
4225 // RegionPolicy is OnlyTopDown or OnlyBottomUp, then the Bot queues and Top
4226 // queues respectivley contain the original roots and don't get updated when
4227 // picking a node. So if SU isTopReady on a OnlyBottomUp pick, then it was
4228 // because we schduled everything but the top roots. Conversley, if SU
4229 // isBottomReady on OnlyTopDown, then it was because we scheduled everything
4230 // but the bottom roots. If its in a queue even coincidentally, it should be
4231 // removed so it does not get re-picked in a subsequent pickNode call.
4232 if (SU->isTopReady())
4233 Top.removeReady(SU);
4234 if (SU->isBottomReady())
4235 Bot.removeReady(SU);
4236
4237 LLVM_DEBUG(dbgs() << "Scheduling " << *SU << " " << *SU->getInstr());
4238
4239 if (IsTopNode) {
4240 if (SU->NodeNum == TopIdx++)
4241 ++NumInstrsInSourceOrderPreRA;
4242 } else {
4243 assert(BotIdx < NumRegionInstrs && "out of bounds");
4244 if (SU->NodeNum == BotIdx--)
4245 ++NumInstrsInSourceOrderPreRA;
4246 }
4247
4248 NumInstrsScheduledPreRA += 1;
4249
4250 return SU;
4251}
4252
4254 MachineBasicBlock::iterator InsertPos = SU->getInstr();
4255 if (!isTop)
4256 ++InsertPos;
4257 SmallVectorImpl<SDep> &Deps = isTop ? SU->Preds : SU->Succs;
4258
4259 // Find already scheduled copies with a single physreg dependence and move
4260 // them just above the scheduled instruction.
4261 for (SDep &Dep : Deps) {
4262 if (Dep.getKind() != SDep::Data || !Dep.getReg().isPhysical())
4263 continue;
4264 SUnit *DepSU = Dep.getSUnit();
4265 if (isTop ? DepSU->Succs.size() > 1 : DepSU->Preds.size() > 1)
4266 continue;
4267 MachineInstr *Copy = DepSU->getInstr();
4268 if (!Copy->isCopy() && !Copy->isMoveImmediate())
4269 continue;
4270 LLVM_DEBUG(dbgs() << " Rescheduling physreg copy ";
4271 DAG->dumpNode(*Dep.getSUnit()));
4272 DAG->moveInstruction(Copy, InsertPos);
4273 }
4274}
4275
4276/// Update the scheduler's state after scheduling a node. This is the same node
4277/// that was just returned by pickNode(). However, ScheduleDAGMILive needs to
4278/// update it's state based on the current cycle before MachineSchedStrategy
4279/// does.
4280///
4281/// FIXME: Eventually, we may bundle physreg copies rather than rescheduling
4282/// them here. See comments in biasPhysReg.
4283void GenericScheduler::schedNode(SUnit *SU, bool IsTopNode) {
4284 if (IsTopNode) {
4285 SU->TopReadyCycle = std::max(SU->TopReadyCycle, Top.getCurrCycle());
4287 LLVM_DEBUG({
4289 ClusterInfo *TopCluster = DAG->getCluster(TopClusterID);
4290 dbgs() << " Top Cluster: ";
4291 for (auto *N : *TopCluster)
4292 dbgs() << N->NodeNum << '\t';
4293 dbgs() << '\n';
4294 }
4295 });
4296 Top.bumpNode(SU);
4297 if (SU->hasPhysRegUses)
4298 reschedulePhysReg(SU, true);
4299 } else {
4300 SU->BotReadyCycle = std::max(SU->BotReadyCycle, Bot.getCurrCycle());
4302 LLVM_DEBUG({
4304 ClusterInfo *BotCluster = DAG->getCluster(BotClusterID);
4305 dbgs() << " Bot Cluster: ";
4306 for (auto *N : *BotCluster)
4307 dbgs() << N->NodeNum << '\t';
4308 dbgs() << '\n';
4309 }
4310 });
4311 Bot.bumpNode(SU);
4312 if (SU->hasPhysRegDefs)
4313 reschedulePhysReg(SU, false);
4314 }
4315}
4316
4320
4321static MachineSchedRegistry
4322GenericSchedRegistry("converge", "Standard converging scheduler.",
4324
4325//===----------------------------------------------------------------------===//
4326// PostGenericScheduler - Generic PostRA implementation of MachineSchedStrategy.
4327//===----------------------------------------------------------------------===//
4328
4330 DAG = Dag;
4331 SchedModel = DAG->getSchedModel();
4332 TRI = DAG->TRI;
4333
4334 Rem.init(DAG, SchedModel);
4335 Top.init(DAG, SchedModel, &Rem);
4336 Bot.init(DAG, SchedModel, &Rem);
4337
4338 // Initialize the HazardRecognizers. If itineraries don't exist, are empty,
4339 // or are disabled, then these HazardRecs will be disabled.
4340 const InstrItineraryData *Itin = SchedModel->getInstrItineraries();
4341 if (!Top.HazardRec)
4342 Top.HazardRec.reset(DAG->TII->CreateTargetMIHazardRecognizer(Itin, DAG));
4343 if (!Bot.HazardRec)
4344 Bot.HazardRec.reset(DAG->TII->CreateTargetMIHazardRecognizer(Itin, DAG));
4347}
4348
4351 unsigned NumRegionInstrs) {
4352 const MachineFunction &MF = *Begin->getMF();
4353
4354 // Default to top-down because it was implemented first and existing targets
4355 // expect that behavior by default.
4356 RegionPolicy.OnlyTopDown = true;
4357 RegionPolicy.OnlyBottomUp = false;
4358
4359 // Allow the subtarget to override default policy.
4360 SchedRegion Region(Begin, End, NumRegionInstrs);
4362
4363 // After subtarget overrides, apply command line options.
4365 RegionPolicy.OnlyTopDown = true;
4366 RegionPolicy.OnlyBottomUp = false;
4367 } else if (PostRADirection == MISched::BottomUp) {
4368 RegionPolicy.OnlyTopDown = false;
4369 RegionPolicy.OnlyBottomUp = true;
4371 RegionPolicy.OnlyBottomUp = false;
4372 RegionPolicy.OnlyTopDown = false;
4373 }
4374
4375 BotIdx = NumRegionInstrs - 1;
4376 this->NumRegionInstrs = NumRegionInstrs;
4377}
4378
4380 Rem.CriticalPath = DAG->ExitSU.getDepth();
4381
4382 // Some roots may not feed into ExitSU. Check all of them in case.
4383 for (const SUnit *SU : Bot.Available) {
4384 if (SU->getDepth() > Rem.CriticalPath)
4385 Rem.CriticalPath = SU->getDepth();
4386 }
4387 LLVM_DEBUG(dbgs() << "Critical Path: (PGS-RR) " << Rem.CriticalPath << '\n');
4389 errs() << "Critical Path(PGS-RR ): " << Rem.CriticalPath << " \n";
4390 }
4391}
4392
4393/// Apply a set of heuristics to a new candidate for PostRA scheduling.
4394///
4395/// \param Cand provides the policy and current best candidate.
4396/// \param TryCand refers to the next SUnit candidate, otherwise uninitialized.
4397/// \return \c true if TryCand is better than Cand (Reason is NOT NoCand)
4399 SchedCandidate &TryCand) {
4400 // Initialize the candidate if needed.
4401 if (!Cand.isValid()) {
4402 TryCand.Reason = FirstValid;
4403 return true;
4404 }
4405
4406 // Prioritize instructions that read unbuffered resources by stall cycles.
4407 if (tryLess(Top.getLatencyStallCycles(TryCand.SU),
4408 Top.getLatencyStallCycles(Cand.SU), TryCand, Cand, Stall))
4409 return TryCand.Reason != NoCand;
4410
4411 // Keep clustered nodes together.
4412 unsigned CandZoneCluster = Cand.AtTop ? TopClusterID : BotClusterID;
4413 unsigned TryCandZoneCluster = TryCand.AtTop ? TopClusterID : BotClusterID;
4414 bool CandIsClusterSucc =
4415 isTheSameCluster(CandZoneCluster, Cand.SU->ParentClusterIdx);
4416 bool TryCandIsClusterSucc =
4417 isTheSameCluster(TryCandZoneCluster, TryCand.SU->ParentClusterIdx);
4418
4419 if (tryGreater(TryCandIsClusterSucc, CandIsClusterSucc, TryCand, Cand,
4420 Cluster))
4421 return TryCand.Reason != NoCand;
4422 // Avoid critical resource consumption and balance the schedule.
4424 TryCand, Cand, ResourceReduce))
4425 return TryCand.Reason != NoCand;
4428 TryCand, Cand, ResourceDemand))
4429 return TryCand.Reason != NoCand;
4430
4431 // We only compare a subset of features when comparing nodes between
4432 // Top and Bottom boundary.
4433 if (Cand.AtTop == TryCand.AtTop) {
4434 // Avoid serializing long latency dependence chains.
4435 if (Cand.Policy.ReduceLatency &&
4436 tryLatency(TryCand, Cand, Cand.AtTop ? Top : Bot))
4437 return TryCand.Reason != NoCand;
4438 }
4439
4440 // Fall through to original instruction order.
4441 if (TryCand.SU->NodeNum < Cand.SU->NodeNum) {
4442 TryCand.Reason = NodeOrder;
4443 return true;
4444 }
4445
4446 return false;
4447}
4448
4450 SchedCandidate &Cand) {
4451 ReadyQueue &Q = Zone.Available;
4452 for (SUnit *SU : Q) {
4453 SchedCandidate TryCand(Cand.Policy);
4454 TryCand.SU = SU;
4455 TryCand.AtTop = Zone.isTop();
4457 if (tryCandidate(Cand, TryCand)) {
4458 Cand.setBest(TryCand);
4460 }
4461 }
4462}
4463
4464/// Pick the best candidate node from either the top or bottom queue.
4466 // FIXME: This is similiar to GenericScheduler::pickNodeBidirectional. Factor
4467 // out common parts.
4468
4469 // Schedule as far as possible in the direction of no choice. This is most
4470 // efficient, but also provides the best heuristics for CriticalPSets.
4471 if (SUnit *SU = Bot.pickOnlyChoice()) {
4472 IsTopNode = false;
4473 tracePick(SU, Only1, /*IsTopNode=*/false, /*IsPostRA=*/true);
4474 return SU;
4475 }
4476 if (SUnit *SU = Top.pickOnlyChoice()) {
4477 IsTopNode = true;
4478 tracePick(SU, Only1, /*IsTopNode=*/true, /*IsPostRA=*/true);
4479 return SU;
4480 }
4481 // Set the bottom-up policy based on the state of the current bottom zone and
4482 // the instructions outside the zone, including the top zone.
4483 CandPolicy BotPolicy;
4484 setPolicy(BotPolicy, /*IsPostRA=*/true, Bot, &Top);
4485 // Set the top-down policy based on the state of the current top zone and
4486 // the instructions outside the zone, including the bottom zone.
4487 CandPolicy TopPolicy;
4488 setPolicy(TopPolicy, /*IsPostRA=*/true, Top, &Bot);
4489
4490 // See if BotCand is still valid (because we previously scheduled from Top).
4491 LLVM_DEBUG(dbgs() << "Picking from Bot:\n");
4492 if (!BotCand.isValid() || BotCand.SU->isScheduled ||
4493 BotCand.Policy != BotPolicy) {
4494 BotCand.reset(CandPolicy());
4496 assert(BotCand.Reason != NoCand && "failed to find the first candidate");
4497 } else {
4499#ifndef NDEBUG
4500 if (VerifyScheduling) {
4501 SchedCandidate TCand;
4502 TCand.reset(CandPolicy());
4504 assert(TCand.SU == BotCand.SU &&
4505 "Last pick result should correspond to re-picking right now");
4506 }
4507#endif
4508 }
4509
4510 // Check if the top Q has a better candidate.
4511 LLVM_DEBUG(dbgs() << "Picking from Top:\n");
4512 if (!TopCand.isValid() || TopCand.SU->isScheduled ||
4513 TopCand.Policy != TopPolicy) {
4514 TopCand.reset(CandPolicy());
4516 assert(TopCand.Reason != NoCand && "failed to find the first candidate");
4517 } else {
4519#ifndef NDEBUG
4520 if (VerifyScheduling) {
4521 SchedCandidate TCand;
4522 TCand.reset(CandPolicy());
4524 assert(TCand.SU == TopCand.SU &&
4525 "Last pick result should correspond to re-picking right now");
4526 }
4527#endif
4528 }
4529
4530 // Pick best from BotCand and TopCand.
4531 assert(BotCand.isValid());
4532 assert(TopCand.isValid());
4533 SchedCandidate Cand = BotCand;
4534 TopCand.Reason = NoCand;
4535 if (tryCandidate(Cand, TopCand)) {
4536 Cand.setBest(TopCand);
4538 }
4539
4540 IsTopNode = Cand.AtTop;
4541 tracePick(Cand, /*IsPostRA=*/true);
4542 return Cand.SU;
4543}
4544
4545/// Pick the next node to schedule.
4547 if (DAG->top() == DAG->bottom()) {
4548 assert(Top.Available.empty() && Top.Pending.empty() &&
4549 Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
4550 return nullptr;
4551 }
4552 SUnit *SU;
4553 if (RegionPolicy.OnlyBottomUp) {
4554 SU = Bot.pickOnlyChoice();
4555 if (SU) {
4556 tracePick(SU, Only1, /*IsTopNode=*/false, /*IsPostRA=*/true);
4557 } else {
4558 CandPolicy NoPolicy;
4559 BotCand.reset(NoPolicy);
4560 // Set the bottom-up policy based on the state of the current bottom
4561 // zone and the instructions outside the zone, including the top zone.
4562 setPolicy(BotCand.Policy, /*IsPostRA=*/true, Bot, nullptr);
4564 assert(BotCand.Reason != NoCand && "failed to find a candidate");
4565 tracePick(BotCand, /*IsPostRA=*/true);
4566 SU = BotCand.SU;
4567 }
4568 IsTopNode = false;
4569 } else if (RegionPolicy.OnlyTopDown) {
4570 SU = Top.pickOnlyChoice();
4571 if (SU) {
4572 tracePick(SU, Only1, /*IsTopNode=*/true, /*IsPostRA=*/true);
4573 } else {
4574 CandPolicy NoPolicy;
4575 TopCand.reset(NoPolicy);
4576 // Set the top-down policy based on the state of the current top zone
4577 // and the instructions outside the zone, including the bottom zone.
4578 setPolicy(TopCand.Policy, /*IsPostRA=*/true, Top, nullptr);
4580 assert(TopCand.Reason != NoCand && "failed to find a candidate");
4581 tracePick(TopCand, /*IsPostRA=*/true);
4582 SU = TopCand.SU;
4583 }
4584 IsTopNode = true;
4585 } else {
4586 SU = pickNodeBidirectional(IsTopNode);
4587 }
4588 assert(!SU->isScheduled && "SUnit scheduled twice.");
4589
4590 if (SU->isTopReady())
4591 Top.removeReady(SU);
4592 if (SU->isBottomReady())
4593 Bot.removeReady(SU);
4594
4595 LLVM_DEBUG(dbgs() << "Scheduling " << *SU << " " << *SU->getInstr());
4596
4597 if (IsTopNode) {
4598 if (SU->NodeNum == TopIdx++)
4599 ++NumInstrsInSourceOrderPostRA;
4600 } else {
4601 assert(BotIdx < NumRegionInstrs && "out of bounds");
4602 if (SU->NodeNum == BotIdx--)
4603 ++NumInstrsInSourceOrderPostRA;
4604 }
4605
4606 NumInstrsScheduledPostRA += 1;
4607
4608 return SU;
4609}
4610
4611/// Called after ScheduleDAGMI has scheduled an instruction and updated
4612/// scheduled/remaining flags in the DAG nodes.
4613void PostGenericScheduler::schedNode(SUnit *SU, bool IsTopNode) {
4614 if (IsTopNode) {
4615 SU->TopReadyCycle = std::max(SU->TopReadyCycle, Top.getCurrCycle());
4617 Top.bumpNode(SU);
4618 } else {
4619 SU->BotReadyCycle = std::max(SU->BotReadyCycle, Bot.getCurrCycle());
4621 Bot.bumpNode(SU);
4622 }
4623}
4624
4625//===----------------------------------------------------------------------===//
4626// ILP Scheduler. Currently for experimental analysis of heuristics.
4627//===----------------------------------------------------------------------===//
4628
4629namespace {
4630
4631/// Order nodes by the ILP metric.
4632struct ILPOrder {
4633 const SchedDFSResult *DFSResult = nullptr;
4634 const BitVector *ScheduledTrees = nullptr;
4635 bool MaximizeILP;
4636
4637 ILPOrder(bool MaxILP) : MaximizeILP(MaxILP) {}
4638
4639 /// Apply a less-than relation on node priority.
4640 ///
4641 /// (Return true if A comes after B in the Q.)
4642 bool operator()(const SUnit *A, const SUnit *B) const {
4643 unsigned SchedTreeA = DFSResult->getSubtreeID(A);
4644 unsigned SchedTreeB = DFSResult->getSubtreeID(B);
4645 if (SchedTreeA != SchedTreeB) {
4646 // Unscheduled trees have lower priority.
4647 if (ScheduledTrees->test(SchedTreeA) != ScheduledTrees->test(SchedTreeB))
4648 return ScheduledTrees->test(SchedTreeB);
4649
4650 // Trees with shallower connections have lower priority.
4651 if (DFSResult->getSubtreeLevel(SchedTreeA)
4652 != DFSResult->getSubtreeLevel(SchedTreeB)) {
4653 return DFSResult->getSubtreeLevel(SchedTreeA)
4654 < DFSResult->getSubtreeLevel(SchedTreeB);
4655 }
4656 }
4657 if (MaximizeILP)
4658 return DFSResult->getILP(A) < DFSResult->getILP(B);
4659 else
4660 return DFSResult->getILP(A) > DFSResult->getILP(B);
4661 }
4662};
4663
4664/// Schedule based on the ILP metric.
4665class ILPScheduler : public MachineSchedStrategy {
4666 ScheduleDAGMILive *DAG = nullptr;
4667 ILPOrder Cmp;
4668
4669 std::vector<SUnit*> ReadyQ;
4670
4671public:
4672 ILPScheduler(bool MaximizeILP) : Cmp(MaximizeILP) {}
4673
4674 void initialize(ScheduleDAGMI *dag) override {
4675 assert(dag->hasVRegLiveness() && "ILPScheduler needs vreg liveness");
4676 DAG = static_cast<ScheduleDAGMILive*>(dag);
4677 DAG->computeDFSResult();
4678 Cmp.DFSResult = DAG->getDFSResult();
4679 Cmp.ScheduledTrees = &DAG->getScheduledTrees();
4680 ReadyQ.clear();
4681 }
4682
4683 void registerRoots() override {
4684 // Restore the heap in ReadyQ with the updated DFS results.
4685 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4686 }
4687
4688 /// Implement MachineSchedStrategy interface.
4689 /// -----------------------------------------
4690
4691 /// Callback to select the highest priority node from the ready Q.
4692 SUnit *pickNode(bool &IsTopNode) override {
4693 if (ReadyQ.empty()) return nullptr;
4694 std::pop_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4695 SUnit *SU = ReadyQ.back();
4696 ReadyQ.pop_back();
4697 IsTopNode = false;
4698 LLVM_DEBUG(dbgs() << "Pick node " << *SU << " "
4699 << " ILP: " << DAG->getDFSResult()->getILP(SU)
4700 << " Tree: " << DAG->getDFSResult()->getSubtreeID(SU)
4701 << " @"
4702 << DAG->getDFSResult()->getSubtreeLevel(
4703 DAG->getDFSResult()->getSubtreeID(SU))
4704 << '\n'
4705 << "Scheduling " << *SU->getInstr());
4706 return SU;
4707 }
4708
4709 /// Scheduler callback to notify that a new subtree is scheduled.
4710 void scheduleTree(unsigned SubtreeID) override {
4711 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4712 }
4713
4714 /// Callback after a node is scheduled. Mark a newly scheduled tree, notify
4715 /// DFSResults, and resort the priority Q.
4716 void schedNode(SUnit *SU, bool IsTopNode) override {
4717 assert(!IsTopNode && "SchedDFSResult needs bottom-up");
4718 }
4719
4720 void releaseTopNode(SUnit *) override { /*only called for top roots*/ }
4721
4722 void releaseBottomNode(SUnit *SU) override {
4723 ReadyQ.push_back(SU);
4724 std::push_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
4725 }
4726};
4727
4728} // end anonymous namespace
4729
4731 return new ScheduleDAGMILive(C, std::make_unique<ILPScheduler>(true));
4732}
4734 return new ScheduleDAGMILive(C, std::make_unique<ILPScheduler>(false));
4735}
4736
4738 "ilpmax", "Schedule bottom-up for max ILP", createILPMaxScheduler);
4740 "ilpmin", "Schedule bottom-up for min ILP", createILPMinScheduler);
4741
4742//===----------------------------------------------------------------------===//
4743// Machine Instruction Shuffler for Correctness Testing
4744//===----------------------------------------------------------------------===//
4745
4746#ifndef NDEBUG
4747namespace {
4748
4749/// Apply a less-than relation on the node order, which corresponds to the
4750/// instruction order prior to scheduling. IsReverse implements greater-than.
4751template<bool IsReverse>
4752struct SUnitOrder {
4753 bool operator()(SUnit *A, SUnit *B) const {
4754 if (IsReverse)
4755 return A->NodeNum > B->NodeNum;
4756 else
4757 return A->NodeNum < B->NodeNum;
4758 }
4759};
4760
4761/// Reorder instructions as much as possible.
4762class InstructionShuffler : public MachineSchedStrategy {
4763 bool IsAlternating;
4764 bool IsTopDown;
4765
4766 // Using a less-than relation (SUnitOrder<false>) for the TopQ priority
4767 // gives nodes with a higher number higher priority causing the latest
4768 // instructions to be scheduled first.
4769 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<false>>
4770 TopQ;
4771
4772 // When scheduling bottom-up, use greater-than as the queue priority.
4773 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<true>>
4774 BottomQ;
4775
4776public:
4777 InstructionShuffler(bool alternate, bool topdown)
4778 : IsAlternating(alternate), IsTopDown(topdown) {}
4779
4780 void initialize(ScheduleDAGMI*) override {
4781 TopQ.clear();
4782 BottomQ.clear();
4783 }
4784
4785 /// Implement MachineSchedStrategy interface.
4786 /// -----------------------------------------
4787
4788 SUnit *pickNode(bool &IsTopNode) override {
4789 SUnit *SU;
4790 if (IsTopDown) {
4791 do {
4792 if (TopQ.empty()) return nullptr;
4793 SU = TopQ.top();
4794 TopQ.pop();
4795 } while (SU->isScheduled);
4796 IsTopNode = true;
4797 } else {
4798 do {
4799 if (BottomQ.empty()) return nullptr;
4800 SU = BottomQ.top();
4801 BottomQ.pop();
4802 } while (SU->isScheduled);
4803 IsTopNode = false;
4804 }
4805 if (IsAlternating)
4806 IsTopDown = !IsTopDown;
4807 return SU;
4808 }
4809
4810 void schedNode(SUnit *SU, bool IsTopNode) override {}
4811
4812 void releaseTopNode(SUnit *SU) override {
4813 TopQ.push(SU);
4814 }
4815 void releaseBottomNode(SUnit *SU) override {
4816 BottomQ.push(SU);
4817 }
4818};
4819
4820} // end anonymous namespace
4821
4823 bool Alternate =
4825 bool TopDown = PreRADirection != MISched::BottomUp;
4826 return new ScheduleDAGMILive(
4827 C, std::make_unique<InstructionShuffler>(Alternate, TopDown));
4828}
4829
4831 "shuffle", "Shuffle machine instructions alternating directions",
4833#endif // !NDEBUG
4834
4835//===----------------------------------------------------------------------===//
4836// GraphWriter support for ScheduleDAGMILive.
4837//===----------------------------------------------------------------------===//
4838
4839#ifndef NDEBUG
4840
4841template <>
4844
4845template <>
4848
4849 static std::string getGraphName(const ScheduleDAG *G) {
4850 return std::string(G->MF.getName());
4851 }
4852
4854 return true;
4855 }
4856
4857 static bool isNodeHidden(const SUnit *Node, const ScheduleDAG *G) {
4858 if (ViewMISchedCutoff == 0)
4859 return false;
4860 return (Node->Preds.size() > ViewMISchedCutoff
4861 || Node->Succs.size() > ViewMISchedCutoff);
4862 }
4863
4864 /// If you want to override the dot attributes printed for a particular
4865 /// edge, override this method.
4866 static std::string getEdgeAttributes(const SUnit *Node,
4867 SUnitIterator EI,
4868 const ScheduleDAG *Graph) {
4869 if (EI.isArtificialDep())
4870 return "color=cyan,style=dashed";
4871 if (EI.isCtrlDep())
4872 return "color=blue,style=dashed";
4873 return "";
4874 }
4875
4876 static std::string getNodeLabel(const SUnit *SU, const ScheduleDAG *G) {
4877 std::string Str;
4878 raw_string_ostream SS(Str);
4879 const ScheduleDAGMI *DAG = static_cast<const ScheduleDAGMI*>(G);
4880 const SchedDFSResult *DFS = DAG->hasVRegLiveness() ?
4881 static_cast<const ScheduleDAGMILive*>(G)->getDFSResult() : nullptr;
4882 SS << "SU:" << SU->NodeNum;
4883 if (DFS)
4884 SS << " I:" << DFS->getNumInstrs(SU);
4885 return Str;
4886 }
4887
4888 static std::string getNodeDescription(const SUnit *SU, const ScheduleDAG *G) {
4889 return G->getGraphNodeLabel(SU);
4890 }
4891
4892 static std::string getNodeAttributes(const SUnit *N, const ScheduleDAG *G) {
4893 std::string Str("shape=Mrecord");
4894 const ScheduleDAGMI *DAG = static_cast<const ScheduleDAGMI*>(G);
4895 const SchedDFSResult *DFS = DAG->hasVRegLiveness() ?
4896 static_cast<const ScheduleDAGMILive*>(G)->getDFSResult() : nullptr;
4897 if (DFS) {
4898 Str += ",style=filled,fillcolor=\"#";
4899 Str += DOT::getColorString(DFS->getSubtreeID(N));
4900 Str += '"';
4901 }
4902 return Str;
4903 }
4904};
4905
4906#endif // NDEBUG
4907
4908/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
4909/// rendered using 'dot'.
4910void ScheduleDAGMI::viewGraph(const Twine &Name, const Twine &Title) {
4911#ifndef NDEBUG
4912 ViewGraph(this, Name, false, Title);
4913#else
4914 errs() << "ScheduleDAGMI::viewGraph is only available in debug builds on "
4915 << "systems with Graphviz or gv!\n";
4916#endif // NDEBUG
4917}
4918
4919/// Out-of-line implementation with no arguments is handy for gdb.
4921 viewGraph(getDAGName(), "Scheduling-Units Graph for " + getDAGName());
4922}
4923
4924/// Sort predicate for the intervals stored in an instance of
4925/// ResourceSegments. Intervals are always disjoint (no intersection
4926/// for any pairs of intervals), therefore we can sort the totality of
4927/// the intervals by looking only at the left boundary.
4930 return A.first < B.first;
4931}
4932
4933unsigned ResourceSegments::getFirstAvailableAt(
4934 unsigned CurrCycle, unsigned AcquireAtCycle, unsigned ReleaseAtCycle,
4935 std::function<ResourceSegments::IntervalTy(unsigned, unsigned, unsigned)>
4936 IntervalBuilder) const {
4937 assert(llvm::is_sorted(_Intervals, sortIntervals) &&
4938 "Cannot execute on an un-sorted set of intervals.");
4939
4940 // Zero resource usage is allowed by TargetSchedule.td but we do not construct
4941 // a ResourceSegment interval for that situation.
4942 if (AcquireAtCycle == ReleaseAtCycle)
4943 return CurrCycle;
4944
4945 unsigned RetCycle = CurrCycle;
4946 ResourceSegments::IntervalTy NewInterval =
4947 IntervalBuilder(RetCycle, AcquireAtCycle, ReleaseAtCycle);
4948 for (auto &Interval : _Intervals) {
4949 if (!intersects(NewInterval, Interval))
4950 continue;
4951
4952 // Move the interval right next to the top of the one it
4953 // intersects.
4954 assert(Interval.second > NewInterval.first &&
4955 "Invalid intervals configuration.");
4956 RetCycle += (unsigned)Interval.second - (unsigned)NewInterval.first;
4957 NewInterval = IntervalBuilder(RetCycle, AcquireAtCycle, ReleaseAtCycle);
4958 }
4959 return RetCycle;
4960}
4961
4963 const unsigned CutOff) {
4964 assert(A.first <= A.second && "Cannot add negative resource usage");
4965 assert(CutOff > 0 && "0-size interval history has no use.");
4966 // Zero resource usage is allowed by TargetSchedule.td, in the case that the
4967 // instruction needed the resource to be available but does not use it.
4968 // However, ResourceSegment represents an interval that is closed on the left
4969 // and open on the right. It is impossible to represent an empty interval when
4970 // the left is closed. Do not add it to Intervals.
4971 if (A.first == A.second)
4972 return;
4973
4974 assert(all_of(_Intervals,
4975 [&A](const ResourceSegments::IntervalTy &Interval) -> bool {
4976 return !intersects(A, Interval);
4977 }) &&
4978 "A resource is being overwritten");
4979 _Intervals.push_back(A);
4980
4981 sortAndMerge();
4982
4983 // Do not keep the full history of the intervals, just the
4984 // latest #CutOff.
4985 while (_Intervals.size() > CutOff)
4986 _Intervals.pop_front();
4987}
4988
4991 assert(A.first <= A.second && "Invalid interval");
4992 assert(B.first <= B.second && "Invalid interval");
4993
4994 // Share one boundary.
4995 if ((A.first == B.first) || (A.second == B.second))
4996 return true;
4997
4998 // full intersersect: [ *** ) B
4999 // [***) A
5000 if ((A.first > B.first) && (A.second < B.second))
5001 return true;
5002
5003 // right intersect: [ ***) B
5004 // [*** ) A
5005 if ((A.first > B.first) && (A.first < B.second) && (A.second > B.second))
5006 return true;
5007
5008 // left intersect: [*** ) B
5009 // [ ***) A
5010 if ((A.first < B.first) && (B.first < A.second) && (B.second > B.first))
5011 return true;
5012
5013 return false;
5014}
5015
5016void ResourceSegments::sortAndMerge() {
5017 if (_Intervals.size() <= 1)
5018 return;
5019
5020 // First sort the collection.
5021 _Intervals.sort(sortIntervals);
5022
5023 // can use next because I have at least 2 elements in the list
5024 auto next = std::next(std::begin(_Intervals));
5025 auto E = std::end(_Intervals);
5026 for (; next != E; ++next) {
5027 if (std::prev(next)->second >= next->first) {
5028 next->first = std::prev(next)->first;
5029 _Intervals.erase(std::prev(next));
5030 continue;
5031 }
5032 }
5033}
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
Function Alias Analysis false
static const Function * getParent(const Value *V)
basic Basic Alias true
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:686
static std::optional< ArrayRef< InsnRange >::iterator > intersects(const MachineInstr *StartMI, const MachineInstr *EndMI, ArrayRef< InsnRange > Ranges, const InstructionOrdering &Ordering)
Check if the instruction range [StartMI, EndMI] intersects any instruction range in Ranges.
This file defines the DenseMap class.
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
A common definition of LaneBitmask for use in TableGen and CodeGen.
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
static cl::opt< MISched::Direction > PostRADirection("misched-postra-direction", cl::Hidden, cl::desc("Post reg-alloc list scheduling direction"), cl::init(MISched::Unspecified), cl::values(clEnumValN(MISched::TopDown, "topdown", "Force top-down post reg-alloc list scheduling"), clEnumValN(MISched::BottomUp, "bottomup", "Force bottom-up post reg-alloc list scheduling"), clEnumValN(MISched::Bidirectional, "bidirectional", "Force bidirectional post reg-alloc list scheduling")))
static bool isSchedBoundary(MachineBasicBlock::iterator MI, MachineBasicBlock *MBB, MachineFunction *MF, const TargetInstrInfo *TII)
Return true of the given instruction should not be included in a scheduling region.
static MachineSchedRegistry ILPMaxRegistry("ilpmax", "Schedule bottom-up for max ILP", createILPMaxScheduler)
static cl::opt< bool > EnableMemOpCluster("misched-cluster", cl::Hidden, cl::desc("Enable memop clustering."), cl::init(true))
PostRA Machine Instruction Scheduler
static MachineBasicBlock::const_iterator nextIfDebug(MachineBasicBlock::const_iterator I, MachineBasicBlock::const_iterator End)
If this iterator is a debug value, increment until reaching the End or a non-debug instruction.
static const unsigned MinSubtreeSize
static cl::opt< bool > VerifyScheduling("verify-misched", cl::Hidden, cl::desc("Verify machine instrs before and after machine scheduling"))
static const unsigned InvalidCycle
static cl::opt< bool > MISchedSortResourcesInTrace("misched-sort-resources-in-trace", cl::Hidden, cl::init(true), cl::desc("Sort the resources printed in the dump trace"))
static cl::opt< bool > EnableCyclicPath("misched-cyclicpath", cl::Hidden, cl::desc("Enable cyclic critical path analysis."), cl::init(true))
static MachineBasicBlock::const_iterator priorNonDebug(MachineBasicBlock::const_iterator I, MachineBasicBlock::const_iterator Beg)
Decrement this iterator until reaching the top or a non-debug instr.
static cl::opt< MachineSchedRegistry::ScheduleDAGCtor, false, RegisterPassParser< MachineSchedRegistry > > MachineSchedOpt("misched", cl::init(&useDefaultMachineSched), cl::Hidden, cl::desc("Machine instruction scheduler to use"))
MachineSchedOpt allows command line selection of the scheduler.
static cl::opt< bool > EnableMachineSched("enable-misched", cl::desc("Enable the machine instruction scheduling pass."), cl::init(true), cl::Hidden)
static cl::opt< unsigned > MISchedCutoff("misched-cutoff", cl::Hidden, cl::desc("Stop scheduling after N instructions"), cl::init(~0U))
static cl::opt< unsigned > SchedOnlyBlock("misched-only-block", cl::Hidden, cl::desc("Only schedule this MBB#"))
static cl::opt< bool > EnableRegPressure("misched-regpressure", cl::Hidden, cl::desc("Enable register pressure scheduling."), cl::init(true))
static MachineSchedRegistry GenericSchedRegistry("converge", "Standard converging scheduler.", createConvergingSched)
static cl::opt< unsigned > HeaderColWidth("misched-dump-schedule-trace-col-header-width", cl::Hidden, cl::desc("Set width of the columns with " "the resources and schedule units"), cl::init(19))
static cl::opt< bool > ForceFastCluster("force-fast-cluster", cl::Hidden, cl::desc("Switch to fast cluster algorithm with the lost " "of some fusion opportunities"), cl::init(false))
static cl::opt< unsigned > FastClusterThreshold("fast-cluster-threshold", cl::Hidden, cl::desc("The threshold for fast cluster"), cl::init(1000))
static bool checkResourceLimit(unsigned LFactor, unsigned Count, unsigned Latency, bool AfterSchedNode)
Given a Count of resource usage and a Latency value, return true if a SchedBoundary becomes resource ...
static ScheduleDAGInstrs * createInstructionShuffler(MachineSchedContext *C)
static ScheduleDAGInstrs * useDefaultMachineSched(MachineSchedContext *C)
A dummy default scheduler factory indicates whether the scheduler is overridden on the command line.
static bool sortIntervals(const ResourceSegments::IntervalTy &A, const ResourceSegments::IntervalTy &B)
Sort predicate for the intervals stored in an instance of ResourceSegments.
static cl::opt< unsigned > ColWidth("misched-dump-schedule-trace-col-width", cl::Hidden, cl::desc("Set width of the columns showing resource booking."), cl::init(5))
static cl::opt< MISched::Direction > PreRADirection("misched-prera-direction", cl::Hidden, cl::desc("Pre reg-alloc list scheduling direction"), cl::init(MISched::Unspecified), cl::values(clEnumValN(MISched::TopDown, "topdown", "Force top-down pre reg-alloc list scheduling"), clEnumValN(MISched::BottomUp, "bottomup", "Force bottom-up pre reg-alloc list scheduling"), clEnumValN(MISched::Bidirectional, "bidirectional", "Force bidirectional pre reg-alloc list scheduling")))
static MachineSchedRegistry DefaultSchedRegistry("default", "Use the target's default scheduler choice.", useDefaultMachineSched)
static cl::opt< std::string > SchedOnlyFunc("misched-only-func", cl::Hidden, cl::desc("Only schedule this function"))
static const char * scheduleTableLegend
static ScheduleDAGInstrs * createConvergingSched(MachineSchedContext *C)
static cl::opt< bool > MischedDetailResourceBooking("misched-detail-resource-booking", cl::Hidden, cl::init(false), cl::desc("Show details of invoking getNextResoufceCycle."))
static cl::opt< unsigned > ViewMISchedCutoff("view-misched-cutoff", cl::Hidden, cl::desc("Hide nodes with more predecessor/successor than cutoff"))
In some situations a few uninteresting nodes depend on nearly all other nodes in the graph,...
static MachineSchedRegistry ShufflerRegistry("shuffle", "Shuffle machine instructions alternating directions", createInstructionShuffler)
static void tracePick(const SUnit *SU, const GenericSchedulerBase::CandReason Reason, const bool IsTop, const bool IsPostRA=false)
static cl::opt< bool > EnablePostRAMachineSched("enable-post-misched", cl::desc("Enable the post-ra machine instruction scheduling pass."), cl::init(true), cl::Hidden)
static void getSchedRegions(MachineBasicBlock *MBB, MBBRegionsVector &Regions, bool RegionsTopDown)
static cl::opt< unsigned > MIResourceCutOff("misched-resource-cutoff", cl::Hidden, cl::desc("Number of intervals to track"), cl::init(10))
static ScheduleDAGInstrs * createILPMaxScheduler(MachineSchedContext *C)
SmallVector< SchedRegion, 16 > MBBRegionsVector
static cl::opt< bool > MISchedDumpReservedCycles("misched-dump-reserved-cycles", cl::Hidden, cl::init(false), cl::desc("Dump resource usage at schedule boundary."))
static cl::opt< unsigned > ReadyListLimit("misched-limit", cl::Hidden, cl::desc("Limit ready list to N instructions"), cl::init(256))
Avoid quadratic complexity in unusually large basic blocks by limiting the size of the ready lists.
static cl::opt< bool > DumpCriticalPathLength("misched-dcpl", cl::Hidden, cl::desc("Print critical path length to stdout"))
static ScheduleDAGInstrs * createILPMinScheduler(MachineSchedContext *C)
static cl::opt< bool > MISchedDumpScheduleTrace("misched-dump-schedule-trace", cl::Hidden, cl::init(false), cl::desc("Dump resource usage at schedule boundary."))
static MachineSchedRegistry ILPMinRegistry("ilpmin", "Schedule bottom-up for min ILP", createILPMinScheduler)
Register const TargetRegisterInfo * TRI
std::pair< uint64_t, uint64_t > Interval
#define P(N)
FunctionAnalysisManager FAM
if(PassOpts->AAPipeline)
#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
This file defines the PriorityQueue class.
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
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
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
static const X86InstrFMA3Group Groups[]
Value * RHS
Class recording the (high level) value of a variable.
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
Definition APInt.h:78
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
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:278
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
reverse_iterator rend() const
Definition ArrayRef.h:133
size_t size() const
Get the array size.
Definition ArrayRef.h:141
reverse_iterator rbegin() const
Definition ArrayRef.h:132
bool test(unsigned Idx) const
Returns true if bit Idx is set.
Definition BitVector.h:482
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:778
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:782
iterator end()
Definition DenseMap.h:702
Register getReg() const
The EquivalenceClasses data structure is just a set of these.
This represents a collection of equivalence classes and supports three efficient operations: insert a...
iterator_range< member_iterator > members(const ECValue &ECV) const
member_iterator unionSets(const ElemTy &V1, const ElemTy &V2)
Merge the two equivalence sets for the specified values, inserting them if they do not already exist ...
void traceCandidate(const SchedCandidate &Cand)
LLVM_ABI void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone, SchedBoundary *OtherZone)
Set the CandPolicy given a scheduling zone given the current resources and latencies inside and outsi...
MachineSchedPolicy RegionPolicy
const TargetSchedModel * SchedModel
static const char * getReasonStr(GenericSchedulerBase::CandReason Reason)
const MachineSchedContext * Context
CandReason
Represent the type of SchedCandidate found within a single queue.
const TargetRegisterInfo * TRI
void checkAcyclicLatency()
Set IsAcyclicLatencyLimited if the acyclic path is longer than the cyclic critical path by more cycle...
SchedCandidate BotCand
Candidate last picked from Bot boundary.
SchedCandidate TopCand
Candidate last picked from Top boundary.
virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone) const
Apply a set of heuristics to a new candidate.
ScheduleDAGMILive * DAG
void dumpPolicy() const override
void initialize(ScheduleDAGMI *dag) override
Initialize the strategy after building the DAG for a new region.
void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, const RegPressureTracker &RPTracker, RegPressureTracker &TempTracker)
void registerRoots() override
Notify this strategy that all roots have been released (including those that depend on EntrySU or Exi...
void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned NumRegionInstrs) override
Initialize the per-region scheduling policy.
void reschedulePhysReg(SUnit *SU, bool isTop)
SUnit * pickNode(bool &IsTopNode) override
Pick the best node to balance the schedule. Implements MachineSchedStrategy.
void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, const RegPressureTracker &RPTracker, SchedCandidate &Candidate)
Pick the best candidate from the queue.
void schedNode(SUnit *SU, bool IsTopNode) override
Update the scheduler's state after scheduling a node.
SUnit * pickNodeBidirectional(bool &IsTopNode)
Pick the best candidate node from either the top or bottom queue.
bool getMemOperandsWithOffsetWidth(const MachineInstr &LdSt, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
Get the base register and byte offset of a load/store instr.
Itinerary data supplied by a subtarget to be used by a target.
LiveInterval - This class represents the liveness of a register, or stack slot.
MachineInstr * getInstructionFromIndex(SlotIndex index) const
Returns the instruction associated with the given index.
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
Result of a LiveRange query.
VNInfo * valueIn() const
Return the value that is live-in to the instruction.
Segments::iterator iterator
LiveQueryResult Query(SlotIndex Idx) const
Query Liveness at Idx.
VNInfo * getVNInfoBefore(SlotIndex Idx) const
getVNInfoBefore - Return the VNInfo that is live up to but not necessarily including Idx,...
iterator begin()
SlotIndex beginIndex() const
beginIndex - Return the lowest numbered slot covered.
SlotIndex endIndex() const
endNumber - return the maximum point of the range of the whole, exclusive.
bool isLocal(SlotIndex Start, SlotIndex End) const
True iff this segment is a single segment that lies between the specified boundaries,...
LLVM_ABI iterator find(SlotIndex Pos)
find - Return an iterator pointing to the first segment that ends after Pos, or end().
bool hasValue() const
static LocationSize precise(uint64_t Value)
MachineInstrBundleIterator< const MachineInstr > const_iterator
MachineInstrBundleIterator< MachineInstr > iterator
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
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.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream.
Representation of each machine instruction.
bool isCopy() const
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
Analysis pass that exposes the MachineLoopInfo for a machine function.
MachineOperand class - Representation of each machine instruction operand.
MachinePassRegistry - Track the registration of machine passes.
MachineSchedRegistry provides a selection of available machine instruction schedulers.
static LLVM_ABI MachinePassRegistry< ScheduleDAGCtor > Registry
ScheduleDAGInstrs *(*)(MachineSchedContext *) ScheduleDAGCtor
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI MachineSchedulerPass(const TargetMachine *TM)
void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned NumRegionInstrs) override
Optionally override the per-region scheduling policy.
virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand)
Apply a set of heuristics to a new candidate for PostRA scheduling.
void schedNode(SUnit *SU, bool IsTopNode) override
Called after ScheduleDAGMI has scheduled an instruction and updated scheduled/remaining flags in the ...
SchedCandidate BotCand
Candidate last picked from Bot boundary.
void pickNodeFromQueue(SchedBoundary &Zone, SchedCandidate &Cand)
void initialize(ScheduleDAGMI *Dag) override
Initialize the strategy after building the DAG for a new region.
SchedCandidate TopCand
Candidate last picked from Top boundary.
SUnit * pickNodeBidirectional(bool &IsTopNode)
Pick the best candidate node from either the top or bottom queue.
void registerRoots() override
Notify this strategy that all roots have been released (including those that depend on EntrySU or Exi...
SUnit * pickNode(bool &IsTopNode) override
Pick the next node to schedule.
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI PostMachineSchedulerPass(const TargetMachine *TM)
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
Capture a change in pressure for a single pressure set.
unsigned getPSetOrMax() const
unsigned getPSet() const
List of PressureChanges in order of increasing, unique PSetID.
LLVM_ABI void dump(const TargetRegisterInfo &TRI) const
LLVM_ABI void addPressureChange(VirtRegOrUnit VRegOrUnit, bool IsDec, const MachineRegisterInfo *MRI)
Add a change in pressure to the pressure diff of a given instruction.
void clear()
clear - Erase all elements from the queue.
Helpers for implementing custom MachineSchedStrategy classes.
ArrayRef< SUnit * > elements()
LLVM_ABI void dump() const
std::vector< SUnit * >::iterator iterator
StringRef getName() const
Track the current register pressure at some position in the instruction stream, and remember the high...
LLVM_ABI void getMaxUpwardPressureDelta(const MachineInstr *MI, PressureDiff *PDiff, RegPressureDelta &Delta, ArrayRef< PressureChange > CriticalPSets, ArrayRef< unsigned > MaxPressureLimit)
Consider the pressure increase caused by traversing this instruction bottom-up.
LLVM_ABI void getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, ArrayRef< PressureChange > CriticalPSets, ArrayRef< unsigned > MaxPressureLimit)
Consider the pressure increase caused by traversing this instruction top-down.
LLVM_ABI void getUpwardPressureDelta(const MachineInstr *MI, PressureDiff &PDiff, RegPressureDelta &Delta, ArrayRef< PressureChange > CriticalPSets, ArrayRef< unsigned > MaxPressureLimit) const
This is the fast version of querying register pressure that does not directly depend on current liven...
List of registers defined and used by a machine instruction.
LLVM_ABI void detectDeadDefs(const MachineInstr &MI, const LiveIntervals &LIS, const MachineRegisterInfo &MRI)
Use liveness information to find dead defs at MI's dead slot not marked with a dead flag and move the...
LLVM_ABI void adjustLaneLiveness(const LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos)
Use liveness information to find out which uses/defs are partially undefined/dead at Pos and adjust t...
LLVM_ABI void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, bool TrackLaneMasks, bool IgnoreDead)
Analyze the given instruction MI and fill in the Uses, Defs and DeadDefs list based on the MachineOpe...
RegisterPassParser class - Handle the addition of new machine passes.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
LLVM_ABI void add(IntervalTy A, const unsigned CutOff=10)
Adds an interval [a, b) to the collection of the instance.
static IntervalTy getResourceIntervalBottom(unsigned C, unsigned AcquireAtCycle, unsigned ReleaseAtCycle)
These function return the interval used by a resource in bottom and top scheduling.
static LLVM_ABI bool intersects(IntervalTy A, IntervalTy B)
Checks whether intervals intersect.
std::pair< int64_t, int64_t > IntervalTy
Represents an interval of discrete integer values closed on the left and open on the right: [a,...
static IntervalTy getResourceIntervalTop(unsigned C, unsigned AcquireAtCycle, unsigned ReleaseAtCycle)
Scheduling dependency.
Definition ScheduleDAG.h:53
SUnit * getSUnit() const
Kind getKind() const
Returns an enum value representing the kind of the dependence.
@ Anti
A register anti-dependence (aka WAR).
Definition ScheduleDAG.h:58
@ Data
Regular data dependence (aka true-dependence).
Definition ScheduleDAG.h:57
bool isWeak() const
Tests if this a weak dependence.
@ Cluster
Weak DAG edge linking a chain of clustered instrs.
Definition ScheduleDAG.h:78
@ Artificial
Arbitrary strong DAG edge (no real dependence).
Definition ScheduleDAG.h:76
@ Weak
Arbitrary weak DAG edge.
Definition ScheduleDAG.h:77
unsigned getLatency() const
Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
Register getReg() const
Returns the register associated with this edge.
bool isArtificialDep() const
bool isCtrlDep() const
Tests if this is not an SDep::Data dependence.
Scheduling unit. This is a node in the scheduling DAG.
bool isCall
Is a function call.
unsigned TopReadyCycle
Cycle relative to start when node is ready.
unsigned NodeNum
Entry # of node in the node vector.
unsigned NumSuccsLeft
bool isUnbuffered
Uses an unbuffered resource.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
unsigned short Latency
Node latency.
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 ParentClusterIdx
The parent cluster id.
unsigned NumPredsLeft
bool hasPhysRegDefs
Has physreg defs that are being used.
unsigned BotReadyCycle
Cycle relative to end when node is ready.
SmallVector< SDep, 4 > Succs
All sunit successors.
bool hasReservedResource
Uses a reserved resource.
unsigned WeakPredsLeft
bool isBottomReady() const
bool hasPhysRegUses
Has physreg uses.
bool isTopReady() const
SmallVector< SDep, 4 > Preds
All sunit predecessors.
unsigned WeakSuccsLeft
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
Each Scheduling boundary is associated with ready queues.
LLVM_ABI unsigned getNextResourceCycleByInstance(unsigned InstanceIndex, unsigned ReleaseAtCycle, unsigned AcquireAtCycle)
Compute the next cycle at which the given processor resource unit can be scheduled.
LLVM_ABI void releasePending()
Release pending ready nodes in to the available queue.
unsigned getDependentLatency() const
bool isReservedGroup(unsigned PIdx) const
unsigned getScheduledLatency() const
Get the number of latency cycles "covered" by the scheduled instructions.
LLVM_ABI void incExecutedResources(unsigned PIdx, unsigned Count)
bool isResourceLimited() const
const TargetSchedModel * SchedModel
unsigned getExecutedCount() const
Get a scaled count for the minimum execution time of the scheduled micro-ops that are ready to execut...
LLVM_ABI unsigned getLatencyStallCycles(SUnit *SU)
Get the difference between the given SUnit's ready time and the current cycle.
LLVM_ABI unsigned findMaxLatency(ArrayRef< SUnit * > ReadySUs)
LLVM_ABI void dumpReservedCycles() const
Dump the state of the information that tracks resource usage.
LLVM_ABI unsigned getOtherResourceCount(unsigned &OtherCritIdx)
SchedRemainder * Rem
LLVM_ABI void bumpNode(SUnit *SU)
Move the boundary of scheduled code by one SUnit.
unsigned getCriticalCount() const
Get the scaled count of scheduled micro-ops and resources, including executed resources.
LLVM_ABI SUnit * pickOnlyChoice()
Call this before applying any other heuristics to the Available queue.
LLVM_ABI void releaseNode(SUnit *SU, unsigned ReadyCycle, bool InPQueue, unsigned Idx=0)
Release SU to make it ready.
LLVM_ABI unsigned countResource(const MCSchedClassDesc *SC, unsigned PIdx, unsigned Cycles, unsigned ReadyCycle, unsigned StartAtCycle)
Add the given processor resource to this scheduled zone.
LLVM_ABI ~SchedBoundary()
LLVM_ABI void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, SchedRemainder *rem)
unsigned getResourceCount(unsigned ResIdx) const
LLVM_ABI void bumpCycle(unsigned NextCycle)
Move the boundary of scheduled code by one cycle.
unsigned getCurrMOps() const
Micro-ops issued in the current cycle.
unsigned getCurrCycle() const
Number of cycles to issue the instructions scheduled in this zone.
std::unique_ptr< ScheduleHazardRecognizer > HazardRec
LLVM_ABI bool checkHazard(SUnit *SU)
Does this SU have a hazard within the current instruction group.
LLVM_ABI std::pair< unsigned, unsigned > getNextResourceCycle(const MCSchedClassDesc *SC, unsigned PIdx, unsigned ReleaseAtCycle, unsigned AcquireAtCycle)
Compute the next cycle at which the given processor resource can be scheduled.
LLVM_ABI void dumpScheduledState() const
LLVM_ABI void removeReady(SUnit *SU)
Remove SU from the ready set for this boundary.
unsigned getZoneCritResIdx() const
unsigned getUnscheduledLatency(SUnit *SU) const
Compute the values of each DAG node for various metrics during DFS.
Definition ScheduleDFS.h:65
unsigned getNumInstrs(const SUnit *SU) const
Get the number of instructions in the given subtree and its children.
unsigned getSubtreeID(const SUnit *SU) const
Get the ID of the subtree the given DAG node belongs to.
ILPValue getILP(const SUnit *SU) const
Get the ILP value for a DAG node.
unsigned getSubtreeLevel(unsigned SubtreeID) const
Get the connection level of a subtree.
A ScheduleDAG for scheduling lists of MachineInstr.
SmallVector< ClusterInfo > & getClusters()
Returns the array of the clusters.
virtual void finishBlock()
Cleans up after scheduling in the given block.
MachineBasicBlock::iterator end() const
Returns an iterator to the bottom of the current scheduling region.
std::string getDAGName() const override
Returns a label for the region of code covered by the DAG.
MachineBasicBlock * BB
The block in which to insert instructions.
virtual void startBlock(MachineBasicBlock *BB)
Prepares to perform scheduling in the given block.
MachineBasicBlock::iterator RegionEnd
The end of the range to be scheduled.
const MCSchedClassDesc * getSchedClass(SUnit *SU) const
Resolves and cache a resolved scheduling class for an SUnit.
DbgValueVector DbgValues
Remember instruction that precedes DBG_VALUE.
bool addEdge(SUnit *SuccSU, const SDep &PredDep)
Add a DAG edge to the given SU with the given predecessor dependence data.
DumpDirection
The direction that should be used to dump the scheduled Sequence.
bool TrackLaneMasks
Whether lane masks should get tracked.
void dumpNode(const SUnit &SU) const override
bool IsReachable(SUnit *SU, SUnit *TargetSU)
IsReachable - Checks if SU is reachable from TargetSU.
MachineBasicBlock::iterator begin() const
Returns an iterator to the top of the current scheduling region.
void buildSchedGraph(AAResults *AA, RegPressureTracker *RPTracker=nullptr, PressureDiffs *PDiffs=nullptr, LiveIntervals *LIS=nullptr, bool TrackLaneMasks=false)
Builds SUnits for the current region.
SUnit * getSUnit(MachineInstr *MI) const
Returns an existing SUnit for this MI, or nullptr.
TargetSchedModel SchedModel
TargetSchedModel provides an interface to the machine model.
bool canAddEdge(SUnit *SuccSU, SUnit *PredSU)
True if an edge can be added from PredSU to SuccSU without creating a cycle.
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
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 dump() const override
void setDumpDirection(DumpDirection D)
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
void scheduleMI(SUnit *SU, bool IsTopNode)
Move an instruction and update register pressure.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
VReg2SUnitMultiMap VRegUses
Maps vregs to the SUnits of their uses in the current scheduling region.
void computeDFSResult()
Compute a DFSResult after DAG building is complete, and before any queue comparisons.
PressureDiff & getPressureDiff(const SUnit *SU)
SchedDFSResult * DFSResult
Information about DAG subtrees.
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
void initQueues(ArrayRef< SUnit * > TopRoots, ArrayRef< SUnit * > BotRoots)
Release ExitSU predecessors and setup scheduler queues.
RegPressureTracker BotRPTracker
void buildDAGWithRegPressure()
Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking enabled.
std::vector< PressureChange > RegionCriticalPSets
List of pressure sets that exceed the target's pressure limit before scheduling, listed in increasing...
void updateScheduledPressure(const SUnit *SU, const std::vector< unsigned > &NewMaxPressure)
unsigned computeCyclicCriticalPath()
Compute the cyclic critical path through the DAG.
void updatePressureDiffs(ArrayRef< VRegMaskOrUnit > LiveUses)
Update the PressureDiff array for liveness after scheduling this instruction.
RegisterClassInfo * RegClassInfo
const SchedDFSResult * getDFSResult() const
Return a non-null DFS result if the scheduling strategy initialized it.
RegPressureTracker RPTracker
bool ShouldTrackPressure
Register pressure in this region computed by initRegPressure.
void dump() const override
MachineBasicBlock::iterator LiveRegionEnd
RegPressureTracker TopRPTracker
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
void dumpSchedule() const
dump the scheduled Sequence.
std::unique_ptr< MachineSchedStrategy > SchedImpl
void startBlock(MachineBasicBlock *bb) override
Prepares to perform scheduling in the given block.
void releasePred(SUnit *SU, SDep *PredEdge)
ReleasePred - Decrement the NumSuccsLeft count of a predecessor.
void initQueues(ArrayRef< SUnit * > TopRoots, ArrayRef< SUnit * > BotRoots)
Release ExitSU predecessors and setup scheduler queues.
void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos)
Change the position of an instruction within the basic block and update live ranges and region bounda...
void releasePredecessors(SUnit *SU)
releasePredecessors - Call releasePred on each of SU's predecessors.
void postProcessDAG()
Apply each ScheduleDAGMutation step in order.
void dumpScheduleTraceTopDown() const
Print execution trace of the schedule top-down or bottom-up.
void schedule() override
Implement ScheduleDAGInstrs interface for scheduling a sequence of reorderable instructions.
void findRootsAndBiasEdges(SmallVectorImpl< SUnit * > &TopRoots, SmallVectorImpl< SUnit * > &BotRoots)
MachineBasicBlock::iterator CurrentBottom
The bottom of the unscheduled zone.
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs) override
Implement the ScheduleDAGInstrs interface for handling the next scheduling region.
LiveIntervals * getLIS() const
void viewGraph(const Twine &Name, const Twine &Title) override
viewGraph - Pop up a ghostview window with the reachable parts of the DAG rendered using 'dot'.
void viewGraph() override
Out-of-line implementation with no arguments is handy for gdb.
void releaseSucc(SUnit *SU, SDep *SuccEdge)
ReleaseSucc - Decrement the NumPredsLeft count of a successor.
void dumpScheduleTraceBottomUp() const
~ScheduleDAGMI() override
void finishBlock() override
Cleans up after scheduling in the given block.
void updateQueues(SUnit *SU, bool IsTopNode)
Update scheduler DAG and queues after scheduling an instruction.
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
MachineBasicBlock::iterator CurrentTop
The top of the unscheduled zone.
void releaseSuccessors(SUnit *SU)
releaseSuccessors - Call releaseSucc on each of SU's successors.
std::vector< std::unique_ptr< ScheduleDAGMutation > > Mutations
Ordered list of DAG postprocessing steps.
Mutate the DAG as a postpass after normal DAG building.
MachineRegisterInfo & MRI
Virtual/real register map.
std::vector< SUnit > SUnits
The scheduling units.
const TargetRegisterInfo * TRI
Target processor register info.
SUnit EntrySU
Special node for the region entry.
MachineFunction & MF
Machine function.
void dumpNodeAll(const SUnit &SU) const
SUnit ExitSU
Special node for the region exit.
static bool isSameInstr(SlotIndex A, SlotIndex B)
isSameInstr - Return true if A and B refer to the same instruction.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
std::reverse_iterator< const_iterator > const_reverse_iterator
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Register getReg() const
Information about stack frame layout on the target.
StackDirection getStackGrowthDirection() const
getStackGrowthDirection - Return the direction the stack grows
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
Target-Independent Code Generator Pass Configuration Options.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Provide an instruction scheduling machine model to CodeGen passes.
unsigned getMicroOpFactor() const
Multiply number of micro-ops by this factor to normalize it relative to other resources.
ProcResIter getWriteProcResEnd(const MCSchedClassDesc *SC) const
LLVM_ABI bool hasInstrSchedModel() const
Return true if this machine model includes an instruction-level scheduling model.
const MCWriteProcResEntry * ProcResIter
unsigned getResourceFactor(unsigned ResIdx) const
Multiply the number of units consumed for a resource by this factor to normalize it relative to other...
LLVM_ABI unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC=nullptr) const
Return the number of issue slots required for this MI.
unsigned getNumProcResourceKinds() const
Get the number of kinds of resources for this target.
ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const
virtual void overridePostRASchedPolicy(MachineSchedPolicy &Policy, const SchedRegion &Region) const
Override generic post-ra scheduling policy within a region.
virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, const SchedRegion &Region) const
Override generic scheduling policy within a region.
virtual bool enableMachineScheduler() const
True if the subtarget should run MachineScheduler after aggressive coalescing.
virtual bool enablePostRAMachineScheduler() const
True if the subtarget should run a machine scheduler after register allocation.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
VNInfo - Value Number Information.
SlotIndex def
The index of the defining instruction.
bool isPHIDef() const
Returns true if this value is defined by a PHI instruction (or was, PHI instructions may have been el...
Wrapper class representing a virtual register or register unit.
Definition Register.h:175
Base class for the machine scheduler classes.
void scheduleRegions(ScheduleDAGInstrs &Scheduler, bool FixKillFlags)
Main driver for both MachineScheduler and PostMachineScheduler.
Impl class for MachineScheduler.
void setMFAM(MachineFunctionAnalysisManager *MFAM)
void setLegacyPass(MachineFunctionPass *P)
bool run(MachineFunction &MF, const TargetMachine &TM, const RequiredAnalyses &Analyses)
ScheduleDAGInstrs * createMachineScheduler()
Instantiate a ScheduleDAGInstrs that will be owned by the caller.
Impl class for PostMachineScheduler.
bool run(MachineFunction &Func, const TargetMachine &TM, const RequiredAnalyses &Analyses)
void setMFAM(MachineFunctionAnalysisManager *MFAM)
ScheduleDAGInstrs * createPostMachineScheduler()
Instantiate a ScheduleDAGInstrs for PostRA scheduling that will be owned by the caller.
A raw_ostream that writes to an std::string.
Changed
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:165
LLVM_ABI StringRef getColorString(unsigned NodeNumber)
Get a color string for this node number.
void apply(Opt *O, const Mod &M, const Mods &... Ms)
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI int biasPhysReg(const SUnit *SU, bool isTop, bool BiasPRegsExtra=false)
Minimize physical register live ranges.
ScheduleDAGMILive * createSchedLive(MachineSchedContext *C)
Create the standard converging machine scheduler.
@ Offset
Definition DWP.cpp:577
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:360
void stable_sort(R &&Range)
Definition STLExtras.h:2132
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
LLVM_ABI unsigned getWeakLeft(const SUnit *SU, bool isTop)
FormattedString right_justify(StringRef Str, unsigned Width)
right_justify - add spaces before string so total output is Width characters.
Definition Format.h:130
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Printable PrintLaneMask(LaneBitmask LaneMask)
Create Printable object to print LaneBitmasks on a raw_ostream.
Definition LaneBitmask.h:92
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI char & MachineSchedulerID
MachineScheduler - This pass schedules machine instructions.
LLVM_ABI char & PostMachineSchedulerID
PostMachineScheduler - This pass schedules machine instructions postRA.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI bool tryPressure(const PressureChange &TryP, const PressureChange &CandP, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason, const TargetRegisterInfo *TRI, const MachineFunction &MF)
ScheduleDAGMI * createSchedPostRA(MachineSchedContext *C)
Create a generic scheduler with no vreg liveness or DAG mutation passes.
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
cl::opt< bool > ViewMISchedDAGs
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createStoreClusterDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
Definition STLExtras.h:1986
LLVM_ABI bool shouldVerifyScheduling()
Returns whether -verify-misched is set.
LLVM_ABI bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary &Zone)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr unsigned InvalidClusterId
@ Other
Any other memory.
Definition ModRef.h:68
FormattedString left_justify(StringRef Str, unsigned Width)
left_justify - append spaces after string so total output is Width characters.
Definition Format.h:123
bool isTheSameCluster(unsigned A, unsigned B)
Return whether the input cluster ID's are the same and valid.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
LLVM_ABI bool tryBiasPhysRegs(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary *Zone, bool BiasPRegsExtra)
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createLoadClusterDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
DWARFExpression::Operation Op
LLVM_ABI bool tryGreater(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
SmallPtrSet< SUnit *, 8 > ClusterInfo
Keep record of which SUnit are in the same cluster group.
void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, then cleanup.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI unsigned computeRemLatency(SchedBoundary &CurrZone)
Compute remaining latency.
LLVM_ABI void dumpRegSetPressure(ArrayRef< unsigned > SetPressure, const TargetRegisterInfo *TRI)
LLVM_ABI MISched::Direction getPreRADirection()
Returns -misched-prera-direction.
LLVM_ABI bool tryLess(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
Return true if this heuristic determines order.
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createCopyConstrainDAGMutation(const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
cl::opt< bool > PrintDAGs
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
static std::string getNodeDescription(const SUnit *SU, const ScheduleDAG *G)
static std::string getEdgeAttributes(const SUnit *Node, SUnitIterator EI, const ScheduleDAG *Graph)
If you want to override the dot attributes printed for a particular edge, override this method.
static std::string getGraphName(const ScheduleDAG *G)
static std::string getNodeLabel(const SUnit *SU, const ScheduleDAG *G)
static bool isNodeHidden(const SUnit *Node, const ScheduleDAG *G)
static std::string getNodeAttributes(const SUnit *N, const ScheduleDAG *G)
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
Policy for scheduling the next instruction in the candidate's zone.
Store the state used by GenericScheduler heuristics, required for the lifetime of one invocation of p...
void reset(const CandPolicy &NewPolicy)
LLVM_ABI void initResourceDelta(const ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
Status of an instruction's critical resource consumption.
static constexpr LaneBitmask getNone()
Definition LaneBitmask.h:81
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Definition MCSchedule.h:74
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
RegisterClassInfo * RegClassInfo
MachineBlockFrequencyInfo * MBFI
const MachineLoopInfo * MLI
const TargetMachine * TM
RegisterPressure computed within a region of instructions delimited by TopPos and BottomPos.
A region of an MBB for scheduling.
Summarize the unscheduled region.
LLVM_ABI void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
SmallVector< unsigned, 16 > RemainingCounts
An individual mapping from virtual register number to SUnit.