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