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