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