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