1293838Sdim//===-- SIMachineScheduler.h - SI Scheduler Interface -*- C++ -*-------===//
2293838Sdim//
3293838Sdim//                     The LLVM Compiler Infrastructure
4293838Sdim//
5293838Sdim// This file is distributed under the University of Illinois Open Source
6293838Sdim// License. See LICENSE.TXT for details.
7293838Sdim//
8293838Sdim//===----------------------------------------------------------------------===//
9293838Sdim//
10293838Sdim/// \file
11293838Sdim/// \brief SI Machine Scheduler interface
12293838Sdim//
13293838Sdim//===----------------------------------------------------------------------===//
14293838Sdim
15293838Sdim#ifndef LLVM_LIB_TARGET_AMDGPU_SIMACHINESCHEDULER_H
16293838Sdim#define LLVM_LIB_TARGET_AMDGPU_SIMACHINESCHEDULER_H
17293838Sdim
18293838Sdim#include "SIInstrInfo.h"
19293838Sdim#include "llvm/CodeGen/MachineScheduler.h"
20293838Sdim#include "llvm/CodeGen/RegisterPressure.h"
21293838Sdim
22293838Sdimusing namespace llvm;
23293838Sdim
24293838Sdimnamespace llvm {
25293838Sdim
26293838Sdimenum SIScheduleCandReason {
27293838Sdim  NoCand,
28293838Sdim  RegUsage,
29293838Sdim  Latency,
30293838Sdim  Successor,
31293838Sdim  Depth,
32293838Sdim  NodeOrder
33293838Sdim};
34293838Sdim
35293838Sdimstruct SISchedulerCandidate {
36293838Sdim  // The reason for this candidate.
37293838Sdim  SIScheduleCandReason Reason;
38293838Sdim
39293838Sdim  // Set of reasons that apply to multiple candidates.
40293838Sdim  uint32_t RepeatReasonSet;
41293838Sdim
42293838Sdim  SISchedulerCandidate()
43293838Sdim    :  Reason(NoCand), RepeatReasonSet(0) {}
44293838Sdim
45293838Sdim  bool isRepeat(SIScheduleCandReason R) { return RepeatReasonSet & (1 << R); }
46293838Sdim  void setRepeat(SIScheduleCandReason R) { RepeatReasonSet |= (1 << R); }
47293838Sdim};
48293838Sdim
49293838Sdimclass SIScheduleDAGMI;
50293838Sdimclass SIScheduleBlockCreator;
51293838Sdim
52293838Sdimclass SIScheduleBlock {
53293838Sdim  SIScheduleDAGMI *DAG;
54293838Sdim  SIScheduleBlockCreator *BC;
55293838Sdim
56293838Sdim  std::vector<SUnit*> SUnits;
57293838Sdim  std::map<unsigned, unsigned> NodeNum2Index;
58293838Sdim  std::vector<SUnit*> TopReadySUs;
59293838Sdim  std::vector<SUnit*> ScheduledSUnits;
60293838Sdim
61293838Sdim  /// The top of the unscheduled zone.
62293838Sdim  IntervalPressure TopPressure;
63293838Sdim  RegPressureTracker TopRPTracker;
64293838Sdim
65293838Sdim  // Pressure: number of said class of registers needed to
66293838Sdim  // store the live virtual and real registers.
67293838Sdim  // We do care only of SGPR32 and VGPR32 and do track only virtual registers.
68293838Sdim  // Pressure of additional registers required inside the block.
69293838Sdim  std::vector<unsigned> InternalAdditionnalPressure;
70293838Sdim  // Pressure of input and output registers
71293838Sdim  std::vector<unsigned> LiveInPressure;
72293838Sdim  std::vector<unsigned> LiveOutPressure;
73293838Sdim  // Registers required by the block, and outputs.
74293838Sdim  // We do track only virtual registers.
75293838Sdim  // Note that some registers are not 32 bits,
76293838Sdim  // and thus the pressure is not equal
77293838Sdim  // to the number of live registers.
78293838Sdim  std::set<unsigned> LiveInRegs;
79293838Sdim  std::set<unsigned> LiveOutRegs;
80293838Sdim
81293838Sdim  bool Scheduled;
82293838Sdim  bool HighLatencyBlock;
83293838Sdim
84293838Sdim  std::vector<unsigned> HasLowLatencyNonWaitedParent;
85293838Sdim
86293838Sdim  // Unique ID, the index of the Block in the SIScheduleDAGMI Blocks table.
87293838Sdim  unsigned ID;
88293838Sdim
89293838Sdim  std::vector<SIScheduleBlock*> Preds;  // All blocks predecessors.
90293838Sdim  std::vector<SIScheduleBlock*> Succs;  // All blocks successors.
91293838Sdim  unsigned NumHighLatencySuccessors;
92293838Sdim
93293838Sdimpublic:
94293838Sdim  SIScheduleBlock(SIScheduleDAGMI *DAG, SIScheduleBlockCreator *BC,
95293838Sdim                  unsigned ID):
96293838Sdim    DAG(DAG), BC(BC), SUnits(), TopReadySUs(), ScheduledSUnits(),
97293838Sdim    TopRPTracker(TopPressure), Scheduled(false),
98293838Sdim    HighLatencyBlock(false), ID(ID),
99293838Sdim    Preds(), Succs(), NumHighLatencySuccessors(0) {};
100293838Sdim
101293838Sdim  ~SIScheduleBlock() {};
102293838Sdim
103293838Sdim  unsigned getID() const { return ID; }
104293838Sdim
105293838Sdim  /// Functions for Block construction.
106293838Sdim  void addUnit(SUnit *SU);
107293838Sdim
108293838Sdim  // When all SUs have been added.
109293838Sdim  void finalizeUnits();
110293838Sdim
111293838Sdim  // Add block pred, which has instruction predecessor of SU.
112293838Sdim  void addPred(SIScheduleBlock *Pred);
113293838Sdim  void addSucc(SIScheduleBlock *Succ);
114293838Sdim
115293838Sdim  const std::vector<SIScheduleBlock*>& getPreds() const { return Preds; }
116293838Sdim  const std::vector<SIScheduleBlock*>& getSuccs() const { return Succs; }
117293838Sdim
118293838Sdim  unsigned Height;  // Maximum topdown path length to block without outputs
119293838Sdim  unsigned Depth;   // Maximum bottomup path length to block without inputs
120293838Sdim
121293838Sdim  unsigned getNumHighLatencySuccessors() const {
122293838Sdim    return NumHighLatencySuccessors;
123293838Sdim  }
124293838Sdim
125293838Sdim  bool isHighLatencyBlock() { return HighLatencyBlock; }
126293838Sdim
127293838Sdim  // This is approximative.
128293838Sdim  // Ideally should take into accounts some instructions (rcp, etc)
129293838Sdim  // are 4 times slower.
130293838Sdim  int getCost() { return SUnits.size(); }
131293838Sdim
132293838Sdim  // The block Predecessors and Successors must be all registered
133293838Sdim  // before fastSchedule().
134293838Sdim  // Fast schedule with no particular requirement.
135293838Sdim  void fastSchedule();
136293838Sdim
137293838Sdim  std::vector<SUnit*> getScheduledUnits() { return ScheduledSUnits; }
138293838Sdim
139293838Sdim  // Complete schedule that will try to minimize reg pressure and
140293838Sdim  // low latencies, and will fill liveins and liveouts.
141293838Sdim  // Needs all MIs to be grouped between BeginBlock and EndBlock.
142293838Sdim  // The MIs can be moved after the scheduling,
143293838Sdim  // it is just used to allow correct track of live registers.
144293838Sdim  void schedule(MachineBasicBlock::iterator BeginBlock,
145293838Sdim                MachineBasicBlock::iterator EndBlock);
146293838Sdim
147293838Sdim  bool isScheduled() { return Scheduled; }
148293838Sdim
149293838Sdim
150293838Sdim  // Needs the block to be scheduled inside
151293838Sdim  // TODO: find a way to compute it.
152293838Sdim  std::vector<unsigned> &getInternalAdditionnalRegUsage() {
153293838Sdim    return InternalAdditionnalPressure;
154293838Sdim  }
155293838Sdim
156293838Sdim  std::set<unsigned> &getInRegs() { return LiveInRegs; }
157293838Sdim  std::set<unsigned> &getOutRegs() { return LiveOutRegs; }
158293838Sdim
159293838Sdim  void printDebug(bool Full);
160293838Sdim
161293838Sdimprivate:
162293838Sdim  struct SISchedCandidate : SISchedulerCandidate {
163293838Sdim    // The best SUnit candidate.
164293838Sdim    SUnit *SU;
165293838Sdim
166293838Sdim    unsigned SGPRUsage;
167293838Sdim    unsigned VGPRUsage;
168293838Sdim    bool IsLowLatency;
169293838Sdim    unsigned LowLatencyOffset;
170293838Sdim    bool HasLowLatencyNonWaitedParent;
171293838Sdim
172293838Sdim    SISchedCandidate()
173293838Sdim      : SU(nullptr) {}
174293838Sdim
175293838Sdim    bool isValid() const { return SU; }
176293838Sdim
177293838Sdim    // Copy the status of another candidate without changing policy.
178293838Sdim    void setBest(SISchedCandidate &Best) {
179293838Sdim      assert(Best.Reason != NoCand && "uninitialized Sched candidate");
180293838Sdim      SU = Best.SU;
181293838Sdim      Reason = Best.Reason;
182293838Sdim      SGPRUsage = Best.SGPRUsage;
183293838Sdim      VGPRUsage = Best.VGPRUsage;
184293838Sdim      IsLowLatency = Best.IsLowLatency;
185293838Sdim      LowLatencyOffset = Best.LowLatencyOffset;
186293838Sdim      HasLowLatencyNonWaitedParent = Best.HasLowLatencyNonWaitedParent;
187293838Sdim    }
188293838Sdim  };
189293838Sdim
190293838Sdim  void undoSchedule();
191293838Sdim
192293838Sdim  void undoReleaseSucc(SUnit *SU, SDep *SuccEdge);
193293838Sdim  void releaseSucc(SUnit *SU, SDep *SuccEdge);
194293838Sdim  // InOrOutBlock: restrict to links pointing inside the block (true),
195293838Sdim  // or restrict to links pointing outside the block (false).
196293838Sdim  void releaseSuccessors(SUnit *SU, bool InOrOutBlock);
197293838Sdim
198293838Sdim  void nodeScheduled(SUnit *SU);
199293838Sdim  void tryCandidateTopDown(SISchedCandidate &Cand, SISchedCandidate &TryCand);
200293838Sdim  void tryCandidateBottomUp(SISchedCandidate &Cand, SISchedCandidate &TryCand);
201293838Sdim  SUnit* pickNode();
202293838Sdim  void traceCandidate(const SISchedCandidate &Cand);
203293838Sdim  void initRegPressure(MachineBasicBlock::iterator BeginBlock,
204293838Sdim                       MachineBasicBlock::iterator EndBlock);
205293838Sdim};
206293838Sdim
207293838Sdimstruct SIScheduleBlocks {
208293838Sdim  std::vector<SIScheduleBlock*> Blocks;
209293838Sdim  std::vector<int> TopDownIndex2Block;
210293838Sdim  std::vector<int> TopDownBlock2Index;
211293838Sdim};
212293838Sdim
213293838Sdimenum SISchedulerBlockCreatorVariant {
214293838Sdim    LatenciesAlone,
215293838Sdim    LatenciesGrouped,
216293838Sdim    LatenciesAlonePlusConsecutive
217293838Sdim};
218293838Sdim
219293838Sdimclass SIScheduleBlockCreator {
220293838Sdim  SIScheduleDAGMI *DAG;
221293838Sdim  // unique_ptr handles freeing memory for us.
222293838Sdim  std::vector<std::unique_ptr<SIScheduleBlock>> BlockPtrs;
223293838Sdim  std::map<SISchedulerBlockCreatorVariant,
224293838Sdim           SIScheduleBlocks> Blocks;
225293838Sdim  std::vector<SIScheduleBlock*> CurrentBlocks;
226293838Sdim  std::vector<int> Node2CurrentBlock;
227293838Sdim
228293838Sdim  // Topological sort
229293838Sdim  // Maps topological index to the node number.
230293838Sdim  std::vector<int> TopDownIndex2Block;
231293838Sdim  std::vector<int> TopDownBlock2Index;
232293838Sdim  std::vector<int> BottomUpIndex2Block;
233293838Sdim
234293838Sdim  // 0 -> Color not given.
235293838Sdim  // 1 to SUnits.size() -> Reserved group (you should only add elements to them).
236293838Sdim  // Above -> Other groups.
237293838Sdim  int NextReservedID;
238293838Sdim  int NextNonReservedID;
239293838Sdim  std::vector<int> CurrentColoring;
240293838Sdim  std::vector<int> CurrentTopDownReservedDependencyColoring;
241293838Sdim  std::vector<int> CurrentBottomUpReservedDependencyColoring;
242293838Sdim
243293838Sdimpublic:
244293838Sdim  SIScheduleBlockCreator(SIScheduleDAGMI *DAG);
245293838Sdim  ~SIScheduleBlockCreator();
246293838Sdim
247293838Sdim  SIScheduleBlocks
248293838Sdim  getBlocks(SISchedulerBlockCreatorVariant BlockVariant);
249293838Sdim
250293838Sdim  bool isSUInBlock(SUnit *SU, unsigned ID);
251293838Sdim
252293838Sdimprivate:
253293838Sdim  // Give a Reserved color to every high latency.
254293838Sdim  void colorHighLatenciesAlone();
255293838Sdim
256293838Sdim  // Create groups of high latencies with a Reserved color.
257293838Sdim  void colorHighLatenciesGroups();
258293838Sdim
259293838Sdim  // Compute coloring for topdown and bottom traversals with
260293838Sdim  // different colors depending on dependencies on Reserved colors.
261293838Sdim  void colorComputeReservedDependencies();
262293838Sdim
263293838Sdim  // Give color to all non-colored SUs according to Reserved groups dependencies.
264293838Sdim  void colorAccordingToReservedDependencies();
265293838Sdim
266293838Sdim  // Divides Blocks having no bottom up or top down dependencies on Reserved groups.
267293838Sdim  // The new colors are computed according to the dependencies on the other blocks
268293838Sdim  // formed with colorAccordingToReservedDependencies.
269293838Sdim  void colorEndsAccordingToDependencies();
270293838Sdim
271293838Sdim  // Cut groups into groups with SUs in consecutive order (except for Reserved groups).
272293838Sdim  void colorForceConsecutiveOrderInGroup();
273293838Sdim
274293838Sdim  // Merge Constant loads that have all their users into another group to the group.
275293838Sdim  // (TODO: else if all their users depend on the same group, put them there)
276293838Sdim  void colorMergeConstantLoadsNextGroup();
277293838Sdim
278293838Sdim  // Merge SUs that have all their users into another group to the group
279293838Sdim  void colorMergeIfPossibleNextGroup();
280293838Sdim
281293838Sdim  // Merge SUs that have all their users into another group to the group,
282293838Sdim  // but only for Reserved groups.
283293838Sdim  void colorMergeIfPossibleNextGroupOnlyForReserved();
284293838Sdim
285293838Sdim  // Merge SUs that have all their users into another group to the group,
286293838Sdim  // but only if the group is no more than a few SUs.
287293838Sdim  void colorMergeIfPossibleSmallGroupsToNextGroup();
288293838Sdim
289293838Sdim  // Divides Blocks with important size.
290293838Sdim  // Idea of implementation: attribute new colors depending on topdown and
291293838Sdim  // bottom up links to other blocks.
292293838Sdim  void cutHugeBlocks();
293293838Sdim
294293838Sdim  // Put in one group all instructions with no users in this scheduling region
295293838Sdim  // (we'd want these groups be at the end).
296293838Sdim  void regroupNoUserInstructions();
297293838Sdim
298293838Sdim  void createBlocksForVariant(SISchedulerBlockCreatorVariant BlockVariant);
299293838Sdim
300293838Sdim  void topologicalSort();
301293838Sdim
302293838Sdim  void scheduleInsideBlocks();
303293838Sdim
304293838Sdim  void fillStats();
305293838Sdim};
306293838Sdim
307293838Sdimenum SISchedulerBlockSchedulerVariant {
308293838Sdim  BlockLatencyRegUsage,
309293838Sdim  BlockRegUsageLatency,
310293838Sdim  BlockRegUsage
311293838Sdim};
312293838Sdim
313293838Sdimclass SIScheduleBlockScheduler {
314293838Sdim  SIScheduleDAGMI *DAG;
315293838Sdim  SISchedulerBlockSchedulerVariant Variant;
316293838Sdim  std::vector<SIScheduleBlock*> Blocks;
317293838Sdim
318293838Sdim  std::vector<std::map<unsigned, unsigned>> LiveOutRegsNumUsages;
319293838Sdim  std::set<unsigned> LiveRegs;
320293838Sdim  // Num of schedulable unscheduled blocks reading the register.
321293838Sdim  std::map<unsigned, unsigned> LiveRegsConsumers;
322293838Sdim
323293838Sdim  std::vector<unsigned> LastPosHighLatencyParentScheduled;
324293838Sdim  int LastPosWaitedHighLatency;
325293838Sdim
326293838Sdim  std::vector<SIScheduleBlock*> BlocksScheduled;
327293838Sdim  unsigned NumBlockScheduled;
328293838Sdim  std::vector<SIScheduleBlock*> ReadyBlocks;
329293838Sdim
330293838Sdim  unsigned VregCurrentUsage;
331293838Sdim  unsigned SregCurrentUsage;
332293838Sdim
333293838Sdim  // Currently is only approximation.
334293838Sdim  unsigned maxVregUsage;
335293838Sdim  unsigned maxSregUsage;
336293838Sdim
337293838Sdim  std::vector<unsigned> BlockNumPredsLeft;
338293838Sdim  std::vector<unsigned> BlockNumSuccsLeft;
339293838Sdim
340293838Sdimpublic:
341293838Sdim  SIScheduleBlockScheduler(SIScheduleDAGMI *DAG,
342293838Sdim                           SISchedulerBlockSchedulerVariant Variant,
343293838Sdim                           SIScheduleBlocks BlocksStruct);
344293838Sdim  ~SIScheduleBlockScheduler() {};
345293838Sdim
346293838Sdim  std::vector<SIScheduleBlock*> getBlocks() { return BlocksScheduled; };
347293838Sdim
348293838Sdim  unsigned getVGPRUsage() { return maxVregUsage; };
349293838Sdim  unsigned getSGPRUsage() { return maxSregUsage; };
350293838Sdim
351293838Sdimprivate:
352293838Sdim  struct SIBlockSchedCandidate : SISchedulerCandidate {
353293838Sdim    // The best Block candidate.
354293838Sdim    SIScheduleBlock *Block;
355293838Sdim
356293838Sdim    bool IsHighLatency;
357293838Sdim    int VGPRUsageDiff;
358293838Sdim    unsigned NumSuccessors;
359293838Sdim    unsigned NumHighLatencySuccessors;
360293838Sdim    unsigned LastPosHighLatParentScheduled;
361293838Sdim    unsigned Height;
362293838Sdim
363293838Sdim    SIBlockSchedCandidate()
364293838Sdim      : Block(nullptr) {}
365293838Sdim
366293838Sdim    bool isValid() const { return Block; }
367293838Sdim
368293838Sdim    // Copy the status of another candidate without changing policy.
369293838Sdim    void setBest(SIBlockSchedCandidate &Best) {
370293838Sdim      assert(Best.Reason != NoCand && "uninitialized Sched candidate");
371293838Sdim      Block = Best.Block;
372293838Sdim      Reason = Best.Reason;
373293838Sdim      IsHighLatency = Best.IsHighLatency;
374293838Sdim      VGPRUsageDiff = Best.VGPRUsageDiff;
375293838Sdim      NumSuccessors = Best.NumSuccessors;
376293838Sdim      NumHighLatencySuccessors = Best.NumHighLatencySuccessors;
377293838Sdim      LastPosHighLatParentScheduled = Best.LastPosHighLatParentScheduled;
378293838Sdim      Height = Best.Height;
379293838Sdim    }
380293838Sdim  };
381293838Sdim
382293838Sdim  bool tryCandidateLatency(SIBlockSchedCandidate &Cand,
383293838Sdim                           SIBlockSchedCandidate &TryCand);
384293838Sdim  bool tryCandidateRegUsage(SIBlockSchedCandidate &Cand,
385293838Sdim                            SIBlockSchedCandidate &TryCand);
386293838Sdim  SIScheduleBlock *pickBlock();
387293838Sdim
388293838Sdim  void addLiveRegs(std::set<unsigned> &Regs);
389293838Sdim  void decreaseLiveRegs(SIScheduleBlock *Block, std::set<unsigned> &Regs);
390293838Sdim  void releaseBlockSuccs(SIScheduleBlock *Parent);
391293838Sdim  void blockScheduled(SIScheduleBlock *Block);
392293838Sdim
393293838Sdim  // Check register pressure change
394293838Sdim  // by scheduling a block with these LiveIn and LiveOut.
395293838Sdim  std::vector<int> checkRegUsageImpact(std::set<unsigned> &InRegs,
396293838Sdim                                       std::set<unsigned> &OutRegs);
397293838Sdim
398293838Sdim  void schedule();
399293838Sdim};
400293838Sdim
401293838Sdimstruct SIScheduleBlockResult {
402293838Sdim  std::vector<unsigned> SUs;
403293838Sdim  unsigned MaxSGPRUsage;
404293838Sdim  unsigned MaxVGPRUsage;
405293838Sdim};
406293838Sdim
407293838Sdimclass SIScheduler {
408293838Sdim  SIScheduleDAGMI *DAG;
409293838Sdim  SIScheduleBlockCreator BlockCreator;
410293838Sdim
411293838Sdimpublic:
412293838Sdim  SIScheduler(SIScheduleDAGMI *DAG) : DAG(DAG), BlockCreator(DAG) {};
413293838Sdim
414293838Sdim  ~SIScheduler() {};
415293838Sdim
416293838Sdim  struct SIScheduleBlockResult
417293838Sdim  scheduleVariant(SISchedulerBlockCreatorVariant BlockVariant,
418293838Sdim                  SISchedulerBlockSchedulerVariant ScheduleVariant);
419293838Sdim};
420293838Sdim
421293838Sdimclass SIScheduleDAGMI : public ScheduleDAGMILive {
422293838Sdim  const SIInstrInfo *SITII;
423293838Sdim  const SIRegisterInfo *SITRI;
424293838Sdim
425293838Sdim  std::vector<SUnit> SUnitsLinksBackup;
426293838Sdim
427293838Sdim  // For moveLowLatencies. After all Scheduling variants are tested.
428293838Sdim  std::vector<unsigned> ScheduledSUnits;
429293838Sdim  std::vector<unsigned> ScheduledSUnitsInv;
430293838Sdim
431293838Sdim  unsigned VGPRSetID;
432293838Sdim  unsigned SGPRSetID;
433293838Sdim
434293838Sdimpublic:
435293838Sdim  SIScheduleDAGMI(MachineSchedContext *C);
436293838Sdim
437293838Sdim  ~SIScheduleDAGMI() override;
438293838Sdim
439293838Sdim  // Entry point for the schedule.
440293838Sdim  void schedule() override;
441293838Sdim
442293838Sdim  // To init Block's RPTracker.
443293838Sdim  void initRPTracker(RegPressureTracker &RPTracker) {
444293838Sdim    RPTracker.init(&MF, RegClassInfo, LIS, BB, RegionBegin);
445293838Sdim  }
446293838Sdim
447293838Sdim  MachineBasicBlock *getBB() { return BB; }
448293838Sdim  MachineBasicBlock::iterator getCurrentTop() { return CurrentTop; };
449293838Sdim  MachineBasicBlock::iterator getCurrentBottom() { return CurrentBottom; };
450293838Sdim  LiveIntervals *getLIS() { return LIS; }
451293838Sdim  MachineRegisterInfo *getMRI() { return &MRI; }
452293838Sdim  const TargetRegisterInfo *getTRI() { return TRI; }
453293838Sdim  SUnit& getEntrySU() { return EntrySU; };
454293838Sdim  SUnit& getExitSU() { return ExitSU; };
455293838Sdim
456293838Sdim  void restoreSULinksLeft();
457293838Sdim
458293838Sdim  template<typename _Iterator> void fillVgprSgprCost(_Iterator First,
459293838Sdim                                                     _Iterator End,
460293838Sdim                                                     unsigned &VgprUsage,
461293838Sdim                                                     unsigned &SgprUsage);
462293838Sdim  std::set<unsigned> getInRegs() {
463293838Sdim    std::set<unsigned> InRegs (RPTracker.getPressure().LiveInRegs.begin(),
464293838Sdim                               RPTracker.getPressure().LiveInRegs.end());
465293838Sdim    return InRegs;
466293838Sdim  };
467293838Sdim
468293838Sdim  unsigned getVGPRSetID() const { return VGPRSetID; }
469293838Sdim  unsigned getSGPRSetID() const { return SGPRSetID; }
470293838Sdim
471293838Sdimprivate:
472293838Sdim  void topologicalSort();
473293838Sdim  // After scheduling is done, improve low latency placements.
474293838Sdim  void moveLowLatencies();
475293838Sdim
476293838Sdimpublic:
477293838Sdim  // Some stats for scheduling inside blocks.
478293838Sdim  std::vector<unsigned> IsLowLatencySU;
479293838Sdim  std::vector<unsigned> LowLatencyOffset;
480293838Sdim  std::vector<unsigned> IsHighLatencySU;
481293838Sdim  // Topological sort
482293838Sdim  // Maps topological index to the node number.
483293838Sdim  std::vector<int> TopDownIndex2SU;
484293838Sdim  std::vector<int> BottomUpIndex2SU;
485293838Sdim};
486293838Sdim
487293838Sdim} // namespace llvm
488293838Sdim
489293838Sdim#endif /* SIMACHINESCHEDULER_H_ */
490