1 //===- MachinePipeliner.h - Machine Software Pipeliner Pass -------------===//
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 // An implementation of the Swing Modulo Scheduling (SMS) software pipeliner.
10 //
11 // Software pipelining (SWP) is an instruction scheduling technique for loops
12 // that overlap loop iterations and exploits ILP via a compiler transformation.
13 //
14 // Swing Modulo Scheduling is an implementation of software pipelining
15 // that generates schedules that are near optimal in terms of initiation
16 // interval, register requirements, and stage count. See the papers:
17 //
18 // "Swing Modulo Scheduling: A Lifetime-Sensitive Approach", by J. Llosa,
19 // A. Gonzalez, E. Ayguade, and M. Valero. In PACT '96 Proceedings of the 1996
20 // Conference on Parallel Architectures and Compilation Techiniques.
21 //
22 // "Lifetime-Sensitive Modulo Scheduling in a Production Environment", by J.
23 // Llosa, E. Ayguade, A. Gonzalez, M. Valero, and J. Eckhardt. In IEEE
24 // Transactions on Computers, Vol. 50, No. 3, 2001.
25 //
26 // "An Implementation of Swing Modulo Scheduling With Extensions for
27 // Superblocks", by T. Lattner, Master's Thesis, University of Illinois at
28 // Urbana-Champaign, 2005.
29 //
30 //
31 // The SMS algorithm consists of three main steps after computing the minimal
32 // initiation interval (MII).
33 // 1) Analyze the dependence graph and compute information about each
34 //    instruction in the graph.
35 // 2) Order the nodes (instructions) by priority based upon the heuristics
36 //    described in the algorithm.
37 // 3) Attempt to schedule the nodes in the specified order using the MII.
38 //
39 //===----------------------------------------------------------------------===//
40 #ifndef LLVM_CODEGEN_MACHINEPIPELINER_H
41 #define LLVM_CODEGEN_MACHINEPIPELINER_H
42 
43 #include "llvm/CodeGen/MachineDominators.h"
44 #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
45 #include "llvm/CodeGen/RegisterClassInfo.h"
46 #include "llvm/CodeGen/ScheduleDAGInstrs.h"
47 #include "llvm/CodeGen/TargetInstrInfo.h"
48 #include "llvm/InitializePasses.h"
49 
50 namespace llvm {
51 
52 class AAResults;
53 class NodeSet;
54 class SMSchedule;
55 
56 extern cl::opt<bool> SwpEnableCopyToPhi;
57 
58 /// The main class in the implementation of the target independent
59 /// software pipeliner pass.
60 class MachinePipeliner : public MachineFunctionPass {
61 public:
62   MachineFunction *MF = nullptr;
63   MachineOptimizationRemarkEmitter *ORE = nullptr;
64   const MachineLoopInfo *MLI = nullptr;
65   const MachineDominatorTree *MDT = nullptr;
66   const InstrItineraryData *InstrItins;
67   const TargetInstrInfo *TII = nullptr;
68   RegisterClassInfo RegClassInfo;
69   bool disabledByPragma = false;
70   unsigned II_setByPragma = 0;
71 
72 #ifndef NDEBUG
73   static int NumTries;
74 #endif
75 
76   /// Cache the target analysis information about the loop.
77   struct LoopInfo {
78     MachineBasicBlock *TBB = nullptr;
79     MachineBasicBlock *FBB = nullptr;
80     SmallVector<MachineOperand, 4> BrCond;
81     MachineInstr *LoopInductionVar = nullptr;
82     MachineInstr *LoopCompare = nullptr;
83   };
84   LoopInfo LI;
85 
86   static char ID;
87 
88   MachinePipeliner() : MachineFunctionPass(ID) {
89     initializeMachinePipelinerPass(*PassRegistry::getPassRegistry());
90   }
91 
92   bool runOnMachineFunction(MachineFunction &MF) override;
93 
94   void getAnalysisUsage(AnalysisUsage &AU) const override;
95 
96 private:
97   void preprocessPhiNodes(MachineBasicBlock &B);
98   bool canPipelineLoop(MachineLoop &L);
99   bool scheduleLoop(MachineLoop &L);
100   bool swingModuloScheduler(MachineLoop &L);
101   void setPragmaPipelineOptions(MachineLoop &L);
102 };
103 
104 /// This class builds the dependence graph for the instructions in a loop,
105 /// and attempts to schedule the instructions using the SMS algorithm.
106 class SwingSchedulerDAG : public ScheduleDAGInstrs {
107   MachinePipeliner &Pass;
108   /// The minimum initiation interval between iterations for this schedule.
109   unsigned MII = 0;
110   /// The maximum initiation interval between iterations for this schedule.
111   unsigned MAX_II = 0;
112   /// Set to true if a valid pipelined schedule is found for the loop.
113   bool Scheduled = false;
114   MachineLoop &Loop;
115   LiveIntervals &LIS;
116   const RegisterClassInfo &RegClassInfo;
117   unsigned II_setByPragma = 0;
118 
119   /// A toplogical ordering of the SUnits, which is needed for changing
120   /// dependences and iterating over the SUnits.
121   ScheduleDAGTopologicalSort Topo;
122 
123   struct NodeInfo {
124     int ASAP = 0;
125     int ALAP = 0;
126     int ZeroLatencyDepth = 0;
127     int ZeroLatencyHeight = 0;
128 
129     NodeInfo() = default;
130   };
131   /// Computed properties for each node in the graph.
132   std::vector<NodeInfo> ScheduleInfo;
133 
134   enum OrderKind { BottomUp = 0, TopDown = 1 };
135   /// Computed node ordering for scheduling.
136   SetVector<SUnit *> NodeOrder;
137 
138   using NodeSetType = SmallVector<NodeSet, 8>;
139   using ValueMapTy = DenseMap<unsigned, unsigned>;
140   using MBBVectorTy = SmallVectorImpl<MachineBasicBlock *>;
141   using InstrMapTy = DenseMap<MachineInstr *, MachineInstr *>;
142 
143   /// Instructions to change when emitting the final schedule.
144   DenseMap<SUnit *, std::pair<unsigned, int64_t>> InstrChanges;
145 
146   /// We may create a new instruction, so remember it because it
147   /// must be deleted when the pass is finished.
148   DenseMap<MachineInstr*, MachineInstr *> NewMIs;
149 
150   /// Ordered list of DAG postprocessing steps.
151   std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
152 
153   /// Helper class to implement Johnson's circuit finding algorithm.
154   class Circuits {
155     std::vector<SUnit> &SUnits;
156     SetVector<SUnit *> Stack;
157     BitVector Blocked;
158     SmallVector<SmallPtrSet<SUnit *, 4>, 10> B;
159     SmallVector<SmallVector<int, 4>, 16> AdjK;
160     // Node to Index from ScheduleDAGTopologicalSort
161     std::vector<int> *Node2Idx;
162     unsigned NumPaths;
163     static unsigned MaxPaths;
164 
165   public:
166     Circuits(std::vector<SUnit> &SUs, ScheduleDAGTopologicalSort &Topo)
167         : SUnits(SUs), Blocked(SUs.size()), B(SUs.size()), AdjK(SUs.size()) {
168       Node2Idx = new std::vector<int>(SUs.size());
169       unsigned Idx = 0;
170       for (const auto &NodeNum : Topo)
171         Node2Idx->at(NodeNum) = Idx++;
172     }
173 
174     ~Circuits() { delete Node2Idx; }
175 
176     /// Reset the data structures used in the circuit algorithm.
177     void reset() {
178       Stack.clear();
179       Blocked.reset();
180       B.assign(SUnits.size(), SmallPtrSet<SUnit *, 4>());
181       NumPaths = 0;
182     }
183 
184     void createAdjacencyStructure(SwingSchedulerDAG *DAG);
185     bool circuit(int V, int S, NodeSetType &NodeSets, bool HasBackedge = false);
186     void unblock(int U);
187   };
188 
189   struct CopyToPhiMutation : public ScheduleDAGMutation {
190     void apply(ScheduleDAGInstrs *DAG) override;
191   };
192 
193 public:
194   SwingSchedulerDAG(MachinePipeliner &P, MachineLoop &L, LiveIntervals &lis,
195                     const RegisterClassInfo &rci, unsigned II)
196       : ScheduleDAGInstrs(*P.MF, P.MLI, false), Pass(P), Loop(L), LIS(lis),
197         RegClassInfo(rci), II_setByPragma(II), Topo(SUnits, &ExitSU) {
198     P.MF->getSubtarget().getSMSMutations(Mutations);
199     if (SwpEnableCopyToPhi)
200       Mutations.push_back(std::make_unique<CopyToPhiMutation>());
201   }
202 
203   void schedule() override;
204   void finishBlock() override;
205 
206   /// Return true if the loop kernel has been scheduled.
207   bool hasNewSchedule() { return Scheduled; }
208 
209   /// Return the earliest time an instruction may be scheduled.
210   int getASAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ASAP; }
211 
212   /// Return the latest time an instruction my be scheduled.
213   int getALAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ALAP; }
214 
215   /// The mobility function, which the number of slots in which
216   /// an instruction may be scheduled.
217   int getMOV(SUnit *Node) { return getALAP(Node) - getASAP(Node); }
218 
219   /// The depth, in the dependence graph, for a node.
220   unsigned getDepth(SUnit *Node) { return Node->getDepth(); }
221 
222   /// The maximum unweighted length of a path from an arbitrary node to the
223   /// given node in which each edge has latency 0
224   int getZeroLatencyDepth(SUnit *Node) {
225     return ScheduleInfo[Node->NodeNum].ZeroLatencyDepth;
226   }
227 
228   /// The height, in the dependence graph, for a node.
229   unsigned getHeight(SUnit *Node) { return Node->getHeight(); }
230 
231   /// The maximum unweighted length of a path from the given node to an
232   /// arbitrary node in which each edge has latency 0
233   int getZeroLatencyHeight(SUnit *Node) {
234     return ScheduleInfo[Node->NodeNum].ZeroLatencyHeight;
235   }
236 
237   /// Return true if the dependence is a back-edge in the data dependence graph.
238   /// Since the DAG doesn't contain cycles, we represent a cycle in the graph
239   /// using an anti dependence from a Phi to an instruction.
240   bool isBackedge(SUnit *Source, const SDep &Dep) {
241     if (Dep.getKind() != SDep::Anti)
242       return false;
243     return Source->getInstr()->isPHI() || Dep.getSUnit()->getInstr()->isPHI();
244   }
245 
246   bool isLoopCarriedDep(SUnit *Source, const SDep &Dep, bool isSucc = true);
247 
248   /// The distance function, which indicates that operation V of iteration I
249   /// depends on operations U of iteration I-distance.
250   unsigned getDistance(SUnit *U, SUnit *V, const SDep &Dep) {
251     // Instructions that feed a Phi have a distance of 1. Computing larger
252     // values for arrays requires data dependence information.
253     if (V->getInstr()->isPHI() && Dep.getKind() == SDep::Anti)
254       return 1;
255     return 0;
256   }
257 
258   void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule);
259 
260   void fixupRegisterOverlaps(std::deque<SUnit *> &Instrs);
261 
262   /// Return the new base register that was stored away for the changed
263   /// instruction.
264   unsigned getInstrBaseReg(SUnit *SU) {
265     DenseMap<SUnit *, std::pair<unsigned, int64_t>>::iterator It =
266         InstrChanges.find(SU);
267     if (It != InstrChanges.end())
268       return It->second.first;
269     return 0;
270   }
271 
272   void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
273     Mutations.push_back(std::move(Mutation));
274   }
275 
276   static bool classof(const ScheduleDAGInstrs *DAG) { return true; }
277 
278 private:
279   void addLoopCarriedDependences(AAResults *AA);
280   void updatePhiDependences();
281   void changeDependences();
282   unsigned calculateResMII();
283   unsigned calculateRecMII(NodeSetType &RecNodeSets);
284   void findCircuits(NodeSetType &NodeSets);
285   void fuseRecs(NodeSetType &NodeSets);
286   void removeDuplicateNodes(NodeSetType &NodeSets);
287   void computeNodeFunctions(NodeSetType &NodeSets);
288   void registerPressureFilter(NodeSetType &NodeSets);
289   void colocateNodeSets(NodeSetType &NodeSets);
290   void checkNodeSets(NodeSetType &NodeSets);
291   void groupRemainingNodes(NodeSetType &NodeSets);
292   void addConnectedNodes(SUnit *SU, NodeSet &NewSet,
293                          SetVector<SUnit *> &NodesAdded);
294   void computeNodeOrder(NodeSetType &NodeSets);
295   void checkValidNodeOrder(const NodeSetType &Circuits) const;
296   bool schedulePipeline(SMSchedule &Schedule);
297   bool computeDelta(MachineInstr &MI, unsigned &Delta);
298   MachineInstr *findDefInLoop(Register Reg);
299   bool canUseLastOffsetValue(MachineInstr *MI, unsigned &BasePos,
300                              unsigned &OffsetPos, unsigned &NewBase,
301                              int64_t &NewOffset);
302   void postprocessDAG();
303   /// Set the Minimum Initiation Interval for this schedule attempt.
304   void setMII(unsigned ResMII, unsigned RecMII);
305   /// Set the Maximum Initiation Interval for this schedule attempt.
306   void setMAX_II();
307 };
308 
309 /// A NodeSet contains a set of SUnit DAG nodes with additional information
310 /// that assigns a priority to the set.
311 class NodeSet {
312   SetVector<SUnit *> Nodes;
313   bool HasRecurrence = false;
314   unsigned RecMII = 0;
315   int MaxMOV = 0;
316   unsigned MaxDepth = 0;
317   unsigned Colocate = 0;
318   SUnit *ExceedPressure = nullptr;
319   unsigned Latency = 0;
320 
321 public:
322   using iterator = SetVector<SUnit *>::const_iterator;
323 
324   NodeSet() = default;
325   NodeSet(iterator S, iterator E) : Nodes(S, E), HasRecurrence(true) {
326     Latency = 0;
327     for (unsigned i = 0, e = Nodes.size(); i < e; ++i) {
328       DenseMap<SUnit *, unsigned> SuccSUnitLatency;
329       for (const SDep &Succ : Nodes[i]->Succs) {
330         auto SuccSUnit = Succ.getSUnit();
331         if (!Nodes.count(SuccSUnit))
332           continue;
333         unsigned CurLatency = Succ.getLatency();
334         unsigned MaxLatency = 0;
335         if (SuccSUnitLatency.count(SuccSUnit))
336           MaxLatency = SuccSUnitLatency[SuccSUnit];
337         if (CurLatency > MaxLatency)
338           SuccSUnitLatency[SuccSUnit] = CurLatency;
339       }
340       for (auto SUnitLatency : SuccSUnitLatency)
341         Latency += SUnitLatency.second;
342     }
343   }
344 
345   bool insert(SUnit *SU) { return Nodes.insert(SU); }
346 
347   void insert(iterator S, iterator E) { Nodes.insert(S, E); }
348 
349   template <typename UnaryPredicate> bool remove_if(UnaryPredicate P) {
350     return Nodes.remove_if(P);
351   }
352 
353   unsigned count(SUnit *SU) const { return Nodes.count(SU); }
354 
355   bool hasRecurrence() { return HasRecurrence; };
356 
357   unsigned size() const { return Nodes.size(); }
358 
359   bool empty() const { return Nodes.empty(); }
360 
361   SUnit *getNode(unsigned i) const { return Nodes[i]; };
362 
363   void setRecMII(unsigned mii) { RecMII = mii; };
364 
365   void setColocate(unsigned c) { Colocate = c; };
366 
367   void setExceedPressure(SUnit *SU) { ExceedPressure = SU; }
368 
369   bool isExceedSU(SUnit *SU) { return ExceedPressure == SU; }
370 
371   int compareRecMII(NodeSet &RHS) { return RecMII - RHS.RecMII; }
372 
373   int getRecMII() { return RecMII; }
374 
375   /// Summarize node functions for the entire node set.
376   void computeNodeSetInfo(SwingSchedulerDAG *SSD) {
377     for (SUnit *SU : *this) {
378       MaxMOV = std::max(MaxMOV, SSD->getMOV(SU));
379       MaxDepth = std::max(MaxDepth, SSD->getDepth(SU));
380     }
381   }
382 
383   unsigned getLatency() { return Latency; }
384 
385   unsigned getMaxDepth() { return MaxDepth; }
386 
387   void clear() {
388     Nodes.clear();
389     RecMII = 0;
390     HasRecurrence = false;
391     MaxMOV = 0;
392     MaxDepth = 0;
393     Colocate = 0;
394     ExceedPressure = nullptr;
395   }
396 
397   operator SetVector<SUnit *> &() { return Nodes; }
398 
399   /// Sort the node sets by importance. First, rank them by recurrence MII,
400   /// then by mobility (least mobile done first), and finally by depth.
401   /// Each node set may contain a colocate value which is used as the first
402   /// tie breaker, if it's set.
403   bool operator>(const NodeSet &RHS) const {
404     if (RecMII == RHS.RecMII) {
405       if (Colocate != 0 && RHS.Colocate != 0 && Colocate != RHS.Colocate)
406         return Colocate < RHS.Colocate;
407       if (MaxMOV == RHS.MaxMOV)
408         return MaxDepth > RHS.MaxDepth;
409       return MaxMOV < RHS.MaxMOV;
410     }
411     return RecMII > RHS.RecMII;
412   }
413 
414   bool operator==(const NodeSet &RHS) const {
415     return RecMII == RHS.RecMII && MaxMOV == RHS.MaxMOV &&
416            MaxDepth == RHS.MaxDepth;
417   }
418 
419   bool operator!=(const NodeSet &RHS) const { return !operator==(RHS); }
420 
421   iterator begin() { return Nodes.begin(); }
422   iterator end() { return Nodes.end(); }
423   void print(raw_ostream &os) const;
424 
425 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
426   LLVM_DUMP_METHOD void dump() const;
427 #endif
428 };
429 
430 // 16 was selected based on the number of ProcResource kinds for all
431 // existing Subtargets, so that SmallVector don't need to resize too often.
432 static const int DefaultProcResSize = 16;
433 
434 class ResourceManager {
435 private:
436   const MCSubtargetInfo *STI;
437   const MCSchedModel &SM;
438   const bool UseDFA;
439   std::unique_ptr<DFAPacketizer> DFAResources;
440   /// Each processor resource is associated with a so-called processor resource
441   /// mask. This vector allows to correlate processor resource IDs with
442   /// processor resource masks. There is exactly one element per each processor
443   /// resource declared by the scheduling model.
444   llvm::SmallVector<uint64_t, DefaultProcResSize> ProcResourceMasks;
445 
446   llvm::SmallVector<uint64_t, DefaultProcResSize> ProcResourceCount;
447 
448 public:
449   ResourceManager(const TargetSubtargetInfo *ST)
450       : STI(ST), SM(ST->getSchedModel()), UseDFA(ST->useDFAforSMS()),
451         ProcResourceMasks(SM.getNumProcResourceKinds(), 0),
452         ProcResourceCount(SM.getNumProcResourceKinds(), 0) {
453     if (UseDFA)
454       DFAResources.reset(ST->getInstrInfo()->CreateTargetScheduleState(*ST));
455     initProcResourceVectors(SM, ProcResourceMasks);
456   }
457 
458   void initProcResourceVectors(const MCSchedModel &SM,
459                                SmallVectorImpl<uint64_t> &Masks);
460   /// Check if the resources occupied by a MCInstrDesc are available in
461   /// the current state.
462   bool canReserveResources(const MCInstrDesc *MID) const;
463 
464   /// Reserve the resources occupied by a MCInstrDesc and change the current
465   /// state to reflect that change.
466   void reserveResources(const MCInstrDesc *MID);
467 
468   /// Check if the resources occupied by a machine instruction are available
469   /// in the current state.
470   bool canReserveResources(const MachineInstr &MI) const;
471 
472   /// Reserve the resources occupied by a machine instruction and change the
473   /// current state to reflect that change.
474   void reserveResources(const MachineInstr &MI);
475 
476   /// Reset the state
477   void clearResources();
478 };
479 
480 /// This class represents the scheduled code.  The main data structure is a
481 /// map from scheduled cycle to instructions.  During scheduling, the
482 /// data structure explicitly represents all stages/iterations.   When
483 /// the algorithm finshes, the schedule is collapsed into a single stage,
484 /// which represents instructions from different loop iterations.
485 ///
486 /// The SMS algorithm allows negative values for cycles, so the first cycle
487 /// in the schedule is the smallest cycle value.
488 class SMSchedule {
489 private:
490   /// Map from execution cycle to instructions.
491   DenseMap<int, std::deque<SUnit *>> ScheduledInstrs;
492 
493   /// Map from instruction to execution cycle.
494   std::map<SUnit *, int> InstrToCycle;
495 
496   /// Keep track of the first cycle value in the schedule.  It starts
497   /// as zero, but the algorithm allows negative values.
498   int FirstCycle = 0;
499 
500   /// Keep track of the last cycle value in the schedule.
501   int LastCycle = 0;
502 
503   /// The initiation interval (II) for the schedule.
504   int InitiationInterval = 0;
505 
506   /// Target machine information.
507   const TargetSubtargetInfo &ST;
508 
509   /// Virtual register information.
510   MachineRegisterInfo &MRI;
511 
512   ResourceManager ProcItinResources;
513 
514 public:
515   SMSchedule(MachineFunction *mf)
516       : ST(mf->getSubtarget()), MRI(mf->getRegInfo()), ProcItinResources(&ST) {}
517 
518   void reset() {
519     ScheduledInstrs.clear();
520     InstrToCycle.clear();
521     FirstCycle = 0;
522     LastCycle = 0;
523     InitiationInterval = 0;
524   }
525 
526   /// Set the initiation interval for this schedule.
527   void setInitiationInterval(int ii) { InitiationInterval = ii; }
528 
529   /// Return the initiation interval for this schedule.
530   int getInitiationInterval() const { return InitiationInterval; }
531 
532   /// Return the first cycle in the completed schedule.  This
533   /// can be a negative value.
534   int getFirstCycle() const { return FirstCycle; }
535 
536   /// Return the last cycle in the finalized schedule.
537   int getFinalCycle() const { return FirstCycle + InitiationInterval - 1; }
538 
539   /// Return the cycle of the earliest scheduled instruction in the dependence
540   /// chain.
541   int earliestCycleInChain(const SDep &Dep);
542 
543   /// Return the cycle of the latest scheduled instruction in the dependence
544   /// chain.
545   int latestCycleInChain(const SDep &Dep);
546 
547   void computeStart(SUnit *SU, int *MaxEarlyStart, int *MinLateStart,
548                     int *MinEnd, int *MaxStart, int II, SwingSchedulerDAG *DAG);
549   bool insert(SUnit *SU, int StartCycle, int EndCycle, int II);
550 
551   /// Iterators for the cycle to instruction map.
552   using sched_iterator = DenseMap<int, std::deque<SUnit *>>::iterator;
553   using const_sched_iterator =
554       DenseMap<int, std::deque<SUnit *>>::const_iterator;
555 
556   /// Return true if the instruction is scheduled at the specified stage.
557   bool isScheduledAtStage(SUnit *SU, unsigned StageNum) {
558     return (stageScheduled(SU) == (int)StageNum);
559   }
560 
561   /// Return the stage for a scheduled instruction.  Return -1 if
562   /// the instruction has not been scheduled.
563   int stageScheduled(SUnit *SU) const {
564     std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU);
565     if (it == InstrToCycle.end())
566       return -1;
567     return (it->second - FirstCycle) / InitiationInterval;
568   }
569 
570   /// Return the cycle for a scheduled instruction. This function normalizes
571   /// the first cycle to be 0.
572   unsigned cycleScheduled(SUnit *SU) const {
573     std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU);
574     assert(it != InstrToCycle.end() && "Instruction hasn't been scheduled.");
575     return (it->second - FirstCycle) % InitiationInterval;
576   }
577 
578   /// Return the maximum stage count needed for this schedule.
579   unsigned getMaxStageCount() {
580     return (LastCycle - FirstCycle) / InitiationInterval;
581   }
582 
583   /// Return the instructions that are scheduled at the specified cycle.
584   std::deque<SUnit *> &getInstructions(int cycle) {
585     return ScheduledInstrs[cycle];
586   }
587 
588   bool isValidSchedule(SwingSchedulerDAG *SSD);
589   void finalizeSchedule(SwingSchedulerDAG *SSD);
590   void orderDependence(SwingSchedulerDAG *SSD, SUnit *SU,
591                        std::deque<SUnit *> &Insts);
592   bool isLoopCarried(SwingSchedulerDAG *SSD, MachineInstr &Phi);
593   bool isLoopCarriedDefOfUse(SwingSchedulerDAG *SSD, MachineInstr *Def,
594                              MachineOperand &MO);
595   void print(raw_ostream &os) const;
596   void dump() const;
597 };
598 
599 } // end namespace llvm
600 
601 #endif // LLVM_CODEGEN_MACHINEPIPELINER_H
602