LLVM 24.0.0git
MachineScheduler.h
Go to the documentation of this file.
1//===- MachineScheduler.h - MachineInstr Scheduling Pass --------*- C++ -*-===//
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// This file provides an interface for customizing the standard MachineScheduler
10// pass. Note that the entire pass may be replaced as follows:
11//
12// <Target>TargetMachine::createPassConfig(PassManagerBase &PM) {
13// PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID);
14// ...}
15//
16// The MachineScheduler pass is only responsible for choosing the regions to be
17// scheduled. Targets can override the DAG builder and scheduler without
18// replacing the pass as follows:
19//
20// ScheduleDAGInstrs *<Target>TargetMachine::
21// createMachineScheduler(MachineSchedContext *C) {
22// return new CustomMachineScheduler(C);
23// }
24//
25// The default scheduler, ScheduleDAGMILive, builds the DAG and drives list
26// scheduling while updating the instruction stream, register pressure, and live
27// intervals. Most targets don't need to override the DAG builder and list
28// scheduler, but subtargets that require custom scheduling heuristics may
29// plugin an alternate MachineSchedStrategy. The strategy is responsible for
30// selecting the highest priority node from the list:
31//
32// ScheduleDAGInstrs *<Target>TargetMachine::
33// createMachineScheduler(MachineSchedContext *C) {
34// return new ScheduleDAGMILive(C, CustomStrategy(C));
35// }
36//
37// The DAG builder can also be customized in a sense by adding DAG mutations
38// that will run after DAG building and before list scheduling. DAG mutations
39// can adjust dependencies based on target-specific knowledge or add weak edges
40// to aid heuristics:
41//
42// ScheduleDAGInstrs *<Target>TargetMachine::
43// createMachineScheduler(MachineSchedContext *C) {
44// ScheduleDAGMI *DAG = createSchedLive(C);
45// DAG->addMutation(new CustomDAGMutation(...));
46// return DAG;
47// }
48//
49// A target that supports alternative schedulers can use the
50// MachineSchedRegistry to allow command line selection. This can be done by
51// implementing the following boilerplate:
52//
53// static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) {
54// return new CustomMachineScheduler(C);
55// }
56// static MachineSchedRegistry
57// SchedCustomRegistry("custom", "Run my target's custom scheduler",
58// createCustomMachineSched);
59//
60//
61// Finally, subtargets that don't need to implement custom heuristics but would
62// like to configure the GenericScheduler's policy for a given scheduler region,
63// including scheduling direction and register pressure tracking policy, can do
64// this:
65//
66// void <SubTarget>Subtarget::
67// overrideSchedPolicy(MachineSchedPolicy &Policy,
68// const SchedRegion &Region) const {
69// Policy.<Flag> = true;
70// }
71//
72//===----------------------------------------------------------------------===//
73
74#ifndef LLVM_CODEGEN_MACHINESCHEDULER_H
75#define LLVM_CODEGEN_MACHINESCHEDULER_H
76
77#include "llvm/ADT/APInt.h"
78#include "llvm/ADT/ArrayRef.h"
79#include "llvm/ADT/BitVector.h"
80#include "llvm/ADT/STLExtras.h"
82#include "llvm/ADT/StringRef.h"
83#include "llvm/ADT/Twine.h"
96#include <algorithm>
97#include <cassert>
99#include <list>
100#include <memory>
101#include <string>
102#include <vector>
103
104namespace llvm {
105namespace impl_detail {
106// FIXME: Remove these declarations once RegisterClassInfo is queryable as an
107// analysis.
111} // namespace impl_detail
112
113namespace MISched {
120} // namespace MISched
121
122/// Returns -misched-prera-direction.
124/// Returns whether -verify-misched is set.
126
127#ifndef NDEBUG
130#else
131LLVM_ABI extern const bool ViewMISchedDAGs;
132LLVM_ABI extern const bool PrintDAGs;
133#endif
134
135class AAResults;
136class LiveIntervals;
137class MachineFunction;
138class MachineInstr;
139class MachineLoopInfo;
140class RegisterClassInfo;
141class SchedDFSResult;
142class TargetInstrInfo;
143class TargetPassConfig;
144class TargetRegisterInfo;
145
146/// MachineSchedContext provides enough context from the MachineScheduler pass
147/// for the target to instantiate a scheduler.
163
164/// MachineSchedRegistry provides a selection of available machine instruction
165/// schedulers.
168 ScheduleDAGInstrs *(*)(MachineSchedContext *)> {
169public:
171
172 // RegisterPassParser requires a (misnamed) FunctionPassCtor type.
174
176
177 MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C)
179 Registry.Add(this);
180 }
181
182 ~MachineSchedRegistry() { Registry.Remove(this); }
183
184 // Accessors.
185 //
189
191 return (MachineSchedRegistry *)Registry.getList();
192 }
193
195 Registry.setListener(L);
196 }
197};
198
199class ScheduleDAGMI;
200
201/// Define a generic scheduling policy for targets that don't provide their own
202/// MachineSchedStrategy. This can be overriden for each scheduling region
203/// before building the DAG.
205 // Allow the scheduler to disable register pressure tracking.
207 /// Track LaneMasks to allow reordering of independent subregister writes
208 /// of the same vreg. \sa MachineSchedStrategy::shouldTrackLaneMasks()
210
211 // Allow the scheduler to force top-down or bottom-up scheduling. If neither
212 // is true, the scheduler runs in both directions and converges.
213 bool OnlyTopDown = false;
214 bool OnlyBottomUp = false;
215
216 // Disable heuristic that tries to fetch nodes from long dependency chains
217 // first.
219
220 // Compute DFSResult for use in scheduling heuristics.
221 bool ComputeDFSResult = false;
222
223 // If enabled, some extra cases of physreg defs will be biased towards user.
224 bool BiasPRegsExtra = false;
225
227};
228
229/// A region of an MBB for scheduling.
231 /// RegionBegin is the first instruction in the scheduling region, and
232 /// RegionEnd is either MBB->end() or the scheduling boundary after the
233 /// last instruction in the scheduling region. These iterators cannot refer
234 /// to instructions outside of the identified scheduling region because
235 /// those may be reordered before scheduling this region.
239
243};
244
245/// MachineSchedStrategy - Interface to the scheduling algorithm used by
246/// ScheduleDAGMI.
247///
248/// Initialization sequence:
249/// initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots
251 virtual void anchor();
252
253public:
254 virtual ~MachineSchedStrategy() = default;
255
256 /// Optionally override the per-region scheduling policy.
259 unsigned NumRegionInstrs) {}
260
261 virtual MachineSchedPolicy getPolicy() const { return {}; }
262 virtual void dumpPolicy() const {}
263
264 /// Check if pressure tracking is needed before building the DAG and
265 /// initializing this strategy. Called after initPolicy.
266 virtual bool shouldTrackPressure() const { return true; }
267
268 /// Returns true if lanemasks should be tracked. LaneMask tracking is
269 /// necessary to reorder independent subregister defs for the same vreg.
270 /// This has to be enabled in combination with shouldTrackPressure().
271 virtual bool shouldTrackLaneMasks() const { return false; }
272
273 // If this method returns true, handling of the scheduling regions
274 // themselves (in case of a scheduling boundary in MBB) will be done
275 // beginning with the topmost region of MBB.
276 virtual bool doMBBSchedRegionsTopDown() const { return false; }
277
278 /// Initialize the strategy after building the DAG for a new region.
279 virtual void initialize(ScheduleDAGMI *DAG) = 0;
280
281 /// Tell the strategy that MBB is about to be processed.
282 virtual void enterMBB(MachineBasicBlock *MBB) {};
283
284 /// Tell the strategy that current MBB is done.
285 virtual void leaveMBB() {};
286
287 /// Notify this strategy that all roots have been released (including those
288 /// that depend on EntrySU or ExitSU).
289 virtual void registerRoots() {}
290
291 /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to
292 /// schedule the node at the top of the unscheduled region. Otherwise it will
293 /// be scheduled at the bottom.
294 virtual SUnit *pickNode(bool &IsTopNode) = 0;
295
296 /// Scheduler callback to notify that a new subtree is scheduled.
297 virtual void scheduleTree(unsigned SubtreeID) {}
298
299 /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an
300 /// instruction and updated scheduled/remaining flags in the DAG nodes.
301 virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
302
303 /// When all predecessor dependencies have been resolved, free this node for
304 /// top-down scheduling.
305 virtual void releaseTopNode(SUnit *SU) = 0;
306
307 /// When all successor dependencies have been resolved, free this node for
308 /// bottom-up scheduling.
309 virtual void releaseBottomNode(SUnit *SU) = 0;
310};
311
312/// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply
313/// schedules machine instructions according to the given MachineSchedStrategy
314/// without much extra book-keeping. This is the common functionality between
315/// PreRA and PostRA MachineScheduler.
317protected:
321 std::unique_ptr<MachineSchedStrategy> SchedImpl;
322
323 /// Ordered list of DAG postprocessing steps.
324 std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
325
326 /// The top of the unscheduled zone.
328
329 /// The bottom of the unscheduled zone.
331
332#if LLVM_ENABLE_ABI_BREAKING_CHECKS
333 /// The number of instructions scheduled so far. Used to cut off the
334 /// scheduler at the point determined by misched-cutoff.
335 unsigned NumInstrsScheduled = 0;
336#endif
337
338public:
339 ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S,
340 bool RemoveKillFlags)
342 LIS(C->LIS), MBFI(C->MBFI), SchedImpl(std::move(S)) {}
343
344 // Provide a vtable anchor
345 ~ScheduleDAGMI() override;
346
347 /// If this method returns true, handling of the scheduling regions
348 /// themselves (in case of a scheduling boundary in MBB) will be done
349 /// beginning with the topmost region of MBB.
350 bool doMBBSchedRegionsTopDown() const override {
351 return SchedImpl->doMBBSchedRegionsTopDown();
352 }
353
354 // Returns LiveIntervals instance for use in DAG mutators and such.
355 LiveIntervals *getLIS() const { return LIS; }
356
357 /// Return true if this DAG supports VReg liveness and RegPressure.
358 virtual bool hasVRegLiveness() const { return false; }
359
360 /// Add a postprocessing step to the DAG builder.
361 /// Mutations are applied in the order that they are added after normal DAG
362 /// building and before MachineSchedStrategy initialization.
363 ///
364 /// ScheduleDAGMI takes ownership of the Mutation object.
365 void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
366 if (Mutation)
367 Mutations.push_back(std::move(Mutation));
368 }
369
372
373 /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
374 /// region. This covers all instructions in a block, while schedule() may only
375 /// cover a subset.
376 void enterRegion(MachineBasicBlock *bb,
379 unsigned regioninstrs) override;
380
381 /// Implement ScheduleDAGInstrs interface for scheduling a sequence of
382 /// reorderable instructions.
383 void schedule() override;
384
385 void startBlock(MachineBasicBlock *bb) override;
386 void finishBlock() override;
387
388 /// Change the position of an instruction within the basic block and update
389 /// live ranges and region boundary iterators.
390 void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
391
392 void viewGraph(const Twine &Name, const Twine &Title) override;
393 void viewGraph() override;
394
395protected:
396 // Top-Level entry points for the schedule() driver...
397
398 /// Apply each ScheduleDAGMutation step in order. This allows different
399 /// instances of ScheduleDAGMI to perform custom DAG postprocessing.
400 void postProcessDAG();
401
402 /// Release ExitSU predecessors and setup scheduler queues.
403 void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
404
405 /// Update scheduler DAG and queues after scheduling an instruction.
406 void updateQueues(SUnit *SU, bool IsTopNode);
407
408 /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
409 void placeDebugValues();
410
411 /// dump the scheduled Sequence.
412 void dumpSchedule() const;
413 /// Print execution trace of the schedule top-down or bottom-up.
414 void dumpScheduleTraceTopDown() const;
415 void dumpScheduleTraceBottomUp() const;
416
417 // Lesser helpers...
418 bool checkSchedLimit();
419
420 void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
421 SmallVectorImpl<SUnit*> &BotRoots);
422
423 void releaseSucc(SUnit *SU, SDep *SuccEdge);
424 void releaseSuccessors(SUnit *SU);
425 void releasePred(SUnit *SU, SDep *PredEdge);
426 void releasePredecessors(SUnit *SU);
427};
428
429/// ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules
430/// machine instructions while updating LiveIntervals and tracking regpressure.
432protected:
434
435 /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees
436 /// will be empty.
439
441
442 /// Maps vregs to the SUnits of their uses in the current scheduling region.
444
445 // Map each SU to its summary of pressure changes. This array is updated for
446 // liveness during bottom-up scheduling. Top-down scheduling may proceed but
447 // has no affect on the pressure diffs.
449
450 /// Register pressure in this region computed by initRegPressure.
455
456 /// List of pressure sets that exceed the target's pressure limit before
457 /// scheduling, listed in increasing set ID order. Each pressure set is paired
458 /// with its max pressure in the currently scheduled regions.
459 std::vector<PressureChange> RegionCriticalPSets;
460
461 /// The top of the unscheduled zone.
464
465 /// The bottom of the unscheduled zone.
468
469public:
471 std::unique_ptr<MachineSchedStrategy> S)
472 : ScheduleDAGMI(C, std::move(S), /*RemoveKillFlags=*/false),
475
476 ~ScheduleDAGMILive() override;
477
478 /// Return true if this DAG supports VReg liveness and RegPressure.
479 bool hasVRegLiveness() const override { return true; }
480
481 /// Return true if register pressure tracking is enabled.
483
484 /// Get current register pressure for the top scheduled instructions.
485 const IntervalPressure &getTopPressure() const { return TopPressure; }
487
488 /// Get current register pressure for the bottom scheduled instructions.
489 const IntervalPressure &getBotPressure() const { return BotPressure; }
491
492 /// Get register pressure for the entire scheduling region before scheduling.
493 const IntervalPressure &getRegPressure() const { return RegPressure; }
494
495 const std::vector<PressureChange> &getRegionCriticalPSets() const {
496 return RegionCriticalPSets;
497 }
498
500 return SUPressureDiffs[SU->NodeNum];
501 }
502 const PressureDiff &getPressureDiff(const SUnit *SU) const {
503 return SUPressureDiffs[SU->NodeNum];
504 }
505
506 /// Compute a DFSResult after DAG building is complete, and before any
507 /// queue comparisons.
508 void computeDFSResult();
509
510 /// Return a non-null DFS result if the scheduling strategy initialized it.
511 const SchedDFSResult *getDFSResult() const { return DFSResult; }
512
514
515 /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
516 /// region. This covers all instructions in a block, while schedule() may only
517 /// cover a subset.
518 void enterRegion(MachineBasicBlock *bb,
521 unsigned regioninstrs) override;
522
523 /// Implement ScheduleDAGInstrs interface for scheduling a sequence of
524 /// reorderable instructions.
525 void schedule() override;
526
527 /// Compute the cyclic critical path through the DAG.
528 unsigned computeCyclicCriticalPath();
529
530 void dump() const override;
531
532protected:
533 // Top-Level entry points for the schedule() driver...
534
535 /// Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking
536 /// enabled. This sets up three trackers. RPTracker will cover the entire DAG
537 /// region, TopTracker and BottomTracker will be initialized to the top and
538 /// bottom of the DAG region without covereing any unscheduled instruction.
539 void buildDAGWithRegPressure();
540
541 /// Release ExitSU predecessors and setup scheduler queues. Re-position
542 /// the Top RP tracker in case the region beginning has changed.
543 void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
544
545 /// Move an instruction and update register pressure.
546 void scheduleMI(SUnit *SU, bool IsTopNode);
547
548 // Lesser helpers...
549
550 void initRegPressure();
551
552 void updatePressureDiffs(ArrayRef<VRegMaskOrUnit> LiveUses);
553
554 void updateScheduledPressure(const SUnit *SU,
555 const std::vector<unsigned> &NewMaxPressure);
556
557 void collectVRegUses(SUnit &SU);
558};
559
560//===----------------------------------------------------------------------===//
561///
562/// Helpers for implementing custom MachineSchedStrategy classes. These take
563/// care of the book-keeping associated with list scheduling heuristics.
564///
565//===----------------------------------------------------------------------===//
566
567/// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience
568/// methods for pushing and removing nodes. ReadyQueue's are uniquely identified
569/// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in.
570///
571/// This is a convenience class that may be used by implementations of
572/// MachineSchedStrategy.
574 unsigned ID;
575 std::string Name;
576 std::vector<SUnit*> Queue;
577
578public:
579 ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {}
580
581 unsigned getID() const { return ID; }
582
583 StringRef getName() const { return Name; }
584
585 // SU is in this queue if it's NodeQueueID is a superset of this ID.
586 bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); }
587
588 bool empty() const { return Queue.empty(); }
589
590 void clear() { Queue.clear(); }
591
592 unsigned size() const { return Queue.size(); }
593
594 using iterator = std::vector<SUnit*>::iterator;
595
596 iterator begin() { return Queue.begin(); }
597
598 iterator end() { return Queue.end(); }
599
600 ArrayRef<SUnit*> elements() { return Queue; }
601
602 iterator find(SUnit *SU) { return llvm::find(Queue, SU); }
603
604 void push(SUnit *SU) {
605 Queue.push_back(SU);
606 SU->NodeQueueId |= ID;
607 }
608
610 (*I)->NodeQueueId &= ~ID;
611 *I = Queue.back();
612 unsigned idx = I - Queue.begin();
613 Queue.pop_back();
614 return Queue.begin() + idx;
615 }
616
617 LLVM_ABI void dump() const;
618};
619
620/// Summarize the unscheduled region.
622 // Critical path through the DAG in expected latency.
623 unsigned CriticalPath;
625
626 // Scaled count of micro-ops left to schedule.
628
630
631 // Unscheduled resources
633
635
636 void reset() {
637 CriticalPath = 0;
638 CyclicCritPath = 0;
639 RemIssueCount = 0;
641 RemainingCounts.clear();
642 }
643
644 LLVM_ABI void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel);
645};
646
647/// ResourceSegments are a collection of intervals closed on the
648/// left and opened on the right:
649///
650/// list{ [a1, b1), [a2, b2), ..., [a_N, b_N) }
651///
652/// The collection has the following properties:
653///
654/// 1. The list is ordered: a_i < b_i and b_i < a_(i+1)
655///
656/// 2. The intervals in the collection do not intersect each other.
657///
658/// A \ref ResourceSegments instance represents the cycle
659/// reservation history of the instance of and individual resource.
661public:
662 /// Represents an interval of discrete integer values closed on
663 /// the left and open on the right: [a, b).
664 typedef std::pair<int64_t, int64_t> IntervalTy;
665
666 /// Adds an interval [a, b) to the collection of the instance.
667 ///
668 /// When adding [a, b[ to the collection, the operation merges the
669 /// adjacent intervals. For example
670 ///
671 /// 0 1 2 3 4 5 6 7 8 9 10
672 /// [-----) [--) [--)
673 /// + [--)
674 /// = [-----------) [--)
675 ///
676 /// To be able to debug duplicate resource usage, the function has
677 /// assertion that checks that no interval should be added if it
678 /// overlaps any of the intervals in the collection. We can
679 /// require this because by definition a \ref ResourceSegments is
680 /// attached only to an individual resource instance.
681 LLVM_ABI void add(IntervalTy A, const unsigned CutOff = 10);
682
683public:
684 /// Checks whether intervals intersect.
686
687 /// These function return the interval used by a resource in bottom and top
688 /// scheduling.
689 ///
690 /// Consider an instruction that uses resources X0, X1 and X2 as follows:
691 ///
692 /// X0 X1 X1 X2 +--------+-------------+--------------+
693 /// |Resource|AcquireAtCycle|ReleaseAtCycle|
694 /// +--------+-------------+--------------+
695 /// | X0 | 0 | 1 |
696 /// +--------+-------------+--------------+
697 /// | X1 | 1 | 3 |
698 /// +--------+-------------+--------------+
699 /// | X2 | 3 | 4 |
700 /// +--------+-------------+--------------+
701 ///
702 /// If we can schedule the instruction at cycle C, we need to
703 /// compute the interval of the resource as follows:
704 ///
705 /// # TOP DOWN SCHEDULING
706 ///
707 /// Cycles scheduling flows to the _right_, in the same direction
708 /// of time.
709 ///
710 /// C 1 2 3 4 5 ...
711 /// ------|------|------|------|------|------|----->
712 /// X0 X1 X1 X2 ---> direction of time
713 /// X0 [C, C+1)
714 /// X1 [C+1, C+3)
715 /// X2 [C+3, C+4)
716 ///
717 /// Therefore, the formula to compute the interval for a resource
718 /// of an instruction that can be scheduled at cycle C in top-down
719 /// scheduling is:
720 ///
721 /// [C+AcquireAtCycle, C+ReleaseAtCycle)
722 ///
723 ///
724 /// # BOTTOM UP SCHEDULING
725 ///
726 /// Cycles scheduling flows to the _left_, in opposite direction
727 /// of time.
728 ///
729 /// In bottom up scheduling, the scheduling happens in opposite
730 /// direction to the execution of the cycles of the
731 /// instruction. When the instruction is scheduled at cycle `C`,
732 /// the resources are allocated in the past relative to `C`:
733 ///
734 /// 2 1 C -1 -2 -3 -4 -5 ...
735 /// <-----|------|------|------|------|------|------|------|---
736 /// X0 X1 X1 X2 ---> direction of time
737 /// X0 (C+1, C]
738 /// X1 (C, C-2]
739 /// X2 (C-2, C-3]
740 ///
741 /// Therefore, the formula to compute the interval for a resource
742 /// of an instruction that can be scheduled at cycle C in bottom-up
743 /// scheduling is:
744 ///
745 /// [C-ReleaseAtCycle+1, C-AcquireAtCycle+1)
746 ///
747 ///
748 /// NOTE: In both cases, the number of cycles booked by a
749 /// resources is the value (ReleaseAtCycle - AcquireAtCycle).
750 static IntervalTy getResourceIntervalBottom(unsigned C, unsigned AcquireAtCycle,
751 unsigned ReleaseAtCycle) {
752 return std::make_pair<long, long>((long)C - (long)ReleaseAtCycle + 1L,
753 (long)C - (long)AcquireAtCycle + 1L);
754 }
755 static IntervalTy getResourceIntervalTop(unsigned C, unsigned AcquireAtCycle,
756 unsigned ReleaseAtCycle) {
757 return std::make_pair<long, long>((long)C + (long)AcquireAtCycle,
758 (long)C + (long)ReleaseAtCycle);
759 }
760
761private:
762 /// Finds the first cycle in which a resource can be allocated.
763 ///
764 /// The function uses the \param IntervalBuider [*] to build a
765 /// resource interval [a, b[ out of the input parameters \param
766 /// CurrCycle, \param AcquireAtCycle and \param ReleaseAtCycle.
767 ///
768 /// The function then loops through the intervals in the ResourceSegments
769 /// and shifts the interval [a, b[ and the ReturnCycle to the
770 /// right until there is no intersection between the intervals of
771 /// the \ref ResourceSegments instance and the new shifted [a, b[. When
772 /// this condition is met, the ReturnCycle (which
773 /// correspond to the cycle in which the resource can be
774 /// allocated) is returned.
775 ///
776 /// c = CurrCycle in input
777 /// c 1 2 3 4 5 6 7 8 9 10 ... ---> (time
778 /// flow)
779 /// ResourceSegments... [---) [-------) [-----------)
780 /// c [1 3[ -> AcquireAtCycle=1, ReleaseAtCycle=3
781 /// ++c [1 3)
782 /// ++c [1 3)
783 /// ++c [1 3)
784 /// ++c [1 3)
785 /// ++c [1 3) ---> returns c
786 /// incremented by 5 (c+5)
787 ///
788 ///
789 /// Notice that for bottom-up scheduling the diagram is slightly
790 /// different because the current cycle c is always on the right
791 /// of the interval [a, b) (see \ref
792 /// `getResourceIntervalBottom`). This is because the cycle
793 /// increments for bottom-up scheduling moved in the direction
794 /// opposite to the direction of time:
795 ///
796 /// --------> direction of time.
797 /// XXYZZZ (resource usage)
798 /// --------> direction of top-down execution cycles.
799 /// <-------- direction of bottom-up execution cycles.
800 ///
801 /// Even though bottom-up scheduling moves against the flow of
802 /// time, the algorithm used to find the first free slot in between
803 /// intervals is the same as for top-down scheduling.
804 ///
805 /// [*] See \ref `getResourceIntervalTop` and
806 /// \ref `getResourceIntervalBottom` to see how such resource intervals
807 /// are built.
808 LLVM_ABI unsigned getFirstAvailableAt(
809 unsigned CurrCycle, unsigned AcquireAtCycle, unsigned ReleaseAtCycle,
810 std::function<IntervalTy(unsigned, unsigned, unsigned)> IntervalBuilder)
811 const;
812
813public:
814 /// getFirstAvailableAtFromBottom and getFirstAvailableAtFromTop
815 /// should be merged in a single function in which a function that
816 /// creates the `NewInterval` is passed as a parameter.
817 unsigned getFirstAvailableAtFromBottom(unsigned CurrCycle,
818 unsigned AcquireAtCycle,
819 unsigned ReleaseAtCycle) const {
820 return getFirstAvailableAt(CurrCycle, AcquireAtCycle, ReleaseAtCycle,
822 }
823 unsigned getFirstAvailableAtFromTop(unsigned CurrCycle,
824 unsigned AcquireAtCycle,
825 unsigned ReleaseAtCycle) const {
826 return getFirstAvailableAt(CurrCycle, AcquireAtCycle, ReleaseAtCycle,
828 }
829
830private:
831 std::list<IntervalTy> _Intervals;
832 /// Merge all adjacent intervals in the collection. For all pairs
833 /// of adjacient intervals, it performs [a, b) + [b, c) -> [a, c).
834 ///
835 /// Before performing the merge operation, the intervals are
836 /// sorted with \ref sort_predicate.
837 LLVM_ABI void sortAndMerge();
838
839public:
840 // constructor for empty set
841 explicit ResourceSegments() = default;
842 bool empty() const { return _Intervals.empty(); }
843 explicit ResourceSegments(const std::list<IntervalTy> &Intervals)
844 : _Intervals(Intervals) {
845 sortAndMerge();
846 }
847
848 friend bool operator==(const ResourceSegments &c1,
849 const ResourceSegments &c2) {
850 return c1._Intervals == c2._Intervals;
851 }
853 const ResourceSegments &Segments) {
854 os << "{ ";
855 for (auto p : Segments._Intervals)
856 os << "[" << p.first << ", " << p.second << "), ";
857 os << "}\n";
858 return os;
859 }
860};
861
862/// Each Scheduling boundary is associated with ready queues. It tracks the
863/// current cycle in the direction of movement, and maintains the state
864/// of "hazards" and other interlocks at the current cycle.
866public:
867 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
868 enum {
872 };
873
874 ScheduleDAGMI *DAG = nullptr;
875 const TargetSchedModel *SchedModel = nullptr;
876 SchedRemainder *Rem = nullptr;
877
880
881 std::unique_ptr<ScheduleHazardRecognizer> HazardRec;
882
883private:
884 /// True if the pending Q should be checked/updated before scheduling another
885 /// instruction.
886 bool CheckPending;
887
888 /// Number of cycles it takes to issue the instructions scheduled in this
889 /// zone. It is defined as: scheduled-micro-ops / issue-width + stalls.
890 /// See getStalls().
891 unsigned CurrCycle;
892
893 /// Micro-ops issued in the current cycle
894 unsigned CurrMOps;
895
896 /// MinReadyCycle - Cycle of the soonest available instruction.
897 unsigned MinReadyCycle;
898
899 // The expected latency of the critical path in this scheduled zone.
900 unsigned ExpectedLatency;
901
902 // The latency of dependence chains leading into this zone.
903 // For each node scheduled bottom-up: DLat = max DLat, N.Depth.
904 // For each cycle scheduled: DLat -= 1.
905 unsigned DependentLatency;
906
907 /// Count the scheduled (issued) micro-ops that can be retired by
908 /// time=CurrCycle assuming the first scheduled instr is retired at time=0.
909 unsigned RetiredMOps;
910
911 // Count scheduled resources that have been executed. Resources are
912 // considered executed if they become ready in the time that it takes to
913 // saturate any resource including the one in question. Counts are scaled
914 // for direct comparison with other resources. Counts can be compared with
915 // MOps * getMicroOpFactor and Latency * getLatencyFactor.
916 SmallVector<unsigned, 16> ExecutedResCounts;
917
918 /// Cache the max count for a single resource.
919 unsigned MaxExecutedResCount;
920
921 // Cache the critical resources ID in this scheduled zone.
922 unsigned ZoneCritResIdx;
923
924 // Is the scheduled region resource limited vs. latency limited.
925 bool IsResourceLimited;
926
927public:
928private:
929 /// Record how resources have been allocated across the cycles of
930 /// the execution.
931 std::map<unsigned, ResourceSegments> ReservedResourceSegments;
932 std::vector<unsigned> ReservedCycles;
933 /// For each PIdx, stores first index into ReservedResourceSegments that
934 /// corresponds to it.
935 ///
936 /// For example, consider the following 3 resources (ResourceCount =
937 /// 3):
938 ///
939 /// +------------+--------+
940 /// |ResourceName|NumUnits|
941 /// +------------+--------+
942 /// | X | 2 |
943 /// +------------+--------+
944 /// | Y | 3 |
945 /// +------------+--------+
946 /// | Z | 1 |
947 /// +------------+--------+
948 ///
949 /// In this case, the total number of resource instances is 6. The
950 /// vector \ref ReservedResourceSegments will have a slot for each instance.
951 /// The vector \ref ReservedCyclesIndex will track at what index the first
952 /// instance of the resource is found in the vector of \ref
953 /// ReservedResourceSegments:
954 ///
955 /// Indexes of instances in
956 /// ReservedResourceSegments
957 ///
958 /// 0 1 2 3 4 5
959 /// ReservedCyclesIndex[0] = 0; [X0, X1,
960 /// ReservedCyclesIndex[1] = 2; Y0, Y1, Y2
961 /// ReservedCyclesIndex[2] = 5; Z
962 SmallVector<unsigned, 16> ReservedCyclesIndex;
963
964 // For each PIdx, stores the resource group IDs of its subunits
965 SmallVector<APInt, 16> ResourceGroupSubUnitMasks;
966
967#if LLVM_ENABLE_ABI_BREAKING_CHECKS
968 // Remember the greatest possible stall as an upper bound on the number of
969 // times we should retry the pending queue because of a hazard.
970 unsigned MaxObservedStall;
971#endif
972
973public:
974 /// Pending queues extend the ready queues with the same ID and the
975 /// PendingFlag set.
976 SchedBoundary(unsigned ID, const Twine &Name):
977 Available(ID, Name+".A"), Pending(ID << LogMaxQID, Name+".P") {
978 reset();
979 }
980 SchedBoundary &operator=(const SchedBoundary &other) = delete;
981 SchedBoundary(const SchedBoundary &other) = delete;
983
984 LLVM_ABI void reset();
985
986 LLVM_ABI void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel,
987 SchedRemainder *rem);
988
989 bool isTop() const {
990 return Available.getID() == TopQID;
991 }
992
993 /// Number of cycles to issue the instructions scheduled in this zone.
994 unsigned getCurrCycle() const { return CurrCycle; }
995
996 /// Micro-ops issued in the current cycle
997 unsigned getCurrMOps() const { return CurrMOps; }
998
999 // The latency of dependence chains leading into this zone.
1000 unsigned getDependentLatency() const { return DependentLatency; }
1001
1002 /// Get the number of latency cycles "covered" by the scheduled
1003 /// instructions. This is the larger of the critical path within the zone
1004 /// and the number of cycles required to issue the instructions.
1005 unsigned getScheduledLatency() const {
1006 return std::max(ExpectedLatency, CurrCycle);
1007 }
1008
1009 unsigned getUnscheduledLatency(SUnit *SU) const {
1010 return isTop() ? SU->getHeight() : SU->getDepth();
1011 }
1012
1013 unsigned getResourceCount(unsigned ResIdx) const {
1014 return ExecutedResCounts[ResIdx];
1015 }
1016
1017 /// Get the scaled count of scheduled micro-ops and resources, including
1018 /// executed resources.
1019 unsigned getCriticalCount() const {
1020 if (!ZoneCritResIdx)
1021 return RetiredMOps * SchedModel->getMicroOpFactor();
1022 return getResourceCount(ZoneCritResIdx);
1023 }
1024
1025 /// Get a scaled count for the minimum execution time of the scheduled
1026 /// micro-ops that are ready to execute by getExecutedCount. Notice the
1027 /// feedback loop.
1028 unsigned getExecutedCount() const {
1029 return std::max(CurrCycle * SchedModel->getLatencyFactor(),
1030 MaxExecutedResCount);
1031 }
1032
1033 unsigned getZoneCritResIdx() const { return ZoneCritResIdx; }
1034
1035 // Is the scheduled region resource limited vs. latency limited.
1036 bool isResourceLimited() const { return IsResourceLimited; }
1037
1038 /// Get the difference between the given SUnit's ready time and the current
1039 /// cycle.
1040 LLVM_ABI unsigned getLatencyStallCycles(SUnit *SU);
1041
1042 LLVM_ABI unsigned getNextResourceCycleByInstance(unsigned InstanceIndex,
1043 unsigned ReleaseAtCycle,
1044 unsigned AcquireAtCycle);
1045
1046 LLVM_ABI std::pair<unsigned, unsigned>
1047 getNextResourceCycle(const MCSchedClassDesc *SC, unsigned PIdx,
1048 unsigned ReleaseAtCycle, unsigned AcquireAtCycle);
1049
1050 bool isReservedGroup(unsigned PIdx) const {
1051 return SchedModel->getProcResource(PIdx)->SubUnitsIdxBegin &&
1052 !SchedModel->getProcResource(PIdx)->BufferSize;
1053 }
1054
1055 LLVM_ABI bool checkHazard(SUnit *SU);
1056
1057 LLVM_ABI unsigned findMaxLatency(ArrayRef<SUnit *> ReadySUs);
1058
1059 LLVM_ABI unsigned getOtherResourceCount(unsigned &OtherCritIdx);
1060
1061 /// Release SU to make it ready. If it's not in hazard, remove it from
1062 /// pending queue (if already in) and push into available queue.
1063 /// Otherwise, push the SU into pending queue.
1064 ///
1065 /// @param SU The unit to be released.
1066 /// @param ReadyCycle Until which cycle the unit is ready.
1067 /// @param InPQueue Whether SU is already in pending queue.
1068 /// @param Idx Position offset in pending queue (if in it).
1069 LLVM_ABI void releaseNode(SUnit *SU, unsigned ReadyCycle, bool InPQueue,
1070 unsigned Idx = 0);
1071
1072 LLVM_ABI void bumpCycle(unsigned NextCycle);
1073
1074 LLVM_ABI void incExecutedResources(unsigned PIdx, unsigned Count);
1075
1076 LLVM_ABI unsigned countResource(const MCSchedClassDesc *SC, unsigned PIdx,
1077 unsigned Cycles, unsigned ReadyCycle,
1078 unsigned StartAtCycle);
1079
1080 LLVM_ABI void bumpNode(SUnit *SU);
1081
1082 LLVM_ABI void releasePending();
1083
1084 LLVM_ABI void removeReady(SUnit *SU);
1085
1086 /// Call this before applying any other heuristics to the Available queue.
1087 /// Updates the Available/Pending Q's if necessary and returns the single
1088 /// available instruction, or NULL if there are multiple candidates.
1090
1091 /// Dump the state of the information that tracks resource usage.
1092 LLVM_ABI void dumpReservedCycles() const;
1093 LLVM_ABI void dumpScheduledState() const;
1094};
1095
1096/// Base class for GenericScheduler. This class maintains information about
1097/// scheduling candidates based on TargetSchedModel making it easy to implement
1098/// heuristics for either preRA or postRA scheduling.
1100public:
1101 /// Represent the type of SchedCandidate found within a single queue.
1102 /// pickNodeBidirectional depends on these listed by decreasing priority.
1122
1123#ifndef NDEBUG
1124 static const char *getReasonStr(GenericSchedulerBase::CandReason Reason);
1125#endif
1126
1127 /// Policy for scheduling the next instruction in the candidate's zone.
1128 struct CandPolicy {
1129 bool ReduceLatency = false;
1130 unsigned ReduceResIdx = 0;
1131 unsigned DemandResIdx = 0;
1132
1133 CandPolicy() = default;
1134
1135 bool operator==(const CandPolicy &RHS) const {
1136 return ReduceLatency == RHS.ReduceLatency &&
1137 ReduceResIdx == RHS.ReduceResIdx &&
1138 DemandResIdx == RHS.DemandResIdx;
1139 }
1140 bool operator!=(const CandPolicy &RHS) const {
1141 return !(*this == RHS);
1142 }
1143 };
1144
1145 /// Status of an instruction's critical resource consumption.
1147 // Count critical resources in the scheduled region required by SU.
1148 unsigned CritResources = 0;
1149
1150 // Count critical resources from another region consumed by SU.
1151 unsigned DemandedResources = 0;
1152
1154
1155 bool operator==(const SchedResourceDelta &RHS) const {
1156 return CritResources == RHS.CritResources
1157 && DemandedResources == RHS.DemandedResources;
1158 }
1159 bool operator!=(const SchedResourceDelta &RHS) const {
1160 return !operator==(RHS);
1161 }
1162 };
1163
1164 /// Store the state used by GenericScheduler heuristics, required for the
1165 /// lifetime of one invocation of pickNode().
1168
1169 // The best SUnit candidate.
1171
1172 // The reason for this candidate.
1174
1175 // Whether this candidate should be scheduled at top/bottom.
1176 bool AtTop;
1177
1178 // Register pressure values for the best candidate.
1180
1181 // Critical resource consumption of the best candidate.
1183
1186
1187 void reset(const CandPolicy &NewPolicy) {
1188 Policy = NewPolicy;
1189 SU = nullptr;
1190 Reason = NoCand;
1191 AtTop = false;
1194 }
1195
1196 bool isValid() const { return SU; }
1197
1198 // Copy the status of another candidate without changing policy.
1200 assert(Best.Reason != NoCand && "uninitialized Sched candidate");
1201 SU = Best.SU;
1202 Reason = Best.Reason;
1203 AtTop = Best.AtTop;
1204 RPDelta = Best.RPDelta;
1205 ResDelta = Best.ResDelta;
1206 }
1207
1210 };
1211
1212protected:
1215 const TargetRegisterInfo *TRI = nullptr;
1216 unsigned TopIdx = 0;
1217 unsigned BotIdx = 0;
1218 unsigned NumRegionInstrs = 0;
1219
1221
1223
1225
1226 LLVM_ABI void setPolicy(CandPolicy &Policy, bool IsPostRA,
1227 SchedBoundary &CurrZone, SchedBoundary *OtherZone);
1228
1229 MachineSchedPolicy getPolicy() const override { return RegionPolicy; }
1230
1231#ifndef NDEBUG
1232 void traceCandidate(const SchedCandidate &Cand);
1233#endif
1234
1235private:
1236 bool shouldReduceLatency(const CandPolicy &Policy, SchedBoundary &CurrZone,
1237 bool ComputeRemLatency, unsigned &RemLatency) const;
1238};
1239
1240// Utility functions used by heuristics in tryCandidate().
1241LLVM_ABI unsigned computeRemLatency(SchedBoundary &CurrZone);
1242LLVM_ABI bool tryLess(int TryVal, int CandVal,
1243 GenericSchedulerBase::SchedCandidate &TryCand,
1244 GenericSchedulerBase::SchedCandidate &Cand,
1246LLVM_ABI bool tryGreater(int TryVal, int CandVal,
1247 GenericSchedulerBase::SchedCandidate &TryCand,
1248 GenericSchedulerBase::SchedCandidate &Cand,
1250LLVM_ABI bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand,
1251 GenericSchedulerBase::SchedCandidate &Cand,
1252 SchedBoundary &Zone);
1253LLVM_ABI bool tryPressure(const PressureChange &TryP,
1254 const PressureChange &CandP,
1255 GenericSchedulerBase::SchedCandidate &TryCand,
1256 GenericSchedulerBase::SchedCandidate &Cand,
1258 const TargetRegisterInfo *TRI,
1259 const MachineFunction &MF);
1260LLVM_ABI bool tryBiasPhysRegs(GenericSchedulerBase::SchedCandidate &TryCand,
1261 GenericSchedulerBase::SchedCandidate &Cand,
1262 SchedBoundary *Zone, bool BiasPRegsExtra);
1263LLVM_ABI unsigned getWeakLeft(const SUnit *SU, bool isTop);
1264LLVM_ABI int biasPhysReg(const SUnit *SU, bool isTop,
1265 bool BiasPRegsExtra = false);
1266
1267/// GenericScheduler shrinks the unscheduled zone using heuristics to balance
1268/// the schedule.
1270public:
1272 GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"),
1273 Bot(SchedBoundary::BotQID, "BotQ") {}
1274
1275 void initPolicy(MachineBasicBlock::iterator Begin,
1277 unsigned NumRegionInstrs) override;
1278
1279 void dumpPolicy() const override;
1280
1281 bool shouldTrackPressure() const override {
1282 return RegionPolicy.ShouldTrackPressure;
1283 }
1284
1285 bool shouldTrackLaneMasks() const override {
1286 return RegionPolicy.ShouldTrackLaneMasks;
1287 }
1288
1289 void initialize(ScheduleDAGMI *dag) override;
1290
1291 SUnit *pickNode(bool &IsTopNode) override;
1292
1293 void schedNode(SUnit *SU, bool IsTopNode) override;
1294
1295 void releaseTopNode(SUnit *SU) override {
1296 if (SU->isScheduled)
1297 return;
1298
1299 Top.releaseNode(SU, SU->TopReadyCycle, false);
1300 TopCand.SU = nullptr;
1301 }
1302
1303 void releaseBottomNode(SUnit *SU) override {
1304 if (SU->isScheduled)
1305 return;
1306
1307 Bot.releaseNode(SU, SU->BotReadyCycle, false);
1308 BotCand.SU = nullptr;
1309 }
1310
1311 void registerRoots() override;
1312
1313protected:
1315
1316 // State of the top and bottom scheduled instruction boundaries.
1319
1322
1323 /// Candidate last picked from Top boundary.
1325 /// Candidate last picked from Bot boundary.
1327
1328 void checkAcyclicLatency();
1329
1330 void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop,
1331 const RegPressureTracker &RPTracker,
1332 RegPressureTracker &TempTracker);
1333
1334 virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
1335 SchedBoundary *Zone) const;
1336
1337 SUnit *pickNodeBidirectional(bool &IsTopNode);
1338
1340 const CandPolicy &ZonePolicy,
1341 const RegPressureTracker &RPTracker,
1342 SchedCandidate &Candidate);
1343
1344 void reschedulePhysReg(SUnit *SU, bool isTop);
1345};
1346
1347/// PostGenericScheduler - Interface to the scheduling algorithm used by
1348/// ScheduleDAGMI.
1349///
1350/// Callbacks from ScheduleDAGMI:
1351/// initPolicy -> initialize(DAG) -> registerRoots -> pickNode ...
1353protected:
1354 ScheduleDAGMI *DAG = nullptr;
1357
1358 /// Candidate last picked from Top boundary.
1360 /// Candidate last picked from Bot boundary.
1362
1365
1366public:
1368 : GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"),
1369 Bot(SchedBoundary::BotQID, "BotQ") {}
1370
1371 ~PostGenericScheduler() override = default;
1372
1375 unsigned NumRegionInstrs) override;
1376
1377 /// PostRA scheduling does not track pressure.
1378 bool shouldTrackPressure() const override { return false; }
1379
1380 void initialize(ScheduleDAGMI *Dag) override;
1381
1382 void registerRoots() override;
1383
1384 SUnit *pickNode(bool &IsTopNode) override;
1385
1386 SUnit *pickNodeBidirectional(bool &IsTopNode);
1387
1388 void scheduleTree(unsigned SubtreeID) override {
1389 llvm_unreachable("PostRA scheduler does not support subtree analysis.");
1390 }
1391
1392 void schedNode(SUnit *SU, bool IsTopNode) override;
1393
1394 void releaseTopNode(SUnit *SU) override {
1395 if (SU->isScheduled)
1396 return;
1397 Top.releaseNode(SU, SU->TopReadyCycle, false);
1398 TopCand.SU = nullptr;
1399 }
1400
1401 void releaseBottomNode(SUnit *SU) override {
1402 if (SU->isScheduled)
1403 return;
1404 Bot.releaseNode(SU, SU->BotReadyCycle, false);
1405 BotCand.SU = nullptr;
1406 }
1407
1408protected:
1409 virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand);
1410
1411 void pickNodeFromQueue(SchedBoundary &Zone, SchedCandidate &Cand);
1412};
1413
1414/// If ReorderWhileClustering is set to true, no attempt will be made to
1415/// reduce reordering due to store clustering.
1416LLVM_ABI std::unique_ptr<ScheduleDAGMutation>
1417createLoadClusterDAGMutation(const TargetInstrInfo *TII,
1418 bool ReorderWhileClustering = false);
1419
1420/// If ReorderWhileClustering is set to true, no attempt will be made to
1421/// reduce reordering due to store clustering.
1422LLVM_ABI std::unique_ptr<ScheduleDAGMutation>
1423createStoreClusterDAGMutation(const TargetInstrInfo *TII,
1424 bool ReorderWhileClustering = false);
1425
1426LLVM_ABI std::unique_ptr<ScheduleDAGMutation>
1427createCopyConstrainDAGMutation(const TargetInstrInfo *TII);
1428
1429/// Create the standard converging machine scheduler. This will be used as the
1430/// default scheduler if the target does not set a default.
1431/// Adds default DAG mutations.
1432template <typename Strategy = GenericScheduler>
1434 ScheduleDAGMILive *DAG =
1435 new ScheduleDAGMILive(C, std::make_unique<Strategy>(C));
1436 // Register DAG post-processors.
1437 //
1438 // FIXME: extend the mutation API to allow earlier mutations to instantiate
1439 // data and pass it to later mutations. Have a single mutation that gathers
1440 // the interesting nodes in one pass.
1442 return DAG;
1443}
1444
1445/// Create a generic scheduler with no vreg liveness or DAG mutation passes.
1446template <typename Strategy = PostGenericScheduler>
1448 return new ScheduleDAGMI(C, std::make_unique<Strategy>(C),
1449 /*RemoveKillFlags=*/true);
1450}
1451
1453 : public OptionalPassInfoMixin<MachineSchedulerPass> {
1454 // FIXME: Remove this member once RegisterClassInfo is queryable as an
1455 // analysis.
1456 std::unique_ptr<impl_detail::MachineSchedulerImpl> Impl;
1457 const TargetMachine *TM;
1458
1459public:
1465};
1466
1468 : public OptionalPassInfoMixin<SSAMachineSchedulerPass> {
1469 // FIXME: Remove this member once RegisterClassInfo is queryable as an
1470 // analysis.
1471 std::unique_ptr<impl_detail::SSAMachineSchedulerImpl> Impl;
1472 const TargetMachine *TM;
1473
1474public:
1480};
1481
1483 : public OptionalPassInfoMixin<PostMachineSchedulerPass> {
1484 // FIXME: Remove this member once RegisterClassInfo is queryable as an
1485 // analysis.
1486 std::unique_ptr<impl_detail::PostMachineSchedulerImpl> Impl;
1487 const TargetMachine *TM;
1488
1489public:
1495};
1496} // end namespace llvm
1497
1498#endif // LLVM_CODEGEN_MACHINESCHEDULER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
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< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
PowerPC VSX FMA Mutation
This file contains some templates that are useful if you are working with the STL at all.
static const char * name
This file defines the SmallVector class.
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.
Value * RHS
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
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)
MachineSchedPolicy getPolicy() const override
GenericSchedulerBase(const MachineSchedContext *C)
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 releaseBottomNode(SUnit *SU) override
When all successor dependencies have been resolved, free this node for bottom-up scheduling.
void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop, const RegPressureTracker &RPTracker, RegPressureTracker &TempTracker)
bool shouldTrackPressure() const override
Check if pressure tracking is needed before building the DAG and initializing this strategy.
void releaseTopNode(SUnit *SU) override
When all predecessor dependencies have been resolved, free this node for top-down scheduling.
void reschedulePhysReg(SUnit *SU, bool isTop)
void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, const RegPressureTracker &RPTracker, SchedCandidate &Candidate)
Pick the best candidate from the queue.
bool shouldTrackLaneMasks() const override
Returns true if lanemasks should be tracked.
GenericScheduler(const MachineSchedContext *C)
SUnit * pickNodeBidirectional(bool &IsTopNode)
Pick the best candidate node from either the top or bottom queue.
MachineInstrBundleIterator< MachineInstr > iterator
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
Representation of each machine instruction.
MachinePassRegistryListener - Listener to adds and removals of nodes in registration list.
MachinePassRegistryNode(const char *N, const char *D, ScheduleDAGInstrs *C)
MachinePassRegistryNode * getNext() const
MachinePassRegistry - Track the registration of machine passes.
static void setListener(MachinePassRegistryListener< FunctionPassCtor > *L)
static LLVM_ABI MachinePassRegistry< ScheduleDAGCtor > Registry
MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C)
static MachineSchedRegistry * getList()
ScheduleDAGInstrs *(*)(MachineSchedContext *) ScheduleDAGCtor
MachineSchedRegistry * getNext() const
MachineSchedStrategy - Interface to the scheduling algorithm used by ScheduleDAGMI.
virtual bool shouldTrackPressure() const
Check if pressure tracking is needed before building the DAG and initializing this strategy.
virtual void leaveMBB()
Tell the strategy that current MBB is done.
virtual void enterMBB(MachineBasicBlock *MBB)
Tell the strategy that MBB is about to be processed.
virtual void scheduleTree(unsigned SubtreeID)
Scheduler callback to notify that a new subtree is scheduled.
virtual void schedNode(SUnit *SU, bool IsTopNode)=0
Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an instruction and updated scheduled/rem...
virtual ~MachineSchedStrategy()=default
virtual void initialize(ScheduleDAGMI *DAG)=0
Initialize the strategy after building the DAG for a new region.
virtual MachineSchedPolicy getPolicy() const
virtual void releaseTopNode(SUnit *SU)=0
When all predecessor dependencies have been resolved, free this node for top-down scheduling.
virtual void dumpPolicy() const
virtual bool doMBBSchedRegionsTopDown() const
virtual SUnit * pickNode(bool &IsTopNode)=0
Pick the next node to schedule, or return NULL.
virtual void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned NumRegionInstrs)
Optionally override the per-region scheduling policy.
virtual void releaseBottomNode(SUnit *SU)=0
When all successor dependencies have been resolved, free this node for bottom-up scheduling.
virtual bool shouldTrackLaneMasks() const
Returns true if lanemasks should be tracked.
virtual void registerRoots()
Notify this strategy that all roots have been released (including those that depend on EntrySU or Exi...
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI MachineSchedulerPass(const TargetMachine *TM)
LLVM_ABI MachineSchedulerPass(MachineSchedulerPass &&Other)
void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned NumRegionInstrs) override
Optionally override the per-region scheduling policy.
bool shouldTrackPressure() const override
PostRA scheduling does not track pressure.
void scheduleTree(unsigned SubtreeID) override
Scheduler callback to notify that a new subtree is scheduled.
SchedCandidate BotCand
Candidate last picked from Bot boundary.
SchedCandidate TopCand
Candidate last picked from Top boundary.
void releaseTopNode(SUnit *SU) override
When all predecessor dependencies have been resolved, free this node for top-down scheduling.
~PostGenericScheduler() override=default
void releaseBottomNode(SUnit *SU) override
When all successor dependencies have been resolved, free this node for bottom-up scheduling.
PostGenericScheduler(const MachineSchedContext *C)
LLVM_ABI PostMachineSchedulerPass(PostMachineSchedulerPass &&Other)
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
List of PressureChanges in order of increasing, unique PSetID.
Array of PressureDiffs.
Helpers for implementing custom MachineSchedStrategy classes.
void push(SUnit *SU)
iterator find(SUnit *SU)
ArrayRef< SUnit * > elements()
LLVM_ABI void dump() const
ReadyQueue(unsigned id, const Twine &name)
bool isInQueue(SUnit *SU) const
std::vector< SUnit * >::iterator iterator
StringRef getName() const
unsigned size() const
iterator remove(iterator I)
unsigned getID() const
Track the current register pressure at some position in the instruction stream, and remember the high...
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.
friend bool operator==(const ResourceSegments &c1, const ResourceSegments &c2)
static LLVM_ABI bool intersects(IntervalTy A, IntervalTy B)
Checks whether intervals intersect.
unsigned getFirstAvailableAtFromTop(unsigned CurrCycle, unsigned AcquireAtCycle, unsigned ReleaseAtCycle) const
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const ResourceSegments &Segments)
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)
ResourceSegments(const std::list< IntervalTy > &Intervals)
unsigned getFirstAvailableAtFromBottom(unsigned CurrCycle, unsigned AcquireAtCycle, unsigned ReleaseAtCycle) const
getFirstAvailableAtFromBottom and getFirstAvailableAtFromTop should be merged in a single function in...
Scheduling dependency.
Definition ScheduleDAG.h:54
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
LLVM_ABI SSAMachineSchedulerPass(SSAMachineSchedulerPass &&Other)
LLVM_ABI SSAMachineSchedulerPass(const TargetMachine *TM)
Scheduling unit. This is a node in the scheduling DAG.
unsigned NodeQueueId
Queue id of node.
unsigned TopReadyCycle
Cycle relative to start when node is ready.
unsigned NodeNum
Entry # of node in the node vector.
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 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 BotReadyCycle
Cycle relative to end when node is ready.
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.
SchedBoundary(const SchedBoundary &other)=delete
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.
SchedBoundary(unsigned ID, const Twine &Name)
Pending queues extend the ready queues with the same ID and the PendingFlag set.
LLVM_ABI ~SchedBoundary()
LLVM_ABI void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, SchedRemainder *rem)
SchedBoundary & operator=(const SchedBoundary &other)=delete
unsigned getResourceCount(unsigned ResIdx) const
LLVM_ABI void bumpCycle(unsigned NextCycle)
Move the boundary of scheduled code by one cycle.
unsigned getCurrMOps() const
Micro-ops issued in the current cycle.
unsigned getCurrCycle() const
Number of cycles to issue the instructions scheduled in this zone.
std::unique_ptr< ScheduleHazardRecognizer > HazardRec
LLVM_ABI bool checkHazard(SUnit *SU)
Does this SU have a hazard within the current instruction group.
LLVM_ABI std::pair< unsigned, unsigned > getNextResourceCycle(const MCSchedClassDesc *SC, unsigned PIdx, unsigned ReleaseAtCycle, unsigned AcquireAtCycle)
Compute the next cycle at which the given processor resource can be scheduled.
LLVM_ABI void dumpScheduledState() const
LLVM_ABI void removeReady(SUnit *SU)
Remove SU from the ready set for this boundary.
unsigned getZoneCritResIdx() const
unsigned getUnscheduledLatency(SUnit *SU) const
Compute the values of each DAG node for various metrics during DFS.
Definition ScheduleDFS.h:65
A ScheduleDAG for scheduling lists of MachineInstr.
ScheduleDAGInstrs(MachineFunction &mf, const MachineLoopInfo *mli, bool RemoveKillFlags=false)
const MachineLoopInfo * MLI
bool RemoveKillFlags
True if the DAG builder should remove kill flags (in preparation for rescheduling).
ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules machine instructions while...
VReg2SUnitMultiMap VRegUses
Maps vregs to the SUnits of their uses in the current scheduling region.
PressureDiff & getPressureDiff(const SUnit *SU)
SchedDFSResult * DFSResult
Information about DAG subtrees.
RegPressureTracker BotRPTracker
std::vector< PressureChange > RegionCriticalPSets
List of pressure sets that exceed the target's pressure limit before scheduling, listed in increasing...
IntervalPressure TopPressure
The top of the unscheduled zone.
const RegPressureTracker & getBotRPTracker() const
ScheduleDAGMILive(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S)
IntervalPressure BotPressure
The bottom of the unscheduled zone.
bool isTrackingPressure() const
Return true if register pressure tracking is enabled.
bool hasVRegLiveness() const override
Return true if this DAG supports VReg liveness and RegPressure.
RegisterClassInfo * RegClassInfo
const SchedDFSResult * getDFSResult() const
Return a non-null DFS result if the scheduling strategy initialized it.
const PressureDiff & getPressureDiff(const SUnit *SU) const
const RegPressureTracker & getTopRPTracker() const
RegPressureTracker RPTracker
bool ShouldTrackPressure
Register pressure in this region computed by initRegPressure.
const IntervalPressure & getRegPressure() const
Get register pressure for the entire scheduling region before scheduling.
const IntervalPressure & getBotPressure() const
Get current register pressure for the bottom scheduled instructions.
MachineBasicBlock::iterator LiveRegionEnd
const IntervalPressure & getTopPressure() const
Get current register pressure for the top scheduled instructions.
const std::vector< PressureChange > & getRegionCriticalPSets() const
IntervalPressure RegPressure
RegPressureTracker TopRPTracker
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
std::unique_ptr< MachineSchedStrategy > SchedImpl
void addMutation(std::unique_ptr< ScheduleDAGMutation > Mutation)
Add a postprocessing step to the DAG builder.
MachineBasicBlock::iterator top() const
ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr< MachineSchedStrategy > S, bool RemoveKillFlags)
MachineBasicBlock::iterator bottom() const
MachineBasicBlock::iterator CurrentBottom
The bottom of the unscheduled zone.
bool doMBBSchedRegionsTopDown() const override
If this method returns true, handling of the scheduling regions themselves (in case of a scheduling b...
virtual bool hasVRegLiveness() const
Return true if this DAG supports VReg liveness and RegPressure.
LiveIntervals * getLIS() const
~ScheduleDAGMI() override
MachineBasicBlock::iterator CurrentTop
The top of the unscheduled zone.
MachineBlockFrequencyInfo * MBFI
std::vector< std::unique_ptr< ScheduleDAGMutation > > Mutations
Ordered list of DAG postprocessing steps.
const TargetInstrInfo * TII
Target instruction information.
MachineFunction & MF
Machine function.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Primary interface to the complete machine description for the target machine.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Provide an instruction scheduling machine model to CodeGen passes.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
Impl class for MachineScheduler.
Impl class for PostMachineScheduler.
Impl class for SSAMachineScheduler.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
template class LLVM_TEMPLATE_ABI opt< bool >
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.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1781
LLVM_ABI unsigned getWeakLeft(const SUnit *SU, bool isTop)
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createLoadClusterDAGMutation(const TargetInstrInfo *TII, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createStoreClusterDAGMutation(const TargetInstrInfo *TII, bool ReorderWhileClustering=false)
If ReorderWhileClustering is set to true, no attempt will be made to reduce reordering due to store c...
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)
SparseMultiSet< VReg2SUnit, Register, VirtReg2IndexFunctor > VReg2SUnitMultiMap
Track local uses of virtual registers.
ScheduleDAGMI * createSchedPostRA(MachineSchedContext *C)
Create a generic scheduler with no vreg liveness or DAG mutation passes.
cl::opt< bool > ViewMISchedDAGs
LLVM_ABI bool shouldVerifyScheduling()
Returns whether -verify-misched is set.
LLVM_ABI bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary &Zone)
@ Other
Any other memory.
Definition ModRef.h:68
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 > createCopyConstrainDAGMutation(const TargetInstrInfo *TII)
LLVM_ABI bool tryGreater(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
LLVM_ABI unsigned computeRemLatency(SchedBoundary &CurrZone)
Compute remaining latency.
LLVM_ABI MISched::Direction getPreRADirection()
Returns -misched-prera-direction.
LLVM_ABI bool tryLess(int TryVal, int CandVal, GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, GenericSchedulerBase::CandReason Reason)
Return true if this heuristic determines order.
cl::opt< bool > PrintDAGs
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
Policy for scheduling the next instruction in the candidate's zone.
bool operator==(const CandPolicy &RHS) const
bool operator!=(const CandPolicy &RHS) const
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.
bool operator!=(const SchedResourceDelta &RHS) const
bool operator==(const SchedResourceDelta &RHS) const
RegisterPressure computed within a region of instructions delimited by TopIdx and BottomIdx.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
RegisterClassInfo * RegClassInfo
MachineBlockFrequencyInfo * MBFI
const MachineLoopInfo * MLI
const TargetMachine * TM
MachineSchedContext & operator=(const MachineSchedContext &other)=delete
MachineSchedContext(const MachineSchedContext &other)=delete
Define a generic scheduling policy for targets that don't provide their own MachineSchedStrategy.
bool ShouldTrackLaneMasks
Track LaneMasks to allow reordering of independent subregister writes of the same vreg.
A CRTP mix-in for passes that can be skipped.
Store the effects of a change in pressure on things that MI scheduler cares about.
MachineBasicBlock::iterator RegionBegin
RegionBegin is the first instruction in the scheduling region, and RegionEnd is either MBB->end() or ...
MachineBasicBlock::iterator RegionEnd
SchedRegion(MachineBasicBlock::iterator B, MachineBasicBlock::iterator E, unsigned N)
Summarize the unscheduled region.
LLVM_ABI void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel)
SmallVector< unsigned, 16 > RemainingCounts