109467b48Spatrick //===-- SIMachineScheduler.h - SI Scheduler Interface -----------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick /// \file
1009467b48Spatrick /// SI Machine Scheduler interface
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #ifndef LLVM_LIB_TARGET_AMDGPU_SIMACHINESCHEDULER_H
1509467b48Spatrick #define LLVM_LIB_TARGET_AMDGPU_SIMACHINESCHEDULER_H
1609467b48Spatrick 
1709467b48Spatrick #include "llvm/CodeGen/MachineScheduler.h"
1809467b48Spatrick #include "llvm/CodeGen/RegisterPressure.h"
1909467b48Spatrick #include "llvm/CodeGen/ScheduleDAG.h"
2009467b48Spatrick #include <cstdint>
2109467b48Spatrick #include <set>
2209467b48Spatrick #include <vector>
2309467b48Spatrick 
2409467b48Spatrick namespace llvm {
2509467b48Spatrick 
2673471bf0Spatrick class SIInstrInfo;
2773471bf0Spatrick class SIRegisterInfo;
28*d415bd75Srobert class SIScheduleDAGMI;
29*d415bd75Srobert class SIScheduleBlockCreator;
3073471bf0Spatrick 
3109467b48Spatrick enum SIScheduleCandReason {
3209467b48Spatrick   NoCand,
3309467b48Spatrick   RegUsage,
3409467b48Spatrick   Latency,
3509467b48Spatrick   Successor,
3609467b48Spatrick   Depth,
3709467b48Spatrick   NodeOrder
3809467b48Spatrick };
3909467b48Spatrick 
4009467b48Spatrick struct SISchedulerCandidate {
4109467b48Spatrick   // The reason for this candidate.
4209467b48Spatrick   SIScheduleCandReason Reason = NoCand;
4309467b48Spatrick 
4409467b48Spatrick   // Set of reasons that apply to multiple candidates.
4509467b48Spatrick   uint32_t RepeatReasonSet = 0;
4609467b48Spatrick 
4709467b48Spatrick   SISchedulerCandidate() = default;
4809467b48Spatrick 
isRepeatSISchedulerCandidate4909467b48Spatrick   bool isRepeat(SIScheduleCandReason R) { return RepeatReasonSet & (1 << R); }
setRepeatSISchedulerCandidate5009467b48Spatrick   void setRepeat(SIScheduleCandReason R) { RepeatReasonSet |= (1 << R); }
5109467b48Spatrick };
5209467b48Spatrick 
5309467b48Spatrick enum SIScheduleBlockLinkKind {
5409467b48Spatrick   NoData,
5509467b48Spatrick   Data
5609467b48Spatrick };
5709467b48Spatrick 
5809467b48Spatrick class SIScheduleBlock {
5909467b48Spatrick   SIScheduleDAGMI *DAG;
6009467b48Spatrick   SIScheduleBlockCreator *BC;
6109467b48Spatrick 
6209467b48Spatrick   std::vector<SUnit*> SUnits;
6309467b48Spatrick   std::map<unsigned, unsigned> NodeNum2Index;
6409467b48Spatrick   std::vector<SUnit*> TopReadySUs;
6509467b48Spatrick   std::vector<SUnit*> ScheduledSUnits;
6609467b48Spatrick 
6709467b48Spatrick   /// The top of the unscheduled zone.
6809467b48Spatrick   IntervalPressure TopPressure;
6909467b48Spatrick   RegPressureTracker TopRPTracker;
7009467b48Spatrick 
7109467b48Spatrick   // Pressure: number of said class of registers needed to
7209467b48Spatrick   // store the live virtual and real registers.
7309467b48Spatrick   // We do care only of SGPR32 and VGPR32 and do track only virtual registers.
7409467b48Spatrick   // Pressure of additional registers required inside the block.
75*d415bd75Srobert   std::vector<unsigned> InternalAdditionalPressure;
7609467b48Spatrick   // Pressure of input and output registers
7709467b48Spatrick   std::vector<unsigned> LiveInPressure;
7809467b48Spatrick   std::vector<unsigned> LiveOutPressure;
7909467b48Spatrick   // Registers required by the block, and outputs.
8009467b48Spatrick   // We do track only virtual registers.
8109467b48Spatrick   // Note that some registers are not 32 bits,
8209467b48Spatrick   // and thus the pressure is not equal
8309467b48Spatrick   // to the number of live registers.
8409467b48Spatrick   std::set<unsigned> LiveInRegs;
8509467b48Spatrick   std::set<unsigned> LiveOutRegs;
8609467b48Spatrick 
8709467b48Spatrick   bool Scheduled = false;
8809467b48Spatrick   bool HighLatencyBlock = false;
8909467b48Spatrick 
9009467b48Spatrick   std::vector<unsigned> HasLowLatencyNonWaitedParent;
9109467b48Spatrick 
9209467b48Spatrick   // Unique ID, the index of the Block in the SIScheduleDAGMI Blocks table.
9309467b48Spatrick   unsigned ID;
9409467b48Spatrick 
9509467b48Spatrick   std::vector<SIScheduleBlock*> Preds;  // All blocks predecessors.
9609467b48Spatrick   // All blocks successors, and the kind of link
9709467b48Spatrick   std::vector<std::pair<SIScheduleBlock*, SIScheduleBlockLinkKind>> Succs;
9809467b48Spatrick   unsigned NumHighLatencySuccessors = 0;
9909467b48Spatrick 
10009467b48Spatrick public:
SIScheduleBlock(SIScheduleDAGMI * DAG,SIScheduleBlockCreator * BC,unsigned ID)10109467b48Spatrick   SIScheduleBlock(SIScheduleDAGMI *DAG, SIScheduleBlockCreator *BC,
10209467b48Spatrick                   unsigned ID):
10309467b48Spatrick     DAG(DAG), BC(BC), TopRPTracker(TopPressure), ID(ID) {}
10409467b48Spatrick 
10509467b48Spatrick   ~SIScheduleBlock() = default;
10609467b48Spatrick 
getID()10709467b48Spatrick   unsigned getID() const { return ID; }
10809467b48Spatrick 
10909467b48Spatrick   /// Functions for Block construction.
11009467b48Spatrick   void addUnit(SUnit *SU);
11109467b48Spatrick 
11209467b48Spatrick   // When all SUs have been added.
11309467b48Spatrick   void finalizeUnits();
11409467b48Spatrick 
11509467b48Spatrick   // Add block pred, which has instruction predecessor of SU.
11609467b48Spatrick   void addPred(SIScheduleBlock *Pred);
11709467b48Spatrick   void addSucc(SIScheduleBlock *Succ, SIScheduleBlockLinkKind Kind);
11809467b48Spatrick 
getPreds()11909467b48Spatrick   const std::vector<SIScheduleBlock*>& getPreds() const { return Preds; }
12009467b48Spatrick   ArrayRef<std::pair<SIScheduleBlock*, SIScheduleBlockLinkKind>>
getSuccs()12109467b48Spatrick     getSuccs() const { return Succs; }
12209467b48Spatrick 
12309467b48Spatrick   unsigned Height;  // Maximum topdown path length to block without outputs
12409467b48Spatrick   unsigned Depth;   // Maximum bottomup path length to block without inputs
12509467b48Spatrick 
getNumHighLatencySuccessors()12609467b48Spatrick   unsigned getNumHighLatencySuccessors() const {
12709467b48Spatrick     return NumHighLatencySuccessors;
12809467b48Spatrick   }
12909467b48Spatrick 
isHighLatencyBlock()13009467b48Spatrick   bool isHighLatencyBlock() { return HighLatencyBlock; }
13109467b48Spatrick 
13209467b48Spatrick   // This is approximative.
13309467b48Spatrick   // Ideally should take into accounts some instructions (rcp, etc)
13409467b48Spatrick   // are 4 times slower.
getCost()13509467b48Spatrick   int getCost() { return SUnits.size(); }
13609467b48Spatrick 
13709467b48Spatrick   // The block Predecessors and Successors must be all registered
13809467b48Spatrick   // before fastSchedule().
13909467b48Spatrick   // Fast schedule with no particular requirement.
14009467b48Spatrick   void fastSchedule();
14109467b48Spatrick 
getScheduledUnits()14209467b48Spatrick   std::vector<SUnit*> getScheduledUnits() { return ScheduledSUnits; }
14309467b48Spatrick 
14409467b48Spatrick   // Complete schedule that will try to minimize reg pressure and
14509467b48Spatrick   // low latencies, and will fill liveins and liveouts.
14609467b48Spatrick   // Needs all MIs to be grouped between BeginBlock and EndBlock.
14709467b48Spatrick   // The MIs can be moved after the scheduling,
14809467b48Spatrick   // it is just used to allow correct track of live registers.
14909467b48Spatrick   void schedule(MachineBasicBlock::iterator BeginBlock,
15009467b48Spatrick                 MachineBasicBlock::iterator EndBlock);
15109467b48Spatrick 
isScheduled()15209467b48Spatrick   bool isScheduled() { return Scheduled; }
15309467b48Spatrick 
15409467b48Spatrick   // Needs the block to be scheduled inside
15509467b48Spatrick   // TODO: find a way to compute it.
getInternalAdditionalRegUsage()156*d415bd75Srobert   std::vector<unsigned> &getInternalAdditionalRegUsage() {
157*d415bd75Srobert     return InternalAdditionalPressure;
15809467b48Spatrick   }
15909467b48Spatrick 
getInRegs()16009467b48Spatrick   std::set<unsigned> &getInRegs() { return LiveInRegs; }
getOutRegs()16109467b48Spatrick   std::set<unsigned> &getOutRegs() { return LiveOutRegs; }
16209467b48Spatrick 
16309467b48Spatrick   void printDebug(bool Full);
16409467b48Spatrick 
16509467b48Spatrick private:
16609467b48Spatrick   struct SISchedCandidate : SISchedulerCandidate {
16709467b48Spatrick     // The best SUnit candidate.
16809467b48Spatrick     SUnit *SU = nullptr;
16909467b48Spatrick 
17009467b48Spatrick     unsigned SGPRUsage;
17109467b48Spatrick     unsigned VGPRUsage;
17209467b48Spatrick     bool IsLowLatency;
17309467b48Spatrick     unsigned LowLatencyOffset;
17409467b48Spatrick     bool HasLowLatencyNonWaitedParent;
17509467b48Spatrick 
17609467b48Spatrick     SISchedCandidate() = default;
17709467b48Spatrick 
isValidSISchedCandidate17809467b48Spatrick     bool isValid() const { return SU; }
17909467b48Spatrick 
18009467b48Spatrick     // Copy the status of another candidate without changing policy.
setBestSISchedCandidate18109467b48Spatrick     void setBest(SISchedCandidate &Best) {
18209467b48Spatrick       assert(Best.Reason != NoCand && "uninitialized Sched candidate");
18309467b48Spatrick       SU = Best.SU;
18409467b48Spatrick       Reason = Best.Reason;
18509467b48Spatrick       SGPRUsage = Best.SGPRUsage;
18609467b48Spatrick       VGPRUsage = Best.VGPRUsage;
18709467b48Spatrick       IsLowLatency = Best.IsLowLatency;
18809467b48Spatrick       LowLatencyOffset = Best.LowLatencyOffset;
18909467b48Spatrick       HasLowLatencyNonWaitedParent = Best.HasLowLatencyNonWaitedParent;
19009467b48Spatrick     }
19109467b48Spatrick   };
19209467b48Spatrick 
19309467b48Spatrick   void undoSchedule();
19409467b48Spatrick 
19509467b48Spatrick   void undoReleaseSucc(SUnit *SU, SDep *SuccEdge);
19609467b48Spatrick   void releaseSucc(SUnit *SU, SDep *SuccEdge);
19709467b48Spatrick   // InOrOutBlock: restrict to links pointing inside the block (true),
19809467b48Spatrick   // or restrict to links pointing outside the block (false).
19909467b48Spatrick   void releaseSuccessors(SUnit *SU, bool InOrOutBlock);
20009467b48Spatrick 
20109467b48Spatrick   void nodeScheduled(SUnit *SU);
20209467b48Spatrick   void tryCandidateTopDown(SISchedCandidate &Cand, SISchedCandidate &TryCand);
20309467b48Spatrick   void tryCandidateBottomUp(SISchedCandidate &Cand, SISchedCandidate &TryCand);
20409467b48Spatrick   SUnit* pickNode();
20509467b48Spatrick   void traceCandidate(const SISchedCandidate &Cand);
20609467b48Spatrick   void initRegPressure(MachineBasicBlock::iterator BeginBlock,
20709467b48Spatrick                        MachineBasicBlock::iterator EndBlock);
20809467b48Spatrick };
20909467b48Spatrick 
21009467b48Spatrick struct SIScheduleBlocks {
21109467b48Spatrick   std::vector<SIScheduleBlock*> Blocks;
21209467b48Spatrick   std::vector<int> TopDownIndex2Block;
21309467b48Spatrick   std::vector<int> TopDownBlock2Index;
21409467b48Spatrick };
21509467b48Spatrick 
21609467b48Spatrick enum SISchedulerBlockCreatorVariant {
21709467b48Spatrick   LatenciesAlone,
21809467b48Spatrick   LatenciesGrouped,
21909467b48Spatrick   LatenciesAlonePlusConsecutive
22009467b48Spatrick };
22109467b48Spatrick 
22209467b48Spatrick class SIScheduleBlockCreator {
22309467b48Spatrick   SIScheduleDAGMI *DAG;
22409467b48Spatrick   // unique_ptr handles freeing memory for us.
22509467b48Spatrick   std::vector<std::unique_ptr<SIScheduleBlock>> BlockPtrs;
22609467b48Spatrick   std::map<SISchedulerBlockCreatorVariant,
22709467b48Spatrick            SIScheduleBlocks> Blocks;
22809467b48Spatrick   std::vector<SIScheduleBlock*> CurrentBlocks;
22909467b48Spatrick   std::vector<int> Node2CurrentBlock;
23009467b48Spatrick 
23109467b48Spatrick   // Topological sort
23209467b48Spatrick   // Maps topological index to the node number.
23309467b48Spatrick   std::vector<int> TopDownIndex2Block;
23409467b48Spatrick   std::vector<int> TopDownBlock2Index;
23509467b48Spatrick   std::vector<int> BottomUpIndex2Block;
23609467b48Spatrick 
23709467b48Spatrick   // 0 -> Color not given.
23809467b48Spatrick   // 1 to SUnits.size() -> Reserved group (you should only add elements to them).
23909467b48Spatrick   // Above -> Other groups.
24009467b48Spatrick   int NextReservedID;
24109467b48Spatrick   int NextNonReservedID;
24209467b48Spatrick   std::vector<int> CurrentColoring;
24309467b48Spatrick   std::vector<int> CurrentTopDownReservedDependencyColoring;
24409467b48Spatrick   std::vector<int> CurrentBottomUpReservedDependencyColoring;
24509467b48Spatrick 
24609467b48Spatrick public:
24709467b48Spatrick   SIScheduleBlockCreator(SIScheduleDAGMI *DAG);
24809467b48Spatrick 
24909467b48Spatrick   SIScheduleBlocks
25009467b48Spatrick   getBlocks(SISchedulerBlockCreatorVariant BlockVariant);
25109467b48Spatrick 
25209467b48Spatrick   bool isSUInBlock(SUnit *SU, unsigned ID);
25309467b48Spatrick 
25409467b48Spatrick private:
25509467b48Spatrick   // Give a Reserved color to every high latency.
25609467b48Spatrick   void colorHighLatenciesAlone();
25709467b48Spatrick 
25809467b48Spatrick   // Create groups of high latencies with a Reserved color.
25909467b48Spatrick   void colorHighLatenciesGroups();
26009467b48Spatrick 
26109467b48Spatrick   // Compute coloring for topdown and bottom traversals with
26209467b48Spatrick   // different colors depending on dependencies on Reserved colors.
26309467b48Spatrick   void colorComputeReservedDependencies();
26409467b48Spatrick 
26509467b48Spatrick   // Give color to all non-colored SUs according to Reserved groups dependencies.
26609467b48Spatrick   void colorAccordingToReservedDependencies();
26709467b48Spatrick 
26809467b48Spatrick   // Divides Blocks having no bottom up or top down dependencies on Reserved groups.
26909467b48Spatrick   // The new colors are computed according to the dependencies on the other blocks
27009467b48Spatrick   // formed with colorAccordingToReservedDependencies.
27109467b48Spatrick   void colorEndsAccordingToDependencies();
27209467b48Spatrick 
27309467b48Spatrick   // Cut groups into groups with SUs in consecutive order (except for Reserved groups).
27409467b48Spatrick   void colorForceConsecutiveOrderInGroup();
27509467b48Spatrick 
27609467b48Spatrick   // Merge Constant loads that have all their users into another group to the group.
27709467b48Spatrick   // (TODO: else if all their users depend on the same group, put them there)
27809467b48Spatrick   void colorMergeConstantLoadsNextGroup();
27909467b48Spatrick 
28009467b48Spatrick   // Merge SUs that have all their users into another group to the group
28109467b48Spatrick   void colorMergeIfPossibleNextGroup();
28209467b48Spatrick 
28309467b48Spatrick   // Merge SUs that have all their users into another group to the group,
28409467b48Spatrick   // but only for Reserved groups.
28509467b48Spatrick   void colorMergeIfPossibleNextGroupOnlyForReserved();
28609467b48Spatrick 
28709467b48Spatrick   // Merge SUs that have all their users into another group to the group,
28809467b48Spatrick   // but only if the group is no more than a few SUs.
28909467b48Spatrick   void colorMergeIfPossibleSmallGroupsToNextGroup();
29009467b48Spatrick 
29109467b48Spatrick   // Divides Blocks with important size.
29209467b48Spatrick   // Idea of implementation: attribute new colors depending on topdown and
29309467b48Spatrick   // bottom up links to other blocks.
29409467b48Spatrick   void cutHugeBlocks();
29509467b48Spatrick 
29609467b48Spatrick   // Put in one group all instructions with no users in this scheduling region
29709467b48Spatrick   // (we'd want these groups be at the end).
29809467b48Spatrick   void regroupNoUserInstructions();
29909467b48Spatrick 
30009467b48Spatrick   // Give Reserved color to export instructions
30109467b48Spatrick   void colorExports();
30209467b48Spatrick 
30309467b48Spatrick   void createBlocksForVariant(SISchedulerBlockCreatorVariant BlockVariant);
30409467b48Spatrick 
30509467b48Spatrick   void topologicalSort();
30609467b48Spatrick 
30709467b48Spatrick   void scheduleInsideBlocks();
30809467b48Spatrick 
30909467b48Spatrick   void fillStats();
31009467b48Spatrick };
31109467b48Spatrick 
31209467b48Spatrick enum SISchedulerBlockSchedulerVariant {
31309467b48Spatrick   BlockLatencyRegUsage,
31409467b48Spatrick   BlockRegUsageLatency,
31509467b48Spatrick   BlockRegUsage
31609467b48Spatrick };
31709467b48Spatrick 
31809467b48Spatrick class SIScheduleBlockScheduler {
31909467b48Spatrick   SIScheduleDAGMI *DAG;
32009467b48Spatrick   SISchedulerBlockSchedulerVariant Variant;
32109467b48Spatrick   std::vector<SIScheduleBlock*> Blocks;
32209467b48Spatrick 
32309467b48Spatrick   std::vector<std::map<unsigned, unsigned>> LiveOutRegsNumUsages;
32409467b48Spatrick   std::set<unsigned> LiveRegs;
32509467b48Spatrick   // Num of schedulable unscheduled blocks reading the register.
32609467b48Spatrick   std::map<unsigned, unsigned> LiveRegsConsumers;
32709467b48Spatrick 
32809467b48Spatrick   std::vector<unsigned> LastPosHighLatencyParentScheduled;
32909467b48Spatrick   int LastPosWaitedHighLatency;
33009467b48Spatrick 
33109467b48Spatrick   std::vector<SIScheduleBlock*> BlocksScheduled;
33209467b48Spatrick   unsigned NumBlockScheduled;
33309467b48Spatrick   std::vector<SIScheduleBlock*> ReadyBlocks;
33409467b48Spatrick 
33509467b48Spatrick   unsigned VregCurrentUsage;
33609467b48Spatrick   unsigned SregCurrentUsage;
33709467b48Spatrick 
33809467b48Spatrick   // Currently is only approximation.
33909467b48Spatrick   unsigned maxVregUsage;
34009467b48Spatrick   unsigned maxSregUsage;
34109467b48Spatrick 
34209467b48Spatrick   std::vector<unsigned> BlockNumPredsLeft;
34309467b48Spatrick   std::vector<unsigned> BlockNumSuccsLeft;
34409467b48Spatrick 
34509467b48Spatrick public:
34609467b48Spatrick   SIScheduleBlockScheduler(SIScheduleDAGMI *DAG,
34709467b48Spatrick                            SISchedulerBlockSchedulerVariant Variant,
34809467b48Spatrick                            SIScheduleBlocks BlocksStruct);
34909467b48Spatrick   ~SIScheduleBlockScheduler() = default;
35009467b48Spatrick 
getBlocks()35109467b48Spatrick   std::vector<SIScheduleBlock*> getBlocks() { return BlocksScheduled; }
35209467b48Spatrick 
getVGPRUsage()35309467b48Spatrick   unsigned getVGPRUsage() { return maxVregUsage; }
getSGPRUsage()35409467b48Spatrick   unsigned getSGPRUsage() { return maxSregUsage; }
35509467b48Spatrick 
35609467b48Spatrick private:
35709467b48Spatrick   struct SIBlockSchedCandidate : SISchedulerCandidate {
35809467b48Spatrick     // The best Block candidate.
35909467b48Spatrick     SIScheduleBlock *Block = nullptr;
36009467b48Spatrick 
36109467b48Spatrick     bool IsHighLatency;
36209467b48Spatrick     int VGPRUsageDiff;
36309467b48Spatrick     unsigned NumSuccessors;
36409467b48Spatrick     unsigned NumHighLatencySuccessors;
36509467b48Spatrick     unsigned LastPosHighLatParentScheduled;
36609467b48Spatrick     unsigned Height;
36709467b48Spatrick 
36809467b48Spatrick     SIBlockSchedCandidate() = default;
36909467b48Spatrick 
isValidSIBlockSchedCandidate37009467b48Spatrick     bool isValid() const { return Block; }
37109467b48Spatrick 
37209467b48Spatrick     // Copy the status of another candidate without changing policy.
setBestSIBlockSchedCandidate37309467b48Spatrick     void setBest(SIBlockSchedCandidate &Best) {
37409467b48Spatrick       assert(Best.Reason != NoCand && "uninitialized Sched candidate");
37509467b48Spatrick       Block = Best.Block;
37609467b48Spatrick       Reason = Best.Reason;
37709467b48Spatrick       IsHighLatency = Best.IsHighLatency;
37809467b48Spatrick       VGPRUsageDiff = Best.VGPRUsageDiff;
37909467b48Spatrick       NumSuccessors = Best.NumSuccessors;
38009467b48Spatrick       NumHighLatencySuccessors = Best.NumHighLatencySuccessors;
38109467b48Spatrick       LastPosHighLatParentScheduled = Best.LastPosHighLatParentScheduled;
38209467b48Spatrick       Height = Best.Height;
38309467b48Spatrick     }
38409467b48Spatrick   };
38509467b48Spatrick 
38609467b48Spatrick   bool tryCandidateLatency(SIBlockSchedCandidate &Cand,
38709467b48Spatrick                            SIBlockSchedCandidate &TryCand);
38809467b48Spatrick   bool tryCandidateRegUsage(SIBlockSchedCandidate &Cand,
38909467b48Spatrick                             SIBlockSchedCandidate &TryCand);
39009467b48Spatrick   SIScheduleBlock *pickBlock();
39109467b48Spatrick 
39209467b48Spatrick   void addLiveRegs(std::set<unsigned> &Regs);
39309467b48Spatrick   void decreaseLiveRegs(SIScheduleBlock *Block, std::set<unsigned> &Regs);
39409467b48Spatrick   void releaseBlockSuccs(SIScheduleBlock *Parent);
39509467b48Spatrick   void blockScheduled(SIScheduleBlock *Block);
39609467b48Spatrick 
39709467b48Spatrick   // Check register pressure change
39809467b48Spatrick   // by scheduling a block with these LiveIn and LiveOut.
39909467b48Spatrick   std::vector<int> checkRegUsageImpact(std::set<unsigned> &InRegs,
40009467b48Spatrick                                        std::set<unsigned> &OutRegs);
40109467b48Spatrick 
40209467b48Spatrick   void schedule();
40309467b48Spatrick };
40409467b48Spatrick 
40509467b48Spatrick struct SIScheduleBlockResult {
40609467b48Spatrick   std::vector<unsigned> SUs;
40709467b48Spatrick   unsigned MaxSGPRUsage;
40809467b48Spatrick   unsigned MaxVGPRUsage;
40909467b48Spatrick };
41009467b48Spatrick 
41109467b48Spatrick class SIScheduler {
41209467b48Spatrick   SIScheduleDAGMI *DAG;
41309467b48Spatrick   SIScheduleBlockCreator BlockCreator;
41409467b48Spatrick 
41509467b48Spatrick public:
SIScheduler(SIScheduleDAGMI * DAG)41609467b48Spatrick   SIScheduler(SIScheduleDAGMI *DAG) : DAG(DAG), BlockCreator(DAG) {}
41709467b48Spatrick 
41809467b48Spatrick   ~SIScheduler() = default;
41909467b48Spatrick 
42009467b48Spatrick   struct SIScheduleBlockResult
42109467b48Spatrick   scheduleVariant(SISchedulerBlockCreatorVariant BlockVariant,
42209467b48Spatrick                   SISchedulerBlockSchedulerVariant ScheduleVariant);
42309467b48Spatrick };
42409467b48Spatrick 
42509467b48Spatrick class SIScheduleDAGMI final : public ScheduleDAGMILive {
42609467b48Spatrick   const SIInstrInfo *SITII;
42709467b48Spatrick   const SIRegisterInfo *SITRI;
42809467b48Spatrick 
42909467b48Spatrick   std::vector<SUnit> SUnitsLinksBackup;
43009467b48Spatrick 
43109467b48Spatrick   // For moveLowLatencies. After all Scheduling variants are tested.
43209467b48Spatrick   std::vector<unsigned> ScheduledSUnits;
43309467b48Spatrick   std::vector<unsigned> ScheduledSUnitsInv;
43409467b48Spatrick 
43509467b48Spatrick public:
43609467b48Spatrick   SIScheduleDAGMI(MachineSchedContext *C);
43709467b48Spatrick 
43809467b48Spatrick   ~SIScheduleDAGMI() override;
43909467b48Spatrick 
44009467b48Spatrick   // Entry point for the schedule.
44109467b48Spatrick   void schedule() override;
44209467b48Spatrick 
44309467b48Spatrick   // To init Block's RPTracker.
initRPTracker(RegPressureTracker & RPTracker)44409467b48Spatrick   void initRPTracker(RegPressureTracker &RPTracker) {
44509467b48Spatrick     RPTracker.init(&MF, RegClassInfo, LIS, BB, RegionBegin, false, false);
44609467b48Spatrick   }
44709467b48Spatrick 
getBB()44809467b48Spatrick   MachineBasicBlock *getBB() { return BB; }
getCurrentTop()44909467b48Spatrick   MachineBasicBlock::iterator getCurrentTop() { return CurrentTop; }
getCurrentBottom()45009467b48Spatrick   MachineBasicBlock::iterator getCurrentBottom() { return CurrentBottom; }
getLIS()45109467b48Spatrick   LiveIntervals *getLIS() { return LIS; }
getMRI()45209467b48Spatrick   MachineRegisterInfo *getMRI() { return &MRI; }
getTRI()45309467b48Spatrick   const TargetRegisterInfo *getTRI() { return TRI; }
GetTopo()45409467b48Spatrick   ScheduleDAGTopologicalSort *GetTopo() { return &Topo; }
getEntrySU()45509467b48Spatrick   SUnit &getEntrySU() { return EntrySU; }
getExitSU()45609467b48Spatrick   SUnit& getExitSU() { return ExitSU; }
45709467b48Spatrick 
45809467b48Spatrick   void restoreSULinksLeft();
45909467b48Spatrick 
46009467b48Spatrick   template<typename _Iterator> void fillVgprSgprCost(_Iterator First,
46109467b48Spatrick                                                      _Iterator End,
46209467b48Spatrick                                                      unsigned &VgprUsage,
46309467b48Spatrick                                                      unsigned &SgprUsage);
46409467b48Spatrick 
getInRegs()46509467b48Spatrick   std::set<unsigned> getInRegs() {
46609467b48Spatrick     std::set<unsigned> InRegs;
46709467b48Spatrick     for (const auto &RegMaskPair : RPTracker.getPressure().LiveInRegs) {
46809467b48Spatrick       InRegs.insert(RegMaskPair.RegUnit);
46909467b48Spatrick     }
47009467b48Spatrick     return InRegs;
47109467b48Spatrick   }
47209467b48Spatrick 
getOutRegs()47309467b48Spatrick   std::set<unsigned> getOutRegs() {
47409467b48Spatrick     std::set<unsigned> OutRegs;
47509467b48Spatrick     for (const auto &RegMaskPair : RPTracker.getPressure().LiveOutRegs) {
47609467b48Spatrick       OutRegs.insert(RegMaskPair.RegUnit);
47709467b48Spatrick     }
47809467b48Spatrick     return OutRegs;
47909467b48Spatrick   };
48009467b48Spatrick 
48109467b48Spatrick private:
48209467b48Spatrick   void topologicalSort();
48309467b48Spatrick   // After scheduling is done, improve low latency placements.
48409467b48Spatrick   void moveLowLatencies();
48509467b48Spatrick 
48609467b48Spatrick public:
48709467b48Spatrick   // Some stats for scheduling inside blocks.
48809467b48Spatrick   std::vector<unsigned> IsLowLatencySU;
48909467b48Spatrick   std::vector<unsigned> LowLatencyOffset;
49009467b48Spatrick   std::vector<unsigned> IsHighLatencySU;
49109467b48Spatrick   // Topological sort
49209467b48Spatrick   // Maps topological index to the node number.
49309467b48Spatrick   std::vector<int> TopDownIndex2SU;
49409467b48Spatrick   std::vector<int> BottomUpIndex2SU;
49509467b48Spatrick };
49609467b48Spatrick 
49709467b48Spatrick } // end namespace llvm
49809467b48Spatrick 
49909467b48Spatrick #endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINESCHEDULER_H
500