xref: /aosp_15_r20/external/llvm/include/llvm/CodeGen/MachineScheduler.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //==- MachineScheduler.h - MachineInstr Scheduling Pass ----------*- C++ -*-==//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file provides an interface for customizing the standard MachineScheduler
11*9880d681SAndroid Build Coastguard Worker // pass. Note that the entire pass may be replaced as follows:
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker // <Target>TargetMachine::createPassConfig(PassManagerBase &PM) {
14*9880d681SAndroid Build Coastguard Worker //   PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID);
15*9880d681SAndroid Build Coastguard Worker //   ...}
16*9880d681SAndroid Build Coastguard Worker //
17*9880d681SAndroid Build Coastguard Worker // The MachineScheduler pass is only responsible for choosing the regions to be
18*9880d681SAndroid Build Coastguard Worker // scheduled. Targets can override the DAG builder and scheduler without
19*9880d681SAndroid Build Coastguard Worker // replacing the pass as follows:
20*9880d681SAndroid Build Coastguard Worker //
21*9880d681SAndroid Build Coastguard Worker // ScheduleDAGInstrs *<Target>PassConfig::
22*9880d681SAndroid Build Coastguard Worker // createMachineScheduler(MachineSchedContext *C) {
23*9880d681SAndroid Build Coastguard Worker //   return new CustomMachineScheduler(C);
24*9880d681SAndroid Build Coastguard Worker // }
25*9880d681SAndroid Build Coastguard Worker //
26*9880d681SAndroid Build Coastguard Worker // The default scheduler, ScheduleDAGMILive, builds the DAG and drives list
27*9880d681SAndroid Build Coastguard Worker // scheduling while updating the instruction stream, register pressure, and live
28*9880d681SAndroid Build Coastguard Worker // intervals. Most targets don't need to override the DAG builder and list
29*9880d681SAndroid Build Coastguard Worker // schedulier, but subtargets that require custom scheduling heuristics may
30*9880d681SAndroid Build Coastguard Worker // plugin an alternate MachineSchedStrategy. The strategy is responsible for
31*9880d681SAndroid Build Coastguard Worker // selecting the highest priority node from the list:
32*9880d681SAndroid Build Coastguard Worker //
33*9880d681SAndroid Build Coastguard Worker // ScheduleDAGInstrs *<Target>PassConfig::
34*9880d681SAndroid Build Coastguard Worker // createMachineScheduler(MachineSchedContext *C) {
35*9880d681SAndroid Build Coastguard Worker //   return new ScheduleDAGMI(C, CustomStrategy(C));
36*9880d681SAndroid Build Coastguard Worker // }
37*9880d681SAndroid Build Coastguard Worker //
38*9880d681SAndroid Build Coastguard Worker // The DAG builder can also be customized in a sense by adding DAG mutations
39*9880d681SAndroid Build Coastguard Worker // that will run after DAG building and before list scheduling. DAG mutations
40*9880d681SAndroid Build Coastguard Worker // can adjust dependencies based on target-specific knowledge or add weak edges
41*9880d681SAndroid Build Coastguard Worker // to aid heuristics:
42*9880d681SAndroid Build Coastguard Worker //
43*9880d681SAndroid Build Coastguard Worker // ScheduleDAGInstrs *<Target>PassConfig::
44*9880d681SAndroid Build Coastguard Worker // createMachineScheduler(MachineSchedContext *C) {
45*9880d681SAndroid Build Coastguard Worker //   ScheduleDAGMI *DAG = new ScheduleDAGMI(C, CustomStrategy(C));
46*9880d681SAndroid Build Coastguard Worker //   DAG->addMutation(new CustomDependencies(DAG->TII, DAG->TRI));
47*9880d681SAndroid Build Coastguard Worker //   return DAG;
48*9880d681SAndroid Build Coastguard Worker // }
49*9880d681SAndroid Build Coastguard Worker //
50*9880d681SAndroid Build Coastguard Worker // A target that supports alternative schedulers can use the
51*9880d681SAndroid Build Coastguard Worker // MachineSchedRegistry to allow command line selection. This can be done by
52*9880d681SAndroid Build Coastguard Worker // implementing the following boilerplate:
53*9880d681SAndroid Build Coastguard Worker //
54*9880d681SAndroid Build Coastguard Worker // static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) {
55*9880d681SAndroid Build Coastguard Worker //  return new CustomMachineScheduler(C);
56*9880d681SAndroid Build Coastguard Worker // }
57*9880d681SAndroid Build Coastguard Worker // static MachineSchedRegistry
58*9880d681SAndroid Build Coastguard Worker // SchedCustomRegistry("custom", "Run my target's custom scheduler",
59*9880d681SAndroid Build Coastguard Worker //                     createCustomMachineSched);
60*9880d681SAndroid Build Coastguard Worker //
61*9880d681SAndroid Build Coastguard Worker //
62*9880d681SAndroid Build Coastguard Worker // Finally, subtargets that don't need to implement custom heuristics but would
63*9880d681SAndroid Build Coastguard Worker // like to configure the GenericScheduler's policy for a given scheduler region,
64*9880d681SAndroid Build Coastguard Worker // including scheduling direction and register pressure tracking policy, can do
65*9880d681SAndroid Build Coastguard Worker // this:
66*9880d681SAndroid Build Coastguard Worker //
67*9880d681SAndroid Build Coastguard Worker // void <SubTarget>Subtarget::
68*9880d681SAndroid Build Coastguard Worker // overrideSchedPolicy(MachineSchedPolicy &Policy,
69*9880d681SAndroid Build Coastguard Worker //                     unsigned NumRegionInstrs) const {
70*9880d681SAndroid Build Coastguard Worker //   Policy.<Flag> = true;
71*9880d681SAndroid Build Coastguard Worker // }
72*9880d681SAndroid Build Coastguard Worker //
73*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
74*9880d681SAndroid Build Coastguard Worker 
75*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_CODEGEN_MACHINESCHEDULER_H
76*9880d681SAndroid Build Coastguard Worker #define LLVM_CODEGEN_MACHINESCHEDULER_H
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AliasAnalysis.h"
79*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachinePassRegistry.h"
80*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterPressure.h"
81*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleDAGInstrs.h"
82*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleDAGMutation.h"
83*9880d681SAndroid Build Coastguard Worker #include <memory>
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker namespace llvm {
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker extern cl::opt<bool> ForceTopDown;
88*9880d681SAndroid Build Coastguard Worker extern cl::opt<bool> ForceBottomUp;
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker class LiveIntervals;
91*9880d681SAndroid Build Coastguard Worker class MachineDominatorTree;
92*9880d681SAndroid Build Coastguard Worker class MachineLoopInfo;
93*9880d681SAndroid Build Coastguard Worker class RegisterClassInfo;
94*9880d681SAndroid Build Coastguard Worker class ScheduleDAGInstrs;
95*9880d681SAndroid Build Coastguard Worker class SchedDFSResult;
96*9880d681SAndroid Build Coastguard Worker class ScheduleHazardRecognizer;
97*9880d681SAndroid Build Coastguard Worker 
98*9880d681SAndroid Build Coastguard Worker /// MachineSchedContext provides enough context from the MachineScheduler pass
99*9880d681SAndroid Build Coastguard Worker /// for the target to instantiate a scheduler.
100*9880d681SAndroid Build Coastguard Worker struct MachineSchedContext {
101*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF;
102*9880d681SAndroid Build Coastguard Worker   const MachineLoopInfo *MLI;
103*9880d681SAndroid Build Coastguard Worker   const MachineDominatorTree *MDT;
104*9880d681SAndroid Build Coastguard Worker   const TargetPassConfig *PassConfig;
105*9880d681SAndroid Build Coastguard Worker   AliasAnalysis *AA;
106*9880d681SAndroid Build Coastguard Worker   LiveIntervals *LIS;
107*9880d681SAndroid Build Coastguard Worker 
108*9880d681SAndroid Build Coastguard Worker   RegisterClassInfo *RegClassInfo;
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker   MachineSchedContext();
111*9880d681SAndroid Build Coastguard Worker   virtual ~MachineSchedContext();
112*9880d681SAndroid Build Coastguard Worker };
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker /// MachineSchedRegistry provides a selection of available machine instruction
115*9880d681SAndroid Build Coastguard Worker /// schedulers.
116*9880d681SAndroid Build Coastguard Worker class MachineSchedRegistry : public MachinePassRegistryNode {
117*9880d681SAndroid Build Coastguard Worker public:
118*9880d681SAndroid Build Coastguard Worker   typedef ScheduleDAGInstrs *(*ScheduleDAGCtor)(MachineSchedContext *);
119*9880d681SAndroid Build Coastguard Worker 
120*9880d681SAndroid Build Coastguard Worker   // RegisterPassParser requires a (misnamed) FunctionPassCtor type.
121*9880d681SAndroid Build Coastguard Worker   typedef ScheduleDAGCtor FunctionPassCtor;
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker   static MachinePassRegistry Registry;
124*9880d681SAndroid Build Coastguard Worker 
MachineSchedRegistry(const char * N,const char * D,ScheduleDAGCtor C)125*9880d681SAndroid Build Coastguard Worker   MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C)
126*9880d681SAndroid Build Coastguard Worker     : MachinePassRegistryNode(N, D, (MachinePassCtor)C) {
127*9880d681SAndroid Build Coastguard Worker     Registry.Add(this);
128*9880d681SAndroid Build Coastguard Worker   }
~MachineSchedRegistry()129*9880d681SAndroid Build Coastguard Worker   ~MachineSchedRegistry() { Registry.Remove(this); }
130*9880d681SAndroid Build Coastguard Worker 
131*9880d681SAndroid Build Coastguard Worker   // Accessors.
132*9880d681SAndroid Build Coastguard Worker   //
getNext()133*9880d681SAndroid Build Coastguard Worker   MachineSchedRegistry *getNext() const {
134*9880d681SAndroid Build Coastguard Worker     return (MachineSchedRegistry *)MachinePassRegistryNode::getNext();
135*9880d681SAndroid Build Coastguard Worker   }
getList()136*9880d681SAndroid Build Coastguard Worker   static MachineSchedRegistry *getList() {
137*9880d681SAndroid Build Coastguard Worker     return (MachineSchedRegistry *)Registry.getList();
138*9880d681SAndroid Build Coastguard Worker   }
setListener(MachinePassRegistryListener * L)139*9880d681SAndroid Build Coastguard Worker   static void setListener(MachinePassRegistryListener *L) {
140*9880d681SAndroid Build Coastguard Worker     Registry.setListener(L);
141*9880d681SAndroid Build Coastguard Worker   }
142*9880d681SAndroid Build Coastguard Worker };
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker class ScheduleDAGMI;
145*9880d681SAndroid Build Coastguard Worker 
146*9880d681SAndroid Build Coastguard Worker /// Define a generic scheduling policy for targets that don't provide their own
147*9880d681SAndroid Build Coastguard Worker /// MachineSchedStrategy. This can be overriden for each scheduling region
148*9880d681SAndroid Build Coastguard Worker /// before building the DAG.
149*9880d681SAndroid Build Coastguard Worker struct MachineSchedPolicy {
150*9880d681SAndroid Build Coastguard Worker   // Allow the scheduler to disable register pressure tracking.
151*9880d681SAndroid Build Coastguard Worker   bool ShouldTrackPressure;
152*9880d681SAndroid Build Coastguard Worker   /// Track LaneMasks to allow reordering of independent subregister writes
153*9880d681SAndroid Build Coastguard Worker   /// of the same vreg. \sa MachineSchedStrategy::shouldTrackLaneMasks()
154*9880d681SAndroid Build Coastguard Worker   bool ShouldTrackLaneMasks;
155*9880d681SAndroid Build Coastguard Worker 
156*9880d681SAndroid Build Coastguard Worker   // Allow the scheduler to force top-down or bottom-up scheduling. If neither
157*9880d681SAndroid Build Coastguard Worker   // is true, the scheduler runs in both directions and converges.
158*9880d681SAndroid Build Coastguard Worker   bool OnlyTopDown;
159*9880d681SAndroid Build Coastguard Worker   bool OnlyBottomUp;
160*9880d681SAndroid Build Coastguard Worker 
161*9880d681SAndroid Build Coastguard Worker   // Disable heuristic that tries to fetch nodes from long dependency chains
162*9880d681SAndroid Build Coastguard Worker   // first.
163*9880d681SAndroid Build Coastguard Worker   bool DisableLatencyHeuristic;
164*9880d681SAndroid Build Coastguard Worker 
MachineSchedPolicyMachineSchedPolicy165*9880d681SAndroid Build Coastguard Worker   MachineSchedPolicy(): ShouldTrackPressure(false), ShouldTrackLaneMasks(false),
166*9880d681SAndroid Build Coastguard Worker     OnlyTopDown(false), OnlyBottomUp(false), DisableLatencyHeuristic(false) {}
167*9880d681SAndroid Build Coastguard Worker };
168*9880d681SAndroid Build Coastguard Worker 
169*9880d681SAndroid Build Coastguard Worker /// MachineSchedStrategy - Interface to the scheduling algorithm used by
170*9880d681SAndroid Build Coastguard Worker /// ScheduleDAGMI.
171*9880d681SAndroid Build Coastguard Worker ///
172*9880d681SAndroid Build Coastguard Worker /// Initialization sequence:
173*9880d681SAndroid Build Coastguard Worker ///   initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots
174*9880d681SAndroid Build Coastguard Worker class MachineSchedStrategy {
175*9880d681SAndroid Build Coastguard Worker   virtual void anchor();
176*9880d681SAndroid Build Coastguard Worker public:
~MachineSchedStrategy()177*9880d681SAndroid Build Coastguard Worker   virtual ~MachineSchedStrategy() {}
178*9880d681SAndroid Build Coastguard Worker 
179*9880d681SAndroid Build Coastguard Worker   /// Optionally override the per-region scheduling policy.
initPolicy(MachineBasicBlock::iterator Begin,MachineBasicBlock::iterator End,unsigned NumRegionInstrs)180*9880d681SAndroid Build Coastguard Worker   virtual void initPolicy(MachineBasicBlock::iterator Begin,
181*9880d681SAndroid Build Coastguard Worker                           MachineBasicBlock::iterator End,
182*9880d681SAndroid Build Coastguard Worker                           unsigned NumRegionInstrs) {}
183*9880d681SAndroid Build Coastguard Worker 
dumpPolicy()184*9880d681SAndroid Build Coastguard Worker   virtual void dumpPolicy() {}
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker   /// Check if pressure tracking is needed before building the DAG and
187*9880d681SAndroid Build Coastguard Worker   /// initializing this strategy. Called after initPolicy.
shouldTrackPressure()188*9880d681SAndroid Build Coastguard Worker   virtual bool shouldTrackPressure() const { return true; }
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker   /// Returns true if lanemasks should be tracked. LaneMask tracking is
191*9880d681SAndroid Build Coastguard Worker   /// necessary to reorder independent subregister defs for the same vreg.
192*9880d681SAndroid Build Coastguard Worker   /// This has to be enabled in combination with shouldTrackPressure().
shouldTrackLaneMasks()193*9880d681SAndroid Build Coastguard Worker   virtual bool shouldTrackLaneMasks() const { return false; }
194*9880d681SAndroid Build Coastguard Worker 
195*9880d681SAndroid Build Coastguard Worker   /// Initialize the strategy after building the DAG for a new region.
196*9880d681SAndroid Build Coastguard Worker   virtual void initialize(ScheduleDAGMI *DAG) = 0;
197*9880d681SAndroid Build Coastguard Worker 
198*9880d681SAndroid Build Coastguard Worker   /// Notify this strategy that all roots have been released (including those
199*9880d681SAndroid Build Coastguard Worker   /// that depend on EntrySU or ExitSU).
registerRoots()200*9880d681SAndroid Build Coastguard Worker   virtual void registerRoots() {}
201*9880d681SAndroid Build Coastguard Worker 
202*9880d681SAndroid Build Coastguard Worker   /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to
203*9880d681SAndroid Build Coastguard Worker   /// schedule the node at the top of the unscheduled region. Otherwise it will
204*9880d681SAndroid Build Coastguard Worker   /// be scheduled at the bottom.
205*9880d681SAndroid Build Coastguard Worker   virtual SUnit *pickNode(bool &IsTopNode) = 0;
206*9880d681SAndroid Build Coastguard Worker 
207*9880d681SAndroid Build Coastguard Worker   /// \brief Scheduler callback to notify that a new subtree is scheduled.
scheduleTree(unsigned SubtreeID)208*9880d681SAndroid Build Coastguard Worker   virtual void scheduleTree(unsigned SubtreeID) {}
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker   /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an
211*9880d681SAndroid Build Coastguard Worker   /// instruction and updated scheduled/remaining flags in the DAG nodes.
212*9880d681SAndroid Build Coastguard Worker   virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
213*9880d681SAndroid Build Coastguard Worker 
214*9880d681SAndroid Build Coastguard Worker   /// When all predecessor dependencies have been resolved, free this node for
215*9880d681SAndroid Build Coastguard Worker   /// top-down scheduling.
216*9880d681SAndroid Build Coastguard Worker   virtual void releaseTopNode(SUnit *SU) = 0;
217*9880d681SAndroid Build Coastguard Worker   /// When all successor dependencies have been resolved, free this node for
218*9880d681SAndroid Build Coastguard Worker   /// bottom-up scheduling.
219*9880d681SAndroid Build Coastguard Worker   virtual void releaseBottomNode(SUnit *SU) = 0;
220*9880d681SAndroid Build Coastguard Worker };
221*9880d681SAndroid Build Coastguard Worker 
222*9880d681SAndroid Build Coastguard Worker /// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply
223*9880d681SAndroid Build Coastguard Worker /// schedules machine instructions according to the given MachineSchedStrategy
224*9880d681SAndroid Build Coastguard Worker /// without much extra book-keeping. This is the common functionality between
225*9880d681SAndroid Build Coastguard Worker /// PreRA and PostRA MachineScheduler.
226*9880d681SAndroid Build Coastguard Worker class ScheduleDAGMI : public ScheduleDAGInstrs {
227*9880d681SAndroid Build Coastguard Worker protected:
228*9880d681SAndroid Build Coastguard Worker   AliasAnalysis *AA;
229*9880d681SAndroid Build Coastguard Worker   LiveIntervals *LIS;
230*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MachineSchedStrategy> SchedImpl;
231*9880d681SAndroid Build Coastguard Worker 
232*9880d681SAndroid Build Coastguard Worker   /// Topo - A topological ordering for SUnits which permits fast IsReachable
233*9880d681SAndroid Build Coastguard Worker   /// and similar queries.
234*9880d681SAndroid Build Coastguard Worker   ScheduleDAGTopologicalSort Topo;
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker   /// Ordered list of DAG postprocessing steps.
237*9880d681SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
238*9880d681SAndroid Build Coastguard Worker 
239*9880d681SAndroid Build Coastguard Worker   /// The top of the unscheduled zone.
240*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator CurrentTop;
241*9880d681SAndroid Build Coastguard Worker 
242*9880d681SAndroid Build Coastguard Worker   /// The bottom of the unscheduled zone.
243*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator CurrentBottom;
244*9880d681SAndroid Build Coastguard Worker 
245*9880d681SAndroid Build Coastguard Worker   /// Record the next node in a scheduled cluster.
246*9880d681SAndroid Build Coastguard Worker   const SUnit *NextClusterPred;
247*9880d681SAndroid Build Coastguard Worker   const SUnit *NextClusterSucc;
248*9880d681SAndroid Build Coastguard Worker 
249*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
250*9880d681SAndroid Build Coastguard Worker   /// The number of instructions scheduled so far. Used to cut off the
251*9880d681SAndroid Build Coastguard Worker   /// scheduler at the point determined by misched-cutoff.
252*9880d681SAndroid Build Coastguard Worker   unsigned NumInstrsScheduled;
253*9880d681SAndroid Build Coastguard Worker #endif
254*9880d681SAndroid Build Coastguard Worker public:
ScheduleDAGMI(MachineSchedContext * C,std::unique_ptr<MachineSchedStrategy> S,bool RemoveKillFlags)255*9880d681SAndroid Build Coastguard Worker   ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S,
256*9880d681SAndroid Build Coastguard Worker                 bool RemoveKillFlags)
257*9880d681SAndroid Build Coastguard Worker       : ScheduleDAGInstrs(*C->MF, C->MLI, RemoveKillFlags), AA(C->AA),
258*9880d681SAndroid Build Coastguard Worker         LIS(C->LIS), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU),
259*9880d681SAndroid Build Coastguard Worker         CurrentTop(), CurrentBottom(), NextClusterPred(nullptr),
260*9880d681SAndroid Build Coastguard Worker         NextClusterSucc(nullptr) {
261*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
262*9880d681SAndroid Build Coastguard Worker     NumInstrsScheduled = 0;
263*9880d681SAndroid Build Coastguard Worker #endif
264*9880d681SAndroid Build Coastguard Worker   }
265*9880d681SAndroid Build Coastguard Worker 
266*9880d681SAndroid Build Coastguard Worker   // Provide a vtable anchor
267*9880d681SAndroid Build Coastguard Worker   ~ScheduleDAGMI() override;
268*9880d681SAndroid Build Coastguard Worker 
269*9880d681SAndroid Build Coastguard Worker   // Returns LiveIntervals instance for use in DAG mutators and such.
getLIS()270*9880d681SAndroid Build Coastguard Worker   LiveIntervals *getLIS() const { return LIS; }
271*9880d681SAndroid Build Coastguard Worker 
272*9880d681SAndroid Build Coastguard Worker   /// Return true if this DAG supports VReg liveness and RegPressure.
hasVRegLiveness()273*9880d681SAndroid Build Coastguard Worker   virtual bool hasVRegLiveness() const { return false; }
274*9880d681SAndroid Build Coastguard Worker 
275*9880d681SAndroid Build Coastguard Worker   /// Add a postprocessing step to the DAG builder.
276*9880d681SAndroid Build Coastguard Worker   /// Mutations are applied in the order that they are added after normal DAG
277*9880d681SAndroid Build Coastguard Worker   /// building and before MachineSchedStrategy initialization.
278*9880d681SAndroid Build Coastguard Worker   ///
279*9880d681SAndroid Build Coastguard Worker   /// ScheduleDAGMI takes ownership of the Mutation object.
addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation)280*9880d681SAndroid Build Coastguard Worker   void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
281*9880d681SAndroid Build Coastguard Worker     Mutations.push_back(std::move(Mutation));
282*9880d681SAndroid Build Coastguard Worker   }
283*9880d681SAndroid Build Coastguard Worker 
284*9880d681SAndroid Build Coastguard Worker   /// \brief True if an edge can be added from PredSU to SuccSU without creating
285*9880d681SAndroid Build Coastguard Worker   /// a cycle.
286*9880d681SAndroid Build Coastguard Worker   bool canAddEdge(SUnit *SuccSU, SUnit *PredSU);
287*9880d681SAndroid Build Coastguard Worker 
288*9880d681SAndroid Build Coastguard Worker   /// \brief Add a DAG edge to the given SU with the given predecessor
289*9880d681SAndroid Build Coastguard Worker   /// dependence data.
290*9880d681SAndroid Build Coastguard Worker   ///
291*9880d681SAndroid Build Coastguard Worker   /// \returns true if the edge may be added without creating a cycle OR if an
292*9880d681SAndroid Build Coastguard Worker   /// equivalent edge already existed (false indicates failure).
293*9880d681SAndroid Build Coastguard Worker   bool addEdge(SUnit *SuccSU, const SDep &PredDep);
294*9880d681SAndroid Build Coastguard Worker 
top()295*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator top() const { return CurrentTop; }
bottom()296*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator bottom() const { return CurrentBottom; }
297*9880d681SAndroid Build Coastguard Worker 
298*9880d681SAndroid Build Coastguard Worker   /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
299*9880d681SAndroid Build Coastguard Worker   /// region. This covers all instructions in a block, while schedule() may only
300*9880d681SAndroid Build Coastguard Worker   /// cover a subset.
301*9880d681SAndroid Build Coastguard Worker   void enterRegion(MachineBasicBlock *bb,
302*9880d681SAndroid Build Coastguard Worker                    MachineBasicBlock::iterator begin,
303*9880d681SAndroid Build Coastguard Worker                    MachineBasicBlock::iterator end,
304*9880d681SAndroid Build Coastguard Worker                    unsigned regioninstrs) override;
305*9880d681SAndroid Build Coastguard Worker 
306*9880d681SAndroid Build Coastguard Worker   /// Implement ScheduleDAGInstrs interface for scheduling a sequence of
307*9880d681SAndroid Build Coastguard Worker   /// reorderable instructions.
308*9880d681SAndroid Build Coastguard Worker   void schedule() override;
309*9880d681SAndroid Build Coastguard Worker 
310*9880d681SAndroid Build Coastguard Worker   /// Change the position of an instruction within the basic block and update
311*9880d681SAndroid Build Coastguard Worker   /// live ranges and region boundary iterators.
312*9880d681SAndroid Build Coastguard Worker   void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
313*9880d681SAndroid Build Coastguard Worker 
getNextClusterPred()314*9880d681SAndroid Build Coastguard Worker   const SUnit *getNextClusterPred() const { return NextClusterPred; }
315*9880d681SAndroid Build Coastguard Worker 
getNextClusterSucc()316*9880d681SAndroid Build Coastguard Worker   const SUnit *getNextClusterSucc() const { return NextClusterSucc; }
317*9880d681SAndroid Build Coastguard Worker 
318*9880d681SAndroid Build Coastguard Worker   void viewGraph(const Twine &Name, const Twine &Title) override;
319*9880d681SAndroid Build Coastguard Worker   void viewGraph() override;
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker protected:
322*9880d681SAndroid Build Coastguard Worker   // Top-Level entry points for the schedule() driver...
323*9880d681SAndroid Build Coastguard Worker 
324*9880d681SAndroid Build Coastguard Worker   /// Apply each ScheduleDAGMutation step in order. This allows different
325*9880d681SAndroid Build Coastguard Worker   /// instances of ScheduleDAGMI to perform custom DAG postprocessing.
326*9880d681SAndroid Build Coastguard Worker   void postprocessDAG();
327*9880d681SAndroid Build Coastguard Worker 
328*9880d681SAndroid Build Coastguard Worker   /// Release ExitSU predecessors and setup scheduler queues.
329*9880d681SAndroid Build Coastguard Worker   void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
330*9880d681SAndroid Build Coastguard Worker 
331*9880d681SAndroid Build Coastguard Worker   /// Update scheduler DAG and queues after scheduling an instruction.
332*9880d681SAndroid Build Coastguard Worker   void updateQueues(SUnit *SU, bool IsTopNode);
333*9880d681SAndroid Build Coastguard Worker 
334*9880d681SAndroid Build Coastguard Worker   /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
335*9880d681SAndroid Build Coastguard Worker   void placeDebugValues();
336*9880d681SAndroid Build Coastguard Worker 
337*9880d681SAndroid Build Coastguard Worker   /// \brief dump the scheduled Sequence.
338*9880d681SAndroid Build Coastguard Worker   void dumpSchedule() const;
339*9880d681SAndroid Build Coastguard Worker 
340*9880d681SAndroid Build Coastguard Worker   // Lesser helpers...
341*9880d681SAndroid Build Coastguard Worker   bool checkSchedLimit();
342*9880d681SAndroid Build Coastguard Worker 
343*9880d681SAndroid Build Coastguard Worker   void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
344*9880d681SAndroid Build Coastguard Worker                              SmallVectorImpl<SUnit*> &BotRoots);
345*9880d681SAndroid Build Coastguard Worker 
346*9880d681SAndroid Build Coastguard Worker   void releaseSucc(SUnit *SU, SDep *SuccEdge);
347*9880d681SAndroid Build Coastguard Worker   void releaseSuccessors(SUnit *SU);
348*9880d681SAndroid Build Coastguard Worker   void releasePred(SUnit *SU, SDep *PredEdge);
349*9880d681SAndroid Build Coastguard Worker   void releasePredecessors(SUnit *SU);
350*9880d681SAndroid Build Coastguard Worker };
351*9880d681SAndroid Build Coastguard Worker 
352*9880d681SAndroid Build Coastguard Worker /// ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules
353*9880d681SAndroid Build Coastguard Worker /// machine instructions while updating LiveIntervals and tracking regpressure.
354*9880d681SAndroid Build Coastguard Worker class ScheduleDAGMILive : public ScheduleDAGMI {
355*9880d681SAndroid Build Coastguard Worker protected:
356*9880d681SAndroid Build Coastguard Worker   RegisterClassInfo *RegClassInfo;
357*9880d681SAndroid Build Coastguard Worker 
358*9880d681SAndroid Build Coastguard Worker   /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees
359*9880d681SAndroid Build Coastguard Worker   /// will be empty.
360*9880d681SAndroid Build Coastguard Worker   SchedDFSResult *DFSResult;
361*9880d681SAndroid Build Coastguard Worker   BitVector ScheduledTrees;
362*9880d681SAndroid Build Coastguard Worker 
363*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator LiveRegionEnd;
364*9880d681SAndroid Build Coastguard Worker 
365*9880d681SAndroid Build Coastguard Worker   // Map each SU to its summary of pressure changes. This array is updated for
366*9880d681SAndroid Build Coastguard Worker   // liveness during bottom-up scheduling. Top-down scheduling may proceed but
367*9880d681SAndroid Build Coastguard Worker   // has no affect on the pressure diffs.
368*9880d681SAndroid Build Coastguard Worker   PressureDiffs SUPressureDiffs;
369*9880d681SAndroid Build Coastguard Worker 
370*9880d681SAndroid Build Coastguard Worker   /// Register pressure in this region computed by initRegPressure.
371*9880d681SAndroid Build Coastguard Worker   bool ShouldTrackPressure;
372*9880d681SAndroid Build Coastguard Worker   bool ShouldTrackLaneMasks;
373*9880d681SAndroid Build Coastguard Worker   IntervalPressure RegPressure;
374*9880d681SAndroid Build Coastguard Worker   RegPressureTracker RPTracker;
375*9880d681SAndroid Build Coastguard Worker 
376*9880d681SAndroid Build Coastguard Worker   /// List of pressure sets that exceed the target's pressure limit before
377*9880d681SAndroid Build Coastguard Worker   /// scheduling, listed in increasing set ID order. Each pressure set is paired
378*9880d681SAndroid Build Coastguard Worker   /// with its max pressure in the currently scheduled regions.
379*9880d681SAndroid Build Coastguard Worker   std::vector<PressureChange> RegionCriticalPSets;
380*9880d681SAndroid Build Coastguard Worker 
381*9880d681SAndroid Build Coastguard Worker   /// The top of the unscheduled zone.
382*9880d681SAndroid Build Coastguard Worker   IntervalPressure TopPressure;
383*9880d681SAndroid Build Coastguard Worker   RegPressureTracker TopRPTracker;
384*9880d681SAndroid Build Coastguard Worker 
385*9880d681SAndroid Build Coastguard Worker   /// The bottom of the unscheduled zone.
386*9880d681SAndroid Build Coastguard Worker   IntervalPressure BotPressure;
387*9880d681SAndroid Build Coastguard Worker   RegPressureTracker BotRPTracker;
388*9880d681SAndroid Build Coastguard Worker 
389*9880d681SAndroid Build Coastguard Worker   /// True if disconnected subregister components are already renamed.
390*9880d681SAndroid Build Coastguard Worker   /// The renaming is only done on demand if lane masks are tracked.
391*9880d681SAndroid Build Coastguard Worker   bool DisconnectedComponentsRenamed;
392*9880d681SAndroid Build Coastguard Worker 
393*9880d681SAndroid Build Coastguard Worker public:
ScheduleDAGMILive(MachineSchedContext * C,std::unique_ptr<MachineSchedStrategy> S)394*9880d681SAndroid Build Coastguard Worker   ScheduleDAGMILive(MachineSchedContext *C,
395*9880d681SAndroid Build Coastguard Worker                     std::unique_ptr<MachineSchedStrategy> S)
396*9880d681SAndroid Build Coastguard Worker       : ScheduleDAGMI(C, std::move(S), /*RemoveKillFlags=*/false),
397*9880d681SAndroid Build Coastguard Worker         RegClassInfo(C->RegClassInfo), DFSResult(nullptr),
398*9880d681SAndroid Build Coastguard Worker         ShouldTrackPressure(false), ShouldTrackLaneMasks(false),
399*9880d681SAndroid Build Coastguard Worker         RPTracker(RegPressure), TopRPTracker(TopPressure),
400*9880d681SAndroid Build Coastguard Worker         BotRPTracker(BotPressure), DisconnectedComponentsRenamed(false) {}
401*9880d681SAndroid Build Coastguard Worker 
402*9880d681SAndroid Build Coastguard Worker   ~ScheduleDAGMILive() override;
403*9880d681SAndroid Build Coastguard Worker 
404*9880d681SAndroid Build Coastguard Worker   /// Return true if this DAG supports VReg liveness and RegPressure.
hasVRegLiveness()405*9880d681SAndroid Build Coastguard Worker   bool hasVRegLiveness() const override { return true; }
406*9880d681SAndroid Build Coastguard Worker 
407*9880d681SAndroid Build Coastguard Worker   /// \brief Return true if register pressure tracking is enabled.
isTrackingPressure()408*9880d681SAndroid Build Coastguard Worker   bool isTrackingPressure() const { return ShouldTrackPressure; }
409*9880d681SAndroid Build Coastguard Worker 
410*9880d681SAndroid Build Coastguard Worker   /// Get current register pressure for the top scheduled instructions.
getTopPressure()411*9880d681SAndroid Build Coastguard Worker   const IntervalPressure &getTopPressure() const { return TopPressure; }
getTopRPTracker()412*9880d681SAndroid Build Coastguard Worker   const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; }
413*9880d681SAndroid Build Coastguard Worker 
414*9880d681SAndroid Build Coastguard Worker   /// Get current register pressure for the bottom scheduled instructions.
getBotPressure()415*9880d681SAndroid Build Coastguard Worker   const IntervalPressure &getBotPressure() const { return BotPressure; }
getBotRPTracker()416*9880d681SAndroid Build Coastguard Worker   const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; }
417*9880d681SAndroid Build Coastguard Worker 
418*9880d681SAndroid Build Coastguard Worker   /// Get register pressure for the entire scheduling region before scheduling.
getRegPressure()419*9880d681SAndroid Build Coastguard Worker   const IntervalPressure &getRegPressure() const { return RegPressure; }
420*9880d681SAndroid Build Coastguard Worker 
getRegionCriticalPSets()421*9880d681SAndroid Build Coastguard Worker   const std::vector<PressureChange> &getRegionCriticalPSets() const {
422*9880d681SAndroid Build Coastguard Worker     return RegionCriticalPSets;
423*9880d681SAndroid Build Coastguard Worker   }
424*9880d681SAndroid Build Coastguard Worker 
getPressureDiff(const SUnit * SU)425*9880d681SAndroid Build Coastguard Worker   PressureDiff &getPressureDiff(const SUnit *SU) {
426*9880d681SAndroid Build Coastguard Worker     return SUPressureDiffs[SU->NodeNum];
427*9880d681SAndroid Build Coastguard Worker   }
428*9880d681SAndroid Build Coastguard Worker 
429*9880d681SAndroid Build Coastguard Worker   /// Compute a DFSResult after DAG building is complete, and before any
430*9880d681SAndroid Build Coastguard Worker   /// queue comparisons.
431*9880d681SAndroid Build Coastguard Worker   void computeDFSResult();
432*9880d681SAndroid Build Coastguard Worker 
433*9880d681SAndroid Build Coastguard Worker   /// Return a non-null DFS result if the scheduling strategy initialized it.
getDFSResult()434*9880d681SAndroid Build Coastguard Worker   const SchedDFSResult *getDFSResult() const { return DFSResult; }
435*9880d681SAndroid Build Coastguard Worker 
getScheduledTrees()436*9880d681SAndroid Build Coastguard Worker   BitVector &getScheduledTrees() { return ScheduledTrees; }
437*9880d681SAndroid Build Coastguard Worker 
438*9880d681SAndroid Build Coastguard Worker   /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
439*9880d681SAndroid Build Coastguard Worker   /// region. This covers all instructions in a block, while schedule() may only
440*9880d681SAndroid Build Coastguard Worker   /// cover a subset.
441*9880d681SAndroid Build Coastguard Worker   void enterRegion(MachineBasicBlock *bb,
442*9880d681SAndroid Build Coastguard Worker                    MachineBasicBlock::iterator begin,
443*9880d681SAndroid Build Coastguard Worker                    MachineBasicBlock::iterator end,
444*9880d681SAndroid Build Coastguard Worker                    unsigned regioninstrs) override;
445*9880d681SAndroid Build Coastguard Worker 
446*9880d681SAndroid Build Coastguard Worker   /// Implement ScheduleDAGInstrs interface for scheduling a sequence of
447*9880d681SAndroid Build Coastguard Worker   /// reorderable instructions.
448*9880d681SAndroid Build Coastguard Worker   void schedule() override;
449*9880d681SAndroid Build Coastguard Worker 
450*9880d681SAndroid Build Coastguard Worker   /// Compute the cyclic critical path through the DAG.
451*9880d681SAndroid Build Coastguard Worker   unsigned computeCyclicCriticalPath();
452*9880d681SAndroid Build Coastguard Worker 
453*9880d681SAndroid Build Coastguard Worker protected:
454*9880d681SAndroid Build Coastguard Worker   // Top-Level entry points for the schedule() driver...
455*9880d681SAndroid Build Coastguard Worker 
456*9880d681SAndroid Build Coastguard Worker   /// Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking
457*9880d681SAndroid Build Coastguard Worker   /// enabled. This sets up three trackers. RPTracker will cover the entire DAG
458*9880d681SAndroid Build Coastguard Worker   /// region, TopTracker and BottomTracker will be initialized to the top and
459*9880d681SAndroid Build Coastguard Worker   /// bottom of the DAG region without covereing any unscheduled instruction.
460*9880d681SAndroid Build Coastguard Worker   void buildDAGWithRegPressure();
461*9880d681SAndroid Build Coastguard Worker 
462*9880d681SAndroid Build Coastguard Worker   /// Release ExitSU predecessors and setup scheduler queues. Re-position
463*9880d681SAndroid Build Coastguard Worker   /// the Top RP tracker in case the region beginning has changed.
464*9880d681SAndroid Build Coastguard Worker   void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
465*9880d681SAndroid Build Coastguard Worker 
466*9880d681SAndroid Build Coastguard Worker   /// Move an instruction and update register pressure.
467*9880d681SAndroid Build Coastguard Worker   void scheduleMI(SUnit *SU, bool IsTopNode);
468*9880d681SAndroid Build Coastguard Worker 
469*9880d681SAndroid Build Coastguard Worker   // Lesser helpers...
470*9880d681SAndroid Build Coastguard Worker 
471*9880d681SAndroid Build Coastguard Worker   void initRegPressure();
472*9880d681SAndroid Build Coastguard Worker 
473*9880d681SAndroid Build Coastguard Worker   void updatePressureDiffs(ArrayRef<RegisterMaskPair> LiveUses);
474*9880d681SAndroid Build Coastguard Worker 
475*9880d681SAndroid Build Coastguard Worker   void updateScheduledPressure(const SUnit *SU,
476*9880d681SAndroid Build Coastguard Worker                                const std::vector<unsigned> &NewMaxPressure);
477*9880d681SAndroid Build Coastguard Worker };
478*9880d681SAndroid Build Coastguard Worker 
479*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
480*9880d681SAndroid Build Coastguard Worker ///
481*9880d681SAndroid Build Coastguard Worker /// Helpers for implementing custom MachineSchedStrategy classes. These take
482*9880d681SAndroid Build Coastguard Worker /// care of the book-keeping associated with list scheduling heuristics.
483*9880d681SAndroid Build Coastguard Worker ///
484*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
485*9880d681SAndroid Build Coastguard Worker 
486*9880d681SAndroid Build Coastguard Worker /// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience
487*9880d681SAndroid Build Coastguard Worker /// methods for pushing and removing nodes. ReadyQueue's are uniquely identified
488*9880d681SAndroid Build Coastguard Worker /// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in.
489*9880d681SAndroid Build Coastguard Worker ///
490*9880d681SAndroid Build Coastguard Worker /// This is a convenience class that may be used by implementations of
491*9880d681SAndroid Build Coastguard Worker /// MachineSchedStrategy.
492*9880d681SAndroid Build Coastguard Worker class ReadyQueue {
493*9880d681SAndroid Build Coastguard Worker   unsigned ID;
494*9880d681SAndroid Build Coastguard Worker   std::string Name;
495*9880d681SAndroid Build Coastguard Worker   std::vector<SUnit*> Queue;
496*9880d681SAndroid Build Coastguard Worker 
497*9880d681SAndroid Build Coastguard Worker public:
ReadyQueue(unsigned id,const Twine & name)498*9880d681SAndroid Build Coastguard Worker   ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {}
499*9880d681SAndroid Build Coastguard Worker 
getID()500*9880d681SAndroid Build Coastguard Worker   unsigned getID() const { return ID; }
501*9880d681SAndroid Build Coastguard Worker 
getName()502*9880d681SAndroid Build Coastguard Worker   StringRef getName() const { return Name; }
503*9880d681SAndroid Build Coastguard Worker 
504*9880d681SAndroid Build Coastguard Worker   // SU is in this queue if it's NodeQueueID is a superset of this ID.
isInQueue(SUnit * SU)505*9880d681SAndroid Build Coastguard Worker   bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); }
506*9880d681SAndroid Build Coastguard Worker 
empty()507*9880d681SAndroid Build Coastguard Worker   bool empty() const { return Queue.empty(); }
508*9880d681SAndroid Build Coastguard Worker 
clear()509*9880d681SAndroid Build Coastguard Worker   void clear() { Queue.clear(); }
510*9880d681SAndroid Build Coastguard Worker 
size()511*9880d681SAndroid Build Coastguard Worker   unsigned size() const { return Queue.size(); }
512*9880d681SAndroid Build Coastguard Worker 
513*9880d681SAndroid Build Coastguard Worker   typedef std::vector<SUnit*>::iterator iterator;
514*9880d681SAndroid Build Coastguard Worker 
begin()515*9880d681SAndroid Build Coastguard Worker   iterator begin() { return Queue.begin(); }
516*9880d681SAndroid Build Coastguard Worker 
end()517*9880d681SAndroid Build Coastguard Worker   iterator end() { return Queue.end(); }
518*9880d681SAndroid Build Coastguard Worker 
elements()519*9880d681SAndroid Build Coastguard Worker   ArrayRef<SUnit*> elements() { return Queue; }
520*9880d681SAndroid Build Coastguard Worker 
find(SUnit * SU)521*9880d681SAndroid Build Coastguard Worker   iterator find(SUnit *SU) {
522*9880d681SAndroid Build Coastguard Worker     return std::find(Queue.begin(), Queue.end(), SU);
523*9880d681SAndroid Build Coastguard Worker   }
524*9880d681SAndroid Build Coastguard Worker 
push(SUnit * SU)525*9880d681SAndroid Build Coastguard Worker   void push(SUnit *SU) {
526*9880d681SAndroid Build Coastguard Worker     Queue.push_back(SU);
527*9880d681SAndroid Build Coastguard Worker     SU->NodeQueueId |= ID;
528*9880d681SAndroid Build Coastguard Worker   }
529*9880d681SAndroid Build Coastguard Worker 
remove(iterator I)530*9880d681SAndroid Build Coastguard Worker   iterator remove(iterator I) {
531*9880d681SAndroid Build Coastguard Worker     (*I)->NodeQueueId &= ~ID;
532*9880d681SAndroid Build Coastguard Worker     *I = Queue.back();
533*9880d681SAndroid Build Coastguard Worker     unsigned idx = I - Queue.begin();
534*9880d681SAndroid Build Coastguard Worker     Queue.pop_back();
535*9880d681SAndroid Build Coastguard Worker     return Queue.begin() + idx;
536*9880d681SAndroid Build Coastguard Worker   }
537*9880d681SAndroid Build Coastguard Worker 
538*9880d681SAndroid Build Coastguard Worker   void dump();
539*9880d681SAndroid Build Coastguard Worker };
540*9880d681SAndroid Build Coastguard Worker 
541*9880d681SAndroid Build Coastguard Worker /// Summarize the unscheduled region.
542*9880d681SAndroid Build Coastguard Worker struct SchedRemainder {
543*9880d681SAndroid Build Coastguard Worker   // Critical path through the DAG in expected latency.
544*9880d681SAndroid Build Coastguard Worker   unsigned CriticalPath;
545*9880d681SAndroid Build Coastguard Worker   unsigned CyclicCritPath;
546*9880d681SAndroid Build Coastguard Worker 
547*9880d681SAndroid Build Coastguard Worker   // Scaled count of micro-ops left to schedule.
548*9880d681SAndroid Build Coastguard Worker   unsigned RemIssueCount;
549*9880d681SAndroid Build Coastguard Worker 
550*9880d681SAndroid Build Coastguard Worker   bool IsAcyclicLatencyLimited;
551*9880d681SAndroid Build Coastguard Worker 
552*9880d681SAndroid Build Coastguard Worker   // Unscheduled resources
553*9880d681SAndroid Build Coastguard Worker   SmallVector<unsigned, 16> RemainingCounts;
554*9880d681SAndroid Build Coastguard Worker 
resetSchedRemainder555*9880d681SAndroid Build Coastguard Worker   void reset() {
556*9880d681SAndroid Build Coastguard Worker     CriticalPath = 0;
557*9880d681SAndroid Build Coastguard Worker     CyclicCritPath = 0;
558*9880d681SAndroid Build Coastguard Worker     RemIssueCount = 0;
559*9880d681SAndroid Build Coastguard Worker     IsAcyclicLatencyLimited = false;
560*9880d681SAndroid Build Coastguard Worker     RemainingCounts.clear();
561*9880d681SAndroid Build Coastguard Worker   }
562*9880d681SAndroid Build Coastguard Worker 
SchedRemainderSchedRemainder563*9880d681SAndroid Build Coastguard Worker   SchedRemainder() { reset(); }
564*9880d681SAndroid Build Coastguard Worker 
565*9880d681SAndroid Build Coastguard Worker   void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel);
566*9880d681SAndroid Build Coastguard Worker };
567*9880d681SAndroid Build Coastguard Worker 
568*9880d681SAndroid Build Coastguard Worker /// Each Scheduling boundary is associated with ready queues. It tracks the
569*9880d681SAndroid Build Coastguard Worker /// current cycle in the direction of movement, and maintains the state
570*9880d681SAndroid Build Coastguard Worker /// of "hazards" and other interlocks at the current cycle.
571*9880d681SAndroid Build Coastguard Worker class SchedBoundary {
572*9880d681SAndroid Build Coastguard Worker public:
573*9880d681SAndroid Build Coastguard Worker   /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
574*9880d681SAndroid Build Coastguard Worker   enum {
575*9880d681SAndroid Build Coastguard Worker     TopQID = 1,
576*9880d681SAndroid Build Coastguard Worker     BotQID = 2,
577*9880d681SAndroid Build Coastguard Worker     LogMaxQID = 2
578*9880d681SAndroid Build Coastguard Worker   };
579*9880d681SAndroid Build Coastguard Worker 
580*9880d681SAndroid Build Coastguard Worker   ScheduleDAGMI *DAG;
581*9880d681SAndroid Build Coastguard Worker   const TargetSchedModel *SchedModel;
582*9880d681SAndroid Build Coastguard Worker   SchedRemainder *Rem;
583*9880d681SAndroid Build Coastguard Worker 
584*9880d681SAndroid Build Coastguard Worker   ReadyQueue Available;
585*9880d681SAndroid Build Coastguard Worker   ReadyQueue Pending;
586*9880d681SAndroid Build Coastguard Worker 
587*9880d681SAndroid Build Coastguard Worker   ScheduleHazardRecognizer *HazardRec;
588*9880d681SAndroid Build Coastguard Worker 
589*9880d681SAndroid Build Coastguard Worker private:
590*9880d681SAndroid Build Coastguard Worker   /// True if the pending Q should be checked/updated before scheduling another
591*9880d681SAndroid Build Coastguard Worker   /// instruction.
592*9880d681SAndroid Build Coastguard Worker   bool CheckPending;
593*9880d681SAndroid Build Coastguard Worker 
594*9880d681SAndroid Build Coastguard Worker   // For heuristics, keep a list of the nodes that immediately depend on the
595*9880d681SAndroid Build Coastguard Worker   // most recently scheduled node.
596*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<const SUnit*, 8> NextSUs;
597*9880d681SAndroid Build Coastguard Worker 
598*9880d681SAndroid Build Coastguard Worker   /// Number of cycles it takes to issue the instructions scheduled in this
599*9880d681SAndroid Build Coastguard Worker   /// zone. It is defined as: scheduled-micro-ops / issue-width + stalls.
600*9880d681SAndroid Build Coastguard Worker   /// See getStalls().
601*9880d681SAndroid Build Coastguard Worker   unsigned CurrCycle;
602*9880d681SAndroid Build Coastguard Worker 
603*9880d681SAndroid Build Coastguard Worker   /// Micro-ops issued in the current cycle
604*9880d681SAndroid Build Coastguard Worker   unsigned CurrMOps;
605*9880d681SAndroid Build Coastguard Worker 
606*9880d681SAndroid Build Coastguard Worker   /// MinReadyCycle - Cycle of the soonest available instruction.
607*9880d681SAndroid Build Coastguard Worker   unsigned MinReadyCycle;
608*9880d681SAndroid Build Coastguard Worker 
609*9880d681SAndroid Build Coastguard Worker   // The expected latency of the critical path in this scheduled zone.
610*9880d681SAndroid Build Coastguard Worker   unsigned ExpectedLatency;
611*9880d681SAndroid Build Coastguard Worker 
612*9880d681SAndroid Build Coastguard Worker   // The latency of dependence chains leading into this zone.
613*9880d681SAndroid Build Coastguard Worker   // For each node scheduled bottom-up: DLat = max DLat, N.Depth.
614*9880d681SAndroid Build Coastguard Worker   // For each cycle scheduled: DLat -= 1.
615*9880d681SAndroid Build Coastguard Worker   unsigned DependentLatency;
616*9880d681SAndroid Build Coastguard Worker 
617*9880d681SAndroid Build Coastguard Worker   /// Count the scheduled (issued) micro-ops that can be retired by
618*9880d681SAndroid Build Coastguard Worker   /// time=CurrCycle assuming the first scheduled instr is retired at time=0.
619*9880d681SAndroid Build Coastguard Worker   unsigned RetiredMOps;
620*9880d681SAndroid Build Coastguard Worker 
621*9880d681SAndroid Build Coastguard Worker   // Count scheduled resources that have been executed. Resources are
622*9880d681SAndroid Build Coastguard Worker   // considered executed if they become ready in the time that it takes to
623*9880d681SAndroid Build Coastguard Worker   // saturate any resource including the one in question. Counts are scaled
624*9880d681SAndroid Build Coastguard Worker   // for direct comparison with other resources. Counts can be compared with
625*9880d681SAndroid Build Coastguard Worker   // MOps * getMicroOpFactor and Latency * getLatencyFactor.
626*9880d681SAndroid Build Coastguard Worker   SmallVector<unsigned, 16> ExecutedResCounts;
627*9880d681SAndroid Build Coastguard Worker 
628*9880d681SAndroid Build Coastguard Worker   /// Cache the max count for a single resource.
629*9880d681SAndroid Build Coastguard Worker   unsigned MaxExecutedResCount;
630*9880d681SAndroid Build Coastguard Worker 
631*9880d681SAndroid Build Coastguard Worker   // Cache the critical resources ID in this scheduled zone.
632*9880d681SAndroid Build Coastguard Worker   unsigned ZoneCritResIdx;
633*9880d681SAndroid Build Coastguard Worker 
634*9880d681SAndroid Build Coastguard Worker   // Is the scheduled region resource limited vs. latency limited.
635*9880d681SAndroid Build Coastguard Worker   bool IsResourceLimited;
636*9880d681SAndroid Build Coastguard Worker 
637*9880d681SAndroid Build Coastguard Worker   // Record the highest cycle at which each resource has been reserved by a
638*9880d681SAndroid Build Coastguard Worker   // scheduled instruction.
639*9880d681SAndroid Build Coastguard Worker   SmallVector<unsigned, 16> ReservedCycles;
640*9880d681SAndroid Build Coastguard Worker 
641*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
642*9880d681SAndroid Build Coastguard Worker   // Remember the greatest possible stall as an upper bound on the number of
643*9880d681SAndroid Build Coastguard Worker   // times we should retry the pending queue because of a hazard.
644*9880d681SAndroid Build Coastguard Worker   unsigned MaxObservedStall;
645*9880d681SAndroid Build Coastguard Worker #endif
646*9880d681SAndroid Build Coastguard Worker 
647*9880d681SAndroid Build Coastguard Worker public:
648*9880d681SAndroid Build Coastguard Worker   /// Pending queues extend the ready queues with the same ID and the
649*9880d681SAndroid Build Coastguard Worker   /// PendingFlag set.
SchedBoundary(unsigned ID,const Twine & Name)650*9880d681SAndroid Build Coastguard Worker   SchedBoundary(unsigned ID, const Twine &Name):
651*9880d681SAndroid Build Coastguard Worker     DAG(nullptr), SchedModel(nullptr), Rem(nullptr), Available(ID, Name+".A"),
652*9880d681SAndroid Build Coastguard Worker     Pending(ID << LogMaxQID, Name+".P"),
653*9880d681SAndroid Build Coastguard Worker     HazardRec(nullptr) {
654*9880d681SAndroid Build Coastguard Worker     reset();
655*9880d681SAndroid Build Coastguard Worker   }
656*9880d681SAndroid Build Coastguard Worker 
657*9880d681SAndroid Build Coastguard Worker   ~SchedBoundary();
658*9880d681SAndroid Build Coastguard Worker 
659*9880d681SAndroid Build Coastguard Worker   void reset();
660*9880d681SAndroid Build Coastguard Worker 
661*9880d681SAndroid Build Coastguard Worker   void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel,
662*9880d681SAndroid Build Coastguard Worker             SchedRemainder *rem);
663*9880d681SAndroid Build Coastguard Worker 
isTop()664*9880d681SAndroid Build Coastguard Worker   bool isTop() const {
665*9880d681SAndroid Build Coastguard Worker     return Available.getID() == TopQID;
666*9880d681SAndroid Build Coastguard Worker   }
667*9880d681SAndroid Build Coastguard Worker 
668*9880d681SAndroid Build Coastguard Worker   /// Number of cycles to issue the instructions scheduled in this zone.
getCurrCycle()669*9880d681SAndroid Build Coastguard Worker   unsigned getCurrCycle() const { return CurrCycle; }
670*9880d681SAndroid Build Coastguard Worker 
671*9880d681SAndroid Build Coastguard Worker   /// Micro-ops issued in the current cycle
getCurrMOps()672*9880d681SAndroid Build Coastguard Worker   unsigned getCurrMOps() const { return CurrMOps; }
673*9880d681SAndroid Build Coastguard Worker 
674*9880d681SAndroid Build Coastguard Worker   /// Return true if the given SU is used by the most recently scheduled
675*9880d681SAndroid Build Coastguard Worker   /// instruction.
isNextSU(const SUnit * SU)676*9880d681SAndroid Build Coastguard Worker   bool isNextSU(const SUnit *SU) const { return NextSUs.count(SU); }
677*9880d681SAndroid Build Coastguard Worker 
678*9880d681SAndroid Build Coastguard Worker   // The latency of dependence chains leading into this zone.
getDependentLatency()679*9880d681SAndroid Build Coastguard Worker   unsigned getDependentLatency() const { return DependentLatency; }
680*9880d681SAndroid Build Coastguard Worker 
681*9880d681SAndroid Build Coastguard Worker   /// Get the number of latency cycles "covered" by the scheduled
682*9880d681SAndroid Build Coastguard Worker   /// instructions. This is the larger of the critical path within the zone
683*9880d681SAndroid Build Coastguard Worker   /// and the number of cycles required to issue the instructions.
getScheduledLatency()684*9880d681SAndroid Build Coastguard Worker   unsigned getScheduledLatency() const {
685*9880d681SAndroid Build Coastguard Worker     return std::max(ExpectedLatency, CurrCycle);
686*9880d681SAndroid Build Coastguard Worker   }
687*9880d681SAndroid Build Coastguard Worker 
getUnscheduledLatency(SUnit * SU)688*9880d681SAndroid Build Coastguard Worker   unsigned getUnscheduledLatency(SUnit *SU) const {
689*9880d681SAndroid Build Coastguard Worker     return isTop() ? SU->getHeight() : SU->getDepth();
690*9880d681SAndroid Build Coastguard Worker   }
691*9880d681SAndroid Build Coastguard Worker 
getResourceCount(unsigned ResIdx)692*9880d681SAndroid Build Coastguard Worker   unsigned getResourceCount(unsigned ResIdx) const {
693*9880d681SAndroid Build Coastguard Worker     return ExecutedResCounts[ResIdx];
694*9880d681SAndroid Build Coastguard Worker   }
695*9880d681SAndroid Build Coastguard Worker 
696*9880d681SAndroid Build Coastguard Worker   /// Get the scaled count of scheduled micro-ops and resources, including
697*9880d681SAndroid Build Coastguard Worker   /// executed resources.
getCriticalCount()698*9880d681SAndroid Build Coastguard Worker   unsigned getCriticalCount() const {
699*9880d681SAndroid Build Coastguard Worker     if (!ZoneCritResIdx)
700*9880d681SAndroid Build Coastguard Worker       return RetiredMOps * SchedModel->getMicroOpFactor();
701*9880d681SAndroid Build Coastguard Worker     return getResourceCount(ZoneCritResIdx);
702*9880d681SAndroid Build Coastguard Worker   }
703*9880d681SAndroid Build Coastguard Worker 
704*9880d681SAndroid Build Coastguard Worker   /// Get a scaled count for the minimum execution time of the scheduled
705*9880d681SAndroid Build Coastguard Worker   /// micro-ops that are ready to execute by getExecutedCount. Notice the
706*9880d681SAndroid Build Coastguard Worker   /// feedback loop.
getExecutedCount()707*9880d681SAndroid Build Coastguard Worker   unsigned getExecutedCount() const {
708*9880d681SAndroid Build Coastguard Worker     return std::max(CurrCycle * SchedModel->getLatencyFactor(),
709*9880d681SAndroid Build Coastguard Worker                     MaxExecutedResCount);
710*9880d681SAndroid Build Coastguard Worker   }
711*9880d681SAndroid Build Coastguard Worker 
getZoneCritResIdx()712*9880d681SAndroid Build Coastguard Worker   unsigned getZoneCritResIdx() const { return ZoneCritResIdx; }
713*9880d681SAndroid Build Coastguard Worker 
714*9880d681SAndroid Build Coastguard Worker   // Is the scheduled region resource limited vs. latency limited.
isResourceLimited()715*9880d681SAndroid Build Coastguard Worker   bool isResourceLimited() const { return IsResourceLimited; }
716*9880d681SAndroid Build Coastguard Worker 
717*9880d681SAndroid Build Coastguard Worker   /// Get the difference between the given SUnit's ready time and the current
718*9880d681SAndroid Build Coastguard Worker   /// cycle.
719*9880d681SAndroid Build Coastguard Worker   unsigned getLatencyStallCycles(SUnit *SU);
720*9880d681SAndroid Build Coastguard Worker 
721*9880d681SAndroid Build Coastguard Worker   unsigned getNextResourceCycle(unsigned PIdx, unsigned Cycles);
722*9880d681SAndroid Build Coastguard Worker 
723*9880d681SAndroid Build Coastguard Worker   bool checkHazard(SUnit *SU);
724*9880d681SAndroid Build Coastguard Worker 
725*9880d681SAndroid Build Coastguard Worker   unsigned findMaxLatency(ArrayRef<SUnit*> ReadySUs);
726*9880d681SAndroid Build Coastguard Worker 
727*9880d681SAndroid Build Coastguard Worker   unsigned getOtherResourceCount(unsigned &OtherCritIdx);
728*9880d681SAndroid Build Coastguard Worker 
729*9880d681SAndroid Build Coastguard Worker   void releaseNode(SUnit *SU, unsigned ReadyCycle);
730*9880d681SAndroid Build Coastguard Worker 
731*9880d681SAndroid Build Coastguard Worker   void releaseTopNode(SUnit *SU);
732*9880d681SAndroid Build Coastguard Worker 
733*9880d681SAndroid Build Coastguard Worker   void releaseBottomNode(SUnit *SU);
734*9880d681SAndroid Build Coastguard Worker 
735*9880d681SAndroid Build Coastguard Worker   void bumpCycle(unsigned NextCycle);
736*9880d681SAndroid Build Coastguard Worker 
737*9880d681SAndroid Build Coastguard Worker   void incExecutedResources(unsigned PIdx, unsigned Count);
738*9880d681SAndroid Build Coastguard Worker 
739*9880d681SAndroid Build Coastguard Worker   unsigned countResource(unsigned PIdx, unsigned Cycles, unsigned ReadyCycle);
740*9880d681SAndroid Build Coastguard Worker 
741*9880d681SAndroid Build Coastguard Worker   void bumpNode(SUnit *SU);
742*9880d681SAndroid Build Coastguard Worker 
743*9880d681SAndroid Build Coastguard Worker   void releasePending();
744*9880d681SAndroid Build Coastguard Worker 
745*9880d681SAndroid Build Coastguard Worker   void removeReady(SUnit *SU);
746*9880d681SAndroid Build Coastguard Worker 
747*9880d681SAndroid Build Coastguard Worker   /// Call this before applying any other heuristics to the Available queue.
748*9880d681SAndroid Build Coastguard Worker   /// Updates the Available/Pending Q's if necessary and returns the single
749*9880d681SAndroid Build Coastguard Worker   /// available instruction, or NULL if there are multiple candidates.
750*9880d681SAndroid Build Coastguard Worker   SUnit *pickOnlyChoice();
751*9880d681SAndroid Build Coastguard Worker 
752*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
753*9880d681SAndroid Build Coastguard Worker   void dumpScheduledState();
754*9880d681SAndroid Build Coastguard Worker #endif
755*9880d681SAndroid Build Coastguard Worker };
756*9880d681SAndroid Build Coastguard Worker 
757*9880d681SAndroid Build Coastguard Worker /// Base class for GenericScheduler. This class maintains information about
758*9880d681SAndroid Build Coastguard Worker /// scheduling candidates based on TargetSchedModel making it easy to implement
759*9880d681SAndroid Build Coastguard Worker /// heuristics for either preRA or postRA scheduling.
760*9880d681SAndroid Build Coastguard Worker class GenericSchedulerBase : public MachineSchedStrategy {
761*9880d681SAndroid Build Coastguard Worker public:
762*9880d681SAndroid Build Coastguard Worker   /// Represent the type of SchedCandidate found within a single queue.
763*9880d681SAndroid Build Coastguard Worker   /// pickNodeBidirectional depends on these listed by decreasing priority.
764*9880d681SAndroid Build Coastguard Worker   enum CandReason : uint8_t {
765*9880d681SAndroid Build Coastguard Worker     NoCand, Only1, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak,
766*9880d681SAndroid Build Coastguard Worker     RegMax, ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce,
767*9880d681SAndroid Build Coastguard Worker     TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder};
768*9880d681SAndroid Build Coastguard Worker 
769*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
770*9880d681SAndroid Build Coastguard Worker   static const char *getReasonStr(GenericSchedulerBase::CandReason Reason);
771*9880d681SAndroid Build Coastguard Worker #endif
772*9880d681SAndroid Build Coastguard Worker 
773*9880d681SAndroid Build Coastguard Worker   /// Policy for scheduling the next instruction in the candidate's zone.
774*9880d681SAndroid Build Coastguard Worker   struct CandPolicy {
775*9880d681SAndroid Build Coastguard Worker     bool ReduceLatency;
776*9880d681SAndroid Build Coastguard Worker     unsigned ReduceResIdx;
777*9880d681SAndroid Build Coastguard Worker     unsigned DemandResIdx;
778*9880d681SAndroid Build Coastguard Worker 
CandPolicyCandPolicy779*9880d681SAndroid Build Coastguard Worker     CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {}
780*9880d681SAndroid Build Coastguard Worker 
781*9880d681SAndroid Build Coastguard Worker     bool operator==(const CandPolicy &RHS) const {
782*9880d681SAndroid Build Coastguard Worker       return ReduceLatency == RHS.ReduceLatency &&
783*9880d681SAndroid Build Coastguard Worker              ReduceResIdx == RHS.ReduceResIdx &&
784*9880d681SAndroid Build Coastguard Worker              DemandResIdx == RHS.DemandResIdx;
785*9880d681SAndroid Build Coastguard Worker     }
786*9880d681SAndroid Build Coastguard Worker     bool operator!=(const CandPolicy &RHS) const {
787*9880d681SAndroid Build Coastguard Worker       return !(*this == RHS);
788*9880d681SAndroid Build Coastguard Worker     }
789*9880d681SAndroid Build Coastguard Worker   };
790*9880d681SAndroid Build Coastguard Worker 
791*9880d681SAndroid Build Coastguard Worker   /// Status of an instruction's critical resource consumption.
792*9880d681SAndroid Build Coastguard Worker   struct SchedResourceDelta {
793*9880d681SAndroid Build Coastguard Worker     // Count critical resources in the scheduled region required by SU.
794*9880d681SAndroid Build Coastguard Worker     unsigned CritResources;
795*9880d681SAndroid Build Coastguard Worker 
796*9880d681SAndroid Build Coastguard Worker     // Count critical resources from another region consumed by SU.
797*9880d681SAndroid Build Coastguard Worker     unsigned DemandedResources;
798*9880d681SAndroid Build Coastguard Worker 
SchedResourceDeltaSchedResourceDelta799*9880d681SAndroid Build Coastguard Worker     SchedResourceDelta(): CritResources(0), DemandedResources(0) {}
800*9880d681SAndroid Build Coastguard Worker 
801*9880d681SAndroid Build Coastguard Worker     bool operator==(const SchedResourceDelta &RHS) const {
802*9880d681SAndroid Build Coastguard Worker       return CritResources == RHS.CritResources
803*9880d681SAndroid Build Coastguard Worker         && DemandedResources == RHS.DemandedResources;
804*9880d681SAndroid Build Coastguard Worker     }
805*9880d681SAndroid Build Coastguard Worker     bool operator!=(const SchedResourceDelta &RHS) const {
806*9880d681SAndroid Build Coastguard Worker       return !operator==(RHS);
807*9880d681SAndroid Build Coastguard Worker     }
808*9880d681SAndroid Build Coastguard Worker   };
809*9880d681SAndroid Build Coastguard Worker 
810*9880d681SAndroid Build Coastguard Worker   /// Store the state used by GenericScheduler heuristics, required for the
811*9880d681SAndroid Build Coastguard Worker   /// lifetime of one invocation of pickNode().
812*9880d681SAndroid Build Coastguard Worker   struct SchedCandidate {
813*9880d681SAndroid Build Coastguard Worker     CandPolicy Policy;
814*9880d681SAndroid Build Coastguard Worker 
815*9880d681SAndroid Build Coastguard Worker     // The best SUnit candidate.
816*9880d681SAndroid Build Coastguard Worker     SUnit *SU;
817*9880d681SAndroid Build Coastguard Worker 
818*9880d681SAndroid Build Coastguard Worker     // The reason for this candidate.
819*9880d681SAndroid Build Coastguard Worker     CandReason Reason;
820*9880d681SAndroid Build Coastguard Worker 
821*9880d681SAndroid Build Coastguard Worker     // Whether this candidate should be scheduled at top/bottom.
822*9880d681SAndroid Build Coastguard Worker     bool AtTop;
823*9880d681SAndroid Build Coastguard Worker 
824*9880d681SAndroid Build Coastguard Worker     // Register pressure values for the best candidate.
825*9880d681SAndroid Build Coastguard Worker     RegPressureDelta RPDelta;
826*9880d681SAndroid Build Coastguard Worker 
827*9880d681SAndroid Build Coastguard Worker     // Critical resource consumption of the best candidate.
828*9880d681SAndroid Build Coastguard Worker     SchedResourceDelta ResDelta;
829*9880d681SAndroid Build Coastguard Worker 
SchedCandidateSchedCandidate830*9880d681SAndroid Build Coastguard Worker     SchedCandidate() { reset(CandPolicy()); }
SchedCandidateSchedCandidate831*9880d681SAndroid Build Coastguard Worker     SchedCandidate(const CandPolicy &Policy) { reset(Policy); }
832*9880d681SAndroid Build Coastguard Worker 
resetSchedCandidate833*9880d681SAndroid Build Coastguard Worker     void reset(const CandPolicy &NewPolicy) {
834*9880d681SAndroid Build Coastguard Worker       Policy = NewPolicy;
835*9880d681SAndroid Build Coastguard Worker       SU = nullptr;
836*9880d681SAndroid Build Coastguard Worker       Reason = NoCand;
837*9880d681SAndroid Build Coastguard Worker       AtTop = false;
838*9880d681SAndroid Build Coastguard Worker       RPDelta = RegPressureDelta();
839*9880d681SAndroid Build Coastguard Worker       ResDelta = SchedResourceDelta();
840*9880d681SAndroid Build Coastguard Worker     }
841*9880d681SAndroid Build Coastguard Worker 
isValidSchedCandidate842*9880d681SAndroid Build Coastguard Worker     bool isValid() const { return SU; }
843*9880d681SAndroid Build Coastguard Worker 
844*9880d681SAndroid Build Coastguard Worker     // Copy the status of another candidate without changing policy.
setBestSchedCandidate845*9880d681SAndroid Build Coastguard Worker     void setBest(SchedCandidate &Best) {
846*9880d681SAndroid Build Coastguard Worker       assert(Best.Reason != NoCand && "uninitialized Sched candidate");
847*9880d681SAndroid Build Coastguard Worker       SU = Best.SU;
848*9880d681SAndroid Build Coastguard Worker       Reason = Best.Reason;
849*9880d681SAndroid Build Coastguard Worker       AtTop = Best.AtTop;
850*9880d681SAndroid Build Coastguard Worker       RPDelta = Best.RPDelta;
851*9880d681SAndroid Build Coastguard Worker       ResDelta = Best.ResDelta;
852*9880d681SAndroid Build Coastguard Worker     }
853*9880d681SAndroid Build Coastguard Worker 
854*9880d681SAndroid Build Coastguard Worker     void initResourceDelta(const ScheduleDAGMI *DAG,
855*9880d681SAndroid Build Coastguard Worker                            const TargetSchedModel *SchedModel);
856*9880d681SAndroid Build Coastguard Worker   };
857*9880d681SAndroid Build Coastguard Worker 
858*9880d681SAndroid Build Coastguard Worker protected:
859*9880d681SAndroid Build Coastguard Worker   const MachineSchedContext *Context;
860*9880d681SAndroid Build Coastguard Worker   const TargetSchedModel *SchedModel;
861*9880d681SAndroid Build Coastguard Worker   const TargetRegisterInfo *TRI;
862*9880d681SAndroid Build Coastguard Worker 
863*9880d681SAndroid Build Coastguard Worker   SchedRemainder Rem;
864*9880d681SAndroid Build Coastguard Worker protected:
GenericSchedulerBase(const MachineSchedContext * C)865*9880d681SAndroid Build Coastguard Worker   GenericSchedulerBase(const MachineSchedContext *C):
866*9880d681SAndroid Build Coastguard Worker     Context(C), SchedModel(nullptr), TRI(nullptr) {}
867*9880d681SAndroid Build Coastguard Worker 
868*9880d681SAndroid Build Coastguard Worker   void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone,
869*9880d681SAndroid Build Coastguard Worker                  SchedBoundary *OtherZone);
870*9880d681SAndroid Build Coastguard Worker 
871*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
872*9880d681SAndroid Build Coastguard Worker   void traceCandidate(const SchedCandidate &Cand);
873*9880d681SAndroid Build Coastguard Worker #endif
874*9880d681SAndroid Build Coastguard Worker };
875*9880d681SAndroid Build Coastguard Worker 
876*9880d681SAndroid Build Coastguard Worker /// GenericScheduler shrinks the unscheduled zone using heuristics to balance
877*9880d681SAndroid Build Coastguard Worker /// the schedule.
878*9880d681SAndroid Build Coastguard Worker class GenericScheduler : public GenericSchedulerBase {
879*9880d681SAndroid Build Coastguard Worker   ScheduleDAGMILive *DAG;
880*9880d681SAndroid Build Coastguard Worker 
881*9880d681SAndroid Build Coastguard Worker   // State of the top and bottom scheduled instruction boundaries.
882*9880d681SAndroid Build Coastguard Worker   SchedBoundary Top;
883*9880d681SAndroid Build Coastguard Worker   SchedBoundary Bot;
884*9880d681SAndroid Build Coastguard Worker 
885*9880d681SAndroid Build Coastguard Worker   /// Candidate last picked from Top boundary.
886*9880d681SAndroid Build Coastguard Worker   SchedCandidate TopCand;
887*9880d681SAndroid Build Coastguard Worker   /// Candidate last picked from Bot boundary.
888*9880d681SAndroid Build Coastguard Worker   SchedCandidate BotCand;
889*9880d681SAndroid Build Coastguard Worker 
890*9880d681SAndroid Build Coastguard Worker   MachineSchedPolicy RegionPolicy;
891*9880d681SAndroid Build Coastguard Worker public:
GenericScheduler(const MachineSchedContext * C)892*9880d681SAndroid Build Coastguard Worker   GenericScheduler(const MachineSchedContext *C):
893*9880d681SAndroid Build Coastguard Worker     GenericSchedulerBase(C), DAG(nullptr), Top(SchedBoundary::TopQID, "TopQ"),
894*9880d681SAndroid Build Coastguard Worker     Bot(SchedBoundary::BotQID, "BotQ") {}
895*9880d681SAndroid Build Coastguard Worker 
896*9880d681SAndroid Build Coastguard Worker   void initPolicy(MachineBasicBlock::iterator Begin,
897*9880d681SAndroid Build Coastguard Worker                   MachineBasicBlock::iterator End,
898*9880d681SAndroid Build Coastguard Worker                   unsigned NumRegionInstrs) override;
899*9880d681SAndroid Build Coastguard Worker 
900*9880d681SAndroid Build Coastguard Worker   void dumpPolicy() override;
901*9880d681SAndroid Build Coastguard Worker 
shouldTrackPressure()902*9880d681SAndroid Build Coastguard Worker   bool shouldTrackPressure() const override {
903*9880d681SAndroid Build Coastguard Worker     return RegionPolicy.ShouldTrackPressure;
904*9880d681SAndroid Build Coastguard Worker   }
905*9880d681SAndroid Build Coastguard Worker 
shouldTrackLaneMasks()906*9880d681SAndroid Build Coastguard Worker   bool shouldTrackLaneMasks() const override {
907*9880d681SAndroid Build Coastguard Worker     return RegionPolicy.ShouldTrackLaneMasks;
908*9880d681SAndroid Build Coastguard Worker   }
909*9880d681SAndroid Build Coastguard Worker 
910*9880d681SAndroid Build Coastguard Worker   void initialize(ScheduleDAGMI *dag) override;
911*9880d681SAndroid Build Coastguard Worker 
912*9880d681SAndroid Build Coastguard Worker   SUnit *pickNode(bool &IsTopNode) override;
913*9880d681SAndroid Build Coastguard Worker 
914*9880d681SAndroid Build Coastguard Worker   void schedNode(SUnit *SU, bool IsTopNode) override;
915*9880d681SAndroid Build Coastguard Worker 
releaseTopNode(SUnit * SU)916*9880d681SAndroid Build Coastguard Worker   void releaseTopNode(SUnit *SU) override {
917*9880d681SAndroid Build Coastguard Worker     Top.releaseTopNode(SU);
918*9880d681SAndroid Build Coastguard Worker     TopCand.SU = nullptr;
919*9880d681SAndroid Build Coastguard Worker   }
920*9880d681SAndroid Build Coastguard Worker 
releaseBottomNode(SUnit * SU)921*9880d681SAndroid Build Coastguard Worker   void releaseBottomNode(SUnit *SU) override {
922*9880d681SAndroid Build Coastguard Worker     Bot.releaseBottomNode(SU);
923*9880d681SAndroid Build Coastguard Worker     BotCand.SU = nullptr;
924*9880d681SAndroid Build Coastguard Worker   }
925*9880d681SAndroid Build Coastguard Worker 
926*9880d681SAndroid Build Coastguard Worker   void registerRoots() override;
927*9880d681SAndroid Build Coastguard Worker 
928*9880d681SAndroid Build Coastguard Worker protected:
929*9880d681SAndroid Build Coastguard Worker   void checkAcyclicLatency();
930*9880d681SAndroid Build Coastguard Worker 
931*9880d681SAndroid Build Coastguard Worker   void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop,
932*9880d681SAndroid Build Coastguard Worker                      const RegPressureTracker &RPTracker,
933*9880d681SAndroid Build Coastguard Worker                      RegPressureTracker &TempTracker);
934*9880d681SAndroid Build Coastguard Worker 
935*9880d681SAndroid Build Coastguard Worker   void tryCandidate(SchedCandidate &Cand,
936*9880d681SAndroid Build Coastguard Worker                     SchedCandidate &TryCand,
937*9880d681SAndroid Build Coastguard Worker                     SchedBoundary *Zone);
938*9880d681SAndroid Build Coastguard Worker 
939*9880d681SAndroid Build Coastguard Worker   SUnit *pickNodeBidirectional(bool &IsTopNode);
940*9880d681SAndroid Build Coastguard Worker 
941*9880d681SAndroid Build Coastguard Worker   void pickNodeFromQueue(SchedBoundary &Zone,
942*9880d681SAndroid Build Coastguard Worker                          const CandPolicy &ZonePolicy,
943*9880d681SAndroid Build Coastguard Worker                          const RegPressureTracker &RPTracker,
944*9880d681SAndroid Build Coastguard Worker                          SchedCandidate &Candidate);
945*9880d681SAndroid Build Coastguard Worker 
946*9880d681SAndroid Build Coastguard Worker   void reschedulePhysRegCopies(SUnit *SU, bool isTop);
947*9880d681SAndroid Build Coastguard Worker };
948*9880d681SAndroid Build Coastguard Worker 
949*9880d681SAndroid Build Coastguard Worker /// PostGenericScheduler - Interface to the scheduling algorithm used by
950*9880d681SAndroid Build Coastguard Worker /// ScheduleDAGMI.
951*9880d681SAndroid Build Coastguard Worker ///
952*9880d681SAndroid Build Coastguard Worker /// Callbacks from ScheduleDAGMI:
953*9880d681SAndroid Build Coastguard Worker ///   initPolicy -> initialize(DAG) -> registerRoots -> pickNode ...
954*9880d681SAndroid Build Coastguard Worker class PostGenericScheduler : public GenericSchedulerBase {
955*9880d681SAndroid Build Coastguard Worker   ScheduleDAGMI *DAG;
956*9880d681SAndroid Build Coastguard Worker   SchedBoundary Top;
957*9880d681SAndroid Build Coastguard Worker   SmallVector<SUnit*, 8> BotRoots;
958*9880d681SAndroid Build Coastguard Worker public:
PostGenericScheduler(const MachineSchedContext * C)959*9880d681SAndroid Build Coastguard Worker   PostGenericScheduler(const MachineSchedContext *C):
960*9880d681SAndroid Build Coastguard Worker     GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {}
961*9880d681SAndroid Build Coastguard Worker 
~PostGenericScheduler()962*9880d681SAndroid Build Coastguard Worker   ~PostGenericScheduler() override {}
963*9880d681SAndroid Build Coastguard Worker 
initPolicy(MachineBasicBlock::iterator Begin,MachineBasicBlock::iterator End,unsigned NumRegionInstrs)964*9880d681SAndroid Build Coastguard Worker   void initPolicy(MachineBasicBlock::iterator Begin,
965*9880d681SAndroid Build Coastguard Worker                   MachineBasicBlock::iterator End,
966*9880d681SAndroid Build Coastguard Worker                   unsigned NumRegionInstrs) override {
967*9880d681SAndroid Build Coastguard Worker     /* no configurable policy */
968*9880d681SAndroid Build Coastguard Worker   }
969*9880d681SAndroid Build Coastguard Worker 
970*9880d681SAndroid Build Coastguard Worker   /// PostRA scheduling does not track pressure.
shouldTrackPressure()971*9880d681SAndroid Build Coastguard Worker   bool shouldTrackPressure() const override { return false; }
972*9880d681SAndroid Build Coastguard Worker 
973*9880d681SAndroid Build Coastguard Worker   void initialize(ScheduleDAGMI *Dag) override;
974*9880d681SAndroid Build Coastguard Worker 
975*9880d681SAndroid Build Coastguard Worker   void registerRoots() override;
976*9880d681SAndroid Build Coastguard Worker 
977*9880d681SAndroid Build Coastguard Worker   SUnit *pickNode(bool &IsTopNode) override;
978*9880d681SAndroid Build Coastguard Worker 
scheduleTree(unsigned SubtreeID)979*9880d681SAndroid Build Coastguard Worker   void scheduleTree(unsigned SubtreeID) override {
980*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("PostRA scheduler does not support subtree analysis.");
981*9880d681SAndroid Build Coastguard Worker   }
982*9880d681SAndroid Build Coastguard Worker 
983*9880d681SAndroid Build Coastguard Worker   void schedNode(SUnit *SU, bool IsTopNode) override;
984*9880d681SAndroid Build Coastguard Worker 
releaseTopNode(SUnit * SU)985*9880d681SAndroid Build Coastguard Worker   void releaseTopNode(SUnit *SU) override {
986*9880d681SAndroid Build Coastguard Worker     Top.releaseTopNode(SU);
987*9880d681SAndroid Build Coastguard Worker   }
988*9880d681SAndroid Build Coastguard Worker 
989*9880d681SAndroid Build Coastguard Worker   // Only called for roots.
releaseBottomNode(SUnit * SU)990*9880d681SAndroid Build Coastguard Worker   void releaseBottomNode(SUnit *SU) override {
991*9880d681SAndroid Build Coastguard Worker     BotRoots.push_back(SU);
992*9880d681SAndroid Build Coastguard Worker   }
993*9880d681SAndroid Build Coastguard Worker 
994*9880d681SAndroid Build Coastguard Worker protected:
995*9880d681SAndroid Build Coastguard Worker   void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand);
996*9880d681SAndroid Build Coastguard Worker 
997*9880d681SAndroid Build Coastguard Worker   void pickNodeFromQueue(SchedCandidate &Cand);
998*9880d681SAndroid Build Coastguard Worker };
999*9880d681SAndroid Build Coastguard Worker 
1000*9880d681SAndroid Build Coastguard Worker } // namespace llvm
1001*9880d681SAndroid Build Coastguard Worker 
1002*9880d681SAndroid Build Coastguard Worker #endif
1003