xref: /aosp_15_r20/external/llvm/lib/Target/AMDGPU/SIMachineScheduler.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- SIMachineScheduler.h - SI Scheduler Interface -*- 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 /// \file
11*9880d681SAndroid Build Coastguard Worker /// \brief SI Machine Scheduler interface
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_TARGET_AMDGPU_SIMACHINESCHEDULER_H
16*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_TARGET_AMDGPU_SIMACHINESCHEDULER_H
17*9880d681SAndroid Build Coastguard Worker 
18*9880d681SAndroid Build Coastguard Worker #include "SIInstrInfo.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineScheduler.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterPressure.h"
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker using namespace llvm;
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker namespace llvm {
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker enum SIScheduleCandReason {
27*9880d681SAndroid Build Coastguard Worker   NoCand,
28*9880d681SAndroid Build Coastguard Worker   RegUsage,
29*9880d681SAndroid Build Coastguard Worker   Latency,
30*9880d681SAndroid Build Coastguard Worker   Successor,
31*9880d681SAndroid Build Coastguard Worker   Depth,
32*9880d681SAndroid Build Coastguard Worker   NodeOrder
33*9880d681SAndroid Build Coastguard Worker };
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker struct SISchedulerCandidate {
36*9880d681SAndroid Build Coastguard Worker   // The reason for this candidate.
37*9880d681SAndroid Build Coastguard Worker   SIScheduleCandReason Reason;
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker   // Set of reasons that apply to multiple candidates.
40*9880d681SAndroid Build Coastguard Worker   uint32_t RepeatReasonSet;
41*9880d681SAndroid Build Coastguard Worker 
SISchedulerCandidateSISchedulerCandidate42*9880d681SAndroid Build Coastguard Worker   SISchedulerCandidate()
43*9880d681SAndroid Build Coastguard Worker     :  Reason(NoCand), RepeatReasonSet(0) {}
44*9880d681SAndroid Build Coastguard Worker 
isRepeatSISchedulerCandidate45*9880d681SAndroid Build Coastguard Worker   bool isRepeat(SIScheduleCandReason R) { return RepeatReasonSet & (1 << R); }
setRepeatSISchedulerCandidate46*9880d681SAndroid Build Coastguard Worker   void setRepeat(SIScheduleCandReason R) { RepeatReasonSet |= (1 << R); }
47*9880d681SAndroid Build Coastguard Worker };
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker class SIScheduleDAGMI;
50*9880d681SAndroid Build Coastguard Worker class SIScheduleBlockCreator;
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker class SIScheduleBlock {
53*9880d681SAndroid Build Coastguard Worker   SIScheduleDAGMI *DAG;
54*9880d681SAndroid Build Coastguard Worker   SIScheduleBlockCreator *BC;
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker   std::vector<SUnit*> SUnits;
57*9880d681SAndroid Build Coastguard Worker   std::map<unsigned, unsigned> NodeNum2Index;
58*9880d681SAndroid Build Coastguard Worker   std::vector<SUnit*> TopReadySUs;
59*9880d681SAndroid Build Coastguard Worker   std::vector<SUnit*> ScheduledSUnits;
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker   /// The top of the unscheduled zone.
62*9880d681SAndroid Build Coastguard Worker   IntervalPressure TopPressure;
63*9880d681SAndroid Build Coastguard Worker   RegPressureTracker TopRPTracker;
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   // Pressure: number of said class of registers needed to
66*9880d681SAndroid Build Coastguard Worker   // store the live virtual and real registers.
67*9880d681SAndroid Build Coastguard Worker   // We do care only of SGPR32 and VGPR32 and do track only virtual registers.
68*9880d681SAndroid Build Coastguard Worker   // Pressure of additional registers required inside the block.
69*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> InternalAdditionnalPressure;
70*9880d681SAndroid Build Coastguard Worker   // Pressure of input and output registers
71*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> LiveInPressure;
72*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> LiveOutPressure;
73*9880d681SAndroid Build Coastguard Worker   // Registers required by the block, and outputs.
74*9880d681SAndroid Build Coastguard Worker   // We do track only virtual registers.
75*9880d681SAndroid Build Coastguard Worker   // Note that some registers are not 32 bits,
76*9880d681SAndroid Build Coastguard Worker   // and thus the pressure is not equal
77*9880d681SAndroid Build Coastguard Worker   // to the number of live registers.
78*9880d681SAndroid Build Coastguard Worker   std::set<unsigned> LiveInRegs;
79*9880d681SAndroid Build Coastguard Worker   std::set<unsigned> LiveOutRegs;
80*9880d681SAndroid Build Coastguard Worker 
81*9880d681SAndroid Build Coastguard Worker   bool Scheduled;
82*9880d681SAndroid Build Coastguard Worker   bool HighLatencyBlock;
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> HasLowLatencyNonWaitedParent;
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker   // Unique ID, the index of the Block in the SIScheduleDAGMI Blocks table.
87*9880d681SAndroid Build Coastguard Worker   unsigned ID;
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker   std::vector<SIScheduleBlock*> Preds;  // All blocks predecessors.
90*9880d681SAndroid Build Coastguard Worker   std::vector<SIScheduleBlock*> Succs;  // All blocks successors.
91*9880d681SAndroid Build Coastguard Worker   unsigned NumHighLatencySuccessors;
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker public:
SIScheduleBlock(SIScheduleDAGMI * DAG,SIScheduleBlockCreator * BC,unsigned ID)94*9880d681SAndroid Build Coastguard Worker   SIScheduleBlock(SIScheduleDAGMI *DAG, SIScheduleBlockCreator *BC,
95*9880d681SAndroid Build Coastguard Worker                   unsigned ID):
96*9880d681SAndroid Build Coastguard Worker     DAG(DAG), BC(BC), SUnits(), TopReadySUs(), ScheduledSUnits(),
97*9880d681SAndroid Build Coastguard Worker     TopRPTracker(TopPressure), Scheduled(false),
98*9880d681SAndroid Build Coastguard Worker     HighLatencyBlock(false), ID(ID),
99*9880d681SAndroid Build Coastguard Worker     Preds(), Succs(), NumHighLatencySuccessors(0) {};
100*9880d681SAndroid Build Coastguard Worker 
~SIScheduleBlock()101*9880d681SAndroid Build Coastguard Worker   ~SIScheduleBlock() {};
102*9880d681SAndroid Build Coastguard Worker 
getID()103*9880d681SAndroid Build Coastguard Worker   unsigned getID() const { return ID; }
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker   /// Functions for Block construction.
106*9880d681SAndroid Build Coastguard Worker   void addUnit(SUnit *SU);
107*9880d681SAndroid Build Coastguard Worker 
108*9880d681SAndroid Build Coastguard Worker   // When all SUs have been added.
109*9880d681SAndroid Build Coastguard Worker   void finalizeUnits();
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker   // Add block pred, which has instruction predecessor of SU.
112*9880d681SAndroid Build Coastguard Worker   void addPred(SIScheduleBlock *Pred);
113*9880d681SAndroid Build Coastguard Worker   void addSucc(SIScheduleBlock *Succ);
114*9880d681SAndroid Build Coastguard Worker 
getPreds()115*9880d681SAndroid Build Coastguard Worker   const std::vector<SIScheduleBlock*>& getPreds() const { return Preds; }
getSuccs()116*9880d681SAndroid Build Coastguard Worker   const std::vector<SIScheduleBlock*>& getSuccs() const { return Succs; }
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker   unsigned Height;  // Maximum topdown path length to block without outputs
119*9880d681SAndroid Build Coastguard Worker   unsigned Depth;   // Maximum bottomup path length to block without inputs
120*9880d681SAndroid Build Coastguard Worker 
getNumHighLatencySuccessors()121*9880d681SAndroid Build Coastguard Worker   unsigned getNumHighLatencySuccessors() const {
122*9880d681SAndroid Build Coastguard Worker     return NumHighLatencySuccessors;
123*9880d681SAndroid Build Coastguard Worker   }
124*9880d681SAndroid Build Coastguard Worker 
isHighLatencyBlock()125*9880d681SAndroid Build Coastguard Worker   bool isHighLatencyBlock() { return HighLatencyBlock; }
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker   // This is approximative.
128*9880d681SAndroid Build Coastguard Worker   // Ideally should take into accounts some instructions (rcp, etc)
129*9880d681SAndroid Build Coastguard Worker   // are 4 times slower.
getCost()130*9880d681SAndroid Build Coastguard Worker   int getCost() { return SUnits.size(); }
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker   // The block Predecessors and Successors must be all registered
133*9880d681SAndroid Build Coastguard Worker   // before fastSchedule().
134*9880d681SAndroid Build Coastguard Worker   // Fast schedule with no particular requirement.
135*9880d681SAndroid Build Coastguard Worker   void fastSchedule();
136*9880d681SAndroid Build Coastguard Worker 
getScheduledUnits()137*9880d681SAndroid Build Coastguard Worker   std::vector<SUnit*> getScheduledUnits() { return ScheduledSUnits; }
138*9880d681SAndroid Build Coastguard Worker 
139*9880d681SAndroid Build Coastguard Worker   // Complete schedule that will try to minimize reg pressure and
140*9880d681SAndroid Build Coastguard Worker   // low latencies, and will fill liveins and liveouts.
141*9880d681SAndroid Build Coastguard Worker   // Needs all MIs to be grouped between BeginBlock and EndBlock.
142*9880d681SAndroid Build Coastguard Worker   // The MIs can be moved after the scheduling,
143*9880d681SAndroid Build Coastguard Worker   // it is just used to allow correct track of live registers.
144*9880d681SAndroid Build Coastguard Worker   void schedule(MachineBasicBlock::iterator BeginBlock,
145*9880d681SAndroid Build Coastguard Worker                 MachineBasicBlock::iterator EndBlock);
146*9880d681SAndroid Build Coastguard Worker 
isScheduled()147*9880d681SAndroid Build Coastguard Worker   bool isScheduled() { return Scheduled; }
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker   // Needs the block to be scheduled inside
151*9880d681SAndroid Build Coastguard Worker   // TODO: find a way to compute it.
getInternalAdditionnalRegUsage()152*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> &getInternalAdditionnalRegUsage() {
153*9880d681SAndroid Build Coastguard Worker     return InternalAdditionnalPressure;
154*9880d681SAndroid Build Coastguard Worker   }
155*9880d681SAndroid Build Coastguard Worker 
getInRegs()156*9880d681SAndroid Build Coastguard Worker   std::set<unsigned> &getInRegs() { return LiveInRegs; }
getOutRegs()157*9880d681SAndroid Build Coastguard Worker   std::set<unsigned> &getOutRegs() { return LiveOutRegs; }
158*9880d681SAndroid Build Coastguard Worker 
159*9880d681SAndroid Build Coastguard Worker   void printDebug(bool Full);
160*9880d681SAndroid Build Coastguard Worker 
161*9880d681SAndroid Build Coastguard Worker private:
162*9880d681SAndroid Build Coastguard Worker   struct SISchedCandidate : SISchedulerCandidate {
163*9880d681SAndroid Build Coastguard Worker     // The best SUnit candidate.
164*9880d681SAndroid Build Coastguard Worker     SUnit *SU;
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker     unsigned SGPRUsage;
167*9880d681SAndroid Build Coastguard Worker     unsigned VGPRUsage;
168*9880d681SAndroid Build Coastguard Worker     bool IsLowLatency;
169*9880d681SAndroid Build Coastguard Worker     unsigned LowLatencyOffset;
170*9880d681SAndroid Build Coastguard Worker     bool HasLowLatencyNonWaitedParent;
171*9880d681SAndroid Build Coastguard Worker 
SISchedCandidateSISchedCandidate172*9880d681SAndroid Build Coastguard Worker     SISchedCandidate()
173*9880d681SAndroid Build Coastguard Worker       : SU(nullptr) {}
174*9880d681SAndroid Build Coastguard Worker 
isValidSISchedCandidate175*9880d681SAndroid Build Coastguard Worker     bool isValid() const { return SU; }
176*9880d681SAndroid Build Coastguard Worker 
177*9880d681SAndroid Build Coastguard Worker     // Copy the status of another candidate without changing policy.
setBestSISchedCandidate178*9880d681SAndroid Build Coastguard Worker     void setBest(SISchedCandidate &Best) {
179*9880d681SAndroid Build Coastguard Worker       assert(Best.Reason != NoCand && "uninitialized Sched candidate");
180*9880d681SAndroid Build Coastguard Worker       SU = Best.SU;
181*9880d681SAndroid Build Coastguard Worker       Reason = Best.Reason;
182*9880d681SAndroid Build Coastguard Worker       SGPRUsage = Best.SGPRUsage;
183*9880d681SAndroid Build Coastguard Worker       VGPRUsage = Best.VGPRUsage;
184*9880d681SAndroid Build Coastguard Worker       IsLowLatency = Best.IsLowLatency;
185*9880d681SAndroid Build Coastguard Worker       LowLatencyOffset = Best.LowLatencyOffset;
186*9880d681SAndroid Build Coastguard Worker       HasLowLatencyNonWaitedParent = Best.HasLowLatencyNonWaitedParent;
187*9880d681SAndroid Build Coastguard Worker     }
188*9880d681SAndroid Build Coastguard Worker   };
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker   void undoSchedule();
191*9880d681SAndroid Build Coastguard Worker 
192*9880d681SAndroid Build Coastguard Worker   void undoReleaseSucc(SUnit *SU, SDep *SuccEdge);
193*9880d681SAndroid Build Coastguard Worker   void releaseSucc(SUnit *SU, SDep *SuccEdge);
194*9880d681SAndroid Build Coastguard Worker   // InOrOutBlock: restrict to links pointing inside the block (true),
195*9880d681SAndroid Build Coastguard Worker   // or restrict to links pointing outside the block (false).
196*9880d681SAndroid Build Coastguard Worker   void releaseSuccessors(SUnit *SU, bool InOrOutBlock);
197*9880d681SAndroid Build Coastguard Worker 
198*9880d681SAndroid Build Coastguard Worker   void nodeScheduled(SUnit *SU);
199*9880d681SAndroid Build Coastguard Worker   void tryCandidateTopDown(SISchedCandidate &Cand, SISchedCandidate &TryCand);
200*9880d681SAndroid Build Coastguard Worker   void tryCandidateBottomUp(SISchedCandidate &Cand, SISchedCandidate &TryCand);
201*9880d681SAndroid Build Coastguard Worker   SUnit* pickNode();
202*9880d681SAndroid Build Coastguard Worker   void traceCandidate(const SISchedCandidate &Cand);
203*9880d681SAndroid Build Coastguard Worker   void initRegPressure(MachineBasicBlock::iterator BeginBlock,
204*9880d681SAndroid Build Coastguard Worker                        MachineBasicBlock::iterator EndBlock);
205*9880d681SAndroid Build Coastguard Worker };
206*9880d681SAndroid Build Coastguard Worker 
207*9880d681SAndroid Build Coastguard Worker struct SIScheduleBlocks {
208*9880d681SAndroid Build Coastguard Worker   std::vector<SIScheduleBlock*> Blocks;
209*9880d681SAndroid Build Coastguard Worker   std::vector<int> TopDownIndex2Block;
210*9880d681SAndroid Build Coastguard Worker   std::vector<int> TopDownBlock2Index;
211*9880d681SAndroid Build Coastguard Worker };
212*9880d681SAndroid Build Coastguard Worker 
213*9880d681SAndroid Build Coastguard Worker enum SISchedulerBlockCreatorVariant {
214*9880d681SAndroid Build Coastguard Worker     LatenciesAlone,
215*9880d681SAndroid Build Coastguard Worker     LatenciesGrouped,
216*9880d681SAndroid Build Coastguard Worker     LatenciesAlonePlusConsecutive
217*9880d681SAndroid Build Coastguard Worker };
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker class SIScheduleBlockCreator {
220*9880d681SAndroid Build Coastguard Worker   SIScheduleDAGMI *DAG;
221*9880d681SAndroid Build Coastguard Worker   // unique_ptr handles freeing memory for us.
222*9880d681SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<SIScheduleBlock>> BlockPtrs;
223*9880d681SAndroid Build Coastguard Worker   std::map<SISchedulerBlockCreatorVariant,
224*9880d681SAndroid Build Coastguard Worker            SIScheduleBlocks> Blocks;
225*9880d681SAndroid Build Coastguard Worker   std::vector<SIScheduleBlock*> CurrentBlocks;
226*9880d681SAndroid Build Coastguard Worker   std::vector<int> Node2CurrentBlock;
227*9880d681SAndroid Build Coastguard Worker 
228*9880d681SAndroid Build Coastguard Worker   // Topological sort
229*9880d681SAndroid Build Coastguard Worker   // Maps topological index to the node number.
230*9880d681SAndroid Build Coastguard Worker   std::vector<int> TopDownIndex2Block;
231*9880d681SAndroid Build Coastguard Worker   std::vector<int> TopDownBlock2Index;
232*9880d681SAndroid Build Coastguard Worker   std::vector<int> BottomUpIndex2Block;
233*9880d681SAndroid Build Coastguard Worker 
234*9880d681SAndroid Build Coastguard Worker   // 0 -> Color not given.
235*9880d681SAndroid Build Coastguard Worker   // 1 to SUnits.size() -> Reserved group (you should only add elements to them).
236*9880d681SAndroid Build Coastguard Worker   // Above -> Other groups.
237*9880d681SAndroid Build Coastguard Worker   int NextReservedID;
238*9880d681SAndroid Build Coastguard Worker   int NextNonReservedID;
239*9880d681SAndroid Build Coastguard Worker   std::vector<int> CurrentColoring;
240*9880d681SAndroid Build Coastguard Worker   std::vector<int> CurrentTopDownReservedDependencyColoring;
241*9880d681SAndroid Build Coastguard Worker   std::vector<int> CurrentBottomUpReservedDependencyColoring;
242*9880d681SAndroid Build Coastguard Worker 
243*9880d681SAndroid Build Coastguard Worker public:
244*9880d681SAndroid Build Coastguard Worker   SIScheduleBlockCreator(SIScheduleDAGMI *DAG);
245*9880d681SAndroid Build Coastguard Worker   ~SIScheduleBlockCreator();
246*9880d681SAndroid Build Coastguard Worker 
247*9880d681SAndroid Build Coastguard Worker   SIScheduleBlocks
248*9880d681SAndroid Build Coastguard Worker   getBlocks(SISchedulerBlockCreatorVariant BlockVariant);
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker   bool isSUInBlock(SUnit *SU, unsigned ID);
251*9880d681SAndroid Build Coastguard Worker 
252*9880d681SAndroid Build Coastguard Worker private:
253*9880d681SAndroid Build Coastguard Worker   // Give a Reserved color to every high latency.
254*9880d681SAndroid Build Coastguard Worker   void colorHighLatenciesAlone();
255*9880d681SAndroid Build Coastguard Worker 
256*9880d681SAndroid Build Coastguard Worker   // Create groups of high latencies with a Reserved color.
257*9880d681SAndroid Build Coastguard Worker   void colorHighLatenciesGroups();
258*9880d681SAndroid Build Coastguard Worker 
259*9880d681SAndroid Build Coastguard Worker   // Compute coloring for topdown and bottom traversals with
260*9880d681SAndroid Build Coastguard Worker   // different colors depending on dependencies on Reserved colors.
261*9880d681SAndroid Build Coastguard Worker   void colorComputeReservedDependencies();
262*9880d681SAndroid Build Coastguard Worker 
263*9880d681SAndroid Build Coastguard Worker   // Give color to all non-colored SUs according to Reserved groups dependencies.
264*9880d681SAndroid Build Coastguard Worker   void colorAccordingToReservedDependencies();
265*9880d681SAndroid Build Coastguard Worker 
266*9880d681SAndroid Build Coastguard Worker   // Divides Blocks having no bottom up or top down dependencies on Reserved groups.
267*9880d681SAndroid Build Coastguard Worker   // The new colors are computed according to the dependencies on the other blocks
268*9880d681SAndroid Build Coastguard Worker   // formed with colorAccordingToReservedDependencies.
269*9880d681SAndroid Build Coastguard Worker   void colorEndsAccordingToDependencies();
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker   // Cut groups into groups with SUs in consecutive order (except for Reserved groups).
272*9880d681SAndroid Build Coastguard Worker   void colorForceConsecutiveOrderInGroup();
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker   // Merge Constant loads that have all their users into another group to the group.
275*9880d681SAndroid Build Coastguard Worker   // (TODO: else if all their users depend on the same group, put them there)
276*9880d681SAndroid Build Coastguard Worker   void colorMergeConstantLoadsNextGroup();
277*9880d681SAndroid Build Coastguard Worker 
278*9880d681SAndroid Build Coastguard Worker   // Merge SUs that have all their users into another group to the group
279*9880d681SAndroid Build Coastguard Worker   void colorMergeIfPossibleNextGroup();
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker   // Merge SUs that have all their users into another group to the group,
282*9880d681SAndroid Build Coastguard Worker   // but only for Reserved groups.
283*9880d681SAndroid Build Coastguard Worker   void colorMergeIfPossibleNextGroupOnlyForReserved();
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker   // Merge SUs that have all their users into another group to the group,
286*9880d681SAndroid Build Coastguard Worker   // but only if the group is no more than a few SUs.
287*9880d681SAndroid Build Coastguard Worker   void colorMergeIfPossibleSmallGroupsToNextGroup();
288*9880d681SAndroid Build Coastguard Worker 
289*9880d681SAndroid Build Coastguard Worker   // Divides Blocks with important size.
290*9880d681SAndroid Build Coastguard Worker   // Idea of implementation: attribute new colors depending on topdown and
291*9880d681SAndroid Build Coastguard Worker   // bottom up links to other blocks.
292*9880d681SAndroid Build Coastguard Worker   void cutHugeBlocks();
293*9880d681SAndroid Build Coastguard Worker 
294*9880d681SAndroid Build Coastguard Worker   // Put in one group all instructions with no users in this scheduling region
295*9880d681SAndroid Build Coastguard Worker   // (we'd want these groups be at the end).
296*9880d681SAndroid Build Coastguard Worker   void regroupNoUserInstructions();
297*9880d681SAndroid Build Coastguard Worker 
298*9880d681SAndroid Build Coastguard Worker   void createBlocksForVariant(SISchedulerBlockCreatorVariant BlockVariant);
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker   void topologicalSort();
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker   void scheduleInsideBlocks();
303*9880d681SAndroid Build Coastguard Worker 
304*9880d681SAndroid Build Coastguard Worker   void fillStats();
305*9880d681SAndroid Build Coastguard Worker };
306*9880d681SAndroid Build Coastguard Worker 
307*9880d681SAndroid Build Coastguard Worker enum SISchedulerBlockSchedulerVariant {
308*9880d681SAndroid Build Coastguard Worker   BlockLatencyRegUsage,
309*9880d681SAndroid Build Coastguard Worker   BlockRegUsageLatency,
310*9880d681SAndroid Build Coastguard Worker   BlockRegUsage
311*9880d681SAndroid Build Coastguard Worker };
312*9880d681SAndroid Build Coastguard Worker 
313*9880d681SAndroid Build Coastguard Worker class SIScheduleBlockScheduler {
314*9880d681SAndroid Build Coastguard Worker   SIScheduleDAGMI *DAG;
315*9880d681SAndroid Build Coastguard Worker   SISchedulerBlockSchedulerVariant Variant;
316*9880d681SAndroid Build Coastguard Worker   std::vector<SIScheduleBlock*> Blocks;
317*9880d681SAndroid Build Coastguard Worker 
318*9880d681SAndroid Build Coastguard Worker   std::vector<std::map<unsigned, unsigned>> LiveOutRegsNumUsages;
319*9880d681SAndroid Build Coastguard Worker   std::set<unsigned> LiveRegs;
320*9880d681SAndroid Build Coastguard Worker   // Num of schedulable unscheduled blocks reading the register.
321*9880d681SAndroid Build Coastguard Worker   std::map<unsigned, unsigned> LiveRegsConsumers;
322*9880d681SAndroid Build Coastguard Worker 
323*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> LastPosHighLatencyParentScheduled;
324*9880d681SAndroid Build Coastguard Worker   int LastPosWaitedHighLatency;
325*9880d681SAndroid Build Coastguard Worker 
326*9880d681SAndroid Build Coastguard Worker   std::vector<SIScheduleBlock*> BlocksScheduled;
327*9880d681SAndroid Build Coastguard Worker   unsigned NumBlockScheduled;
328*9880d681SAndroid Build Coastguard Worker   std::vector<SIScheduleBlock*> ReadyBlocks;
329*9880d681SAndroid Build Coastguard Worker 
330*9880d681SAndroid Build Coastguard Worker   unsigned VregCurrentUsage;
331*9880d681SAndroid Build Coastguard Worker   unsigned SregCurrentUsage;
332*9880d681SAndroid Build Coastguard Worker 
333*9880d681SAndroid Build Coastguard Worker   // Currently is only approximation.
334*9880d681SAndroid Build Coastguard Worker   unsigned maxVregUsage;
335*9880d681SAndroid Build Coastguard Worker   unsigned maxSregUsage;
336*9880d681SAndroid Build Coastguard Worker 
337*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> BlockNumPredsLeft;
338*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> BlockNumSuccsLeft;
339*9880d681SAndroid Build Coastguard Worker 
340*9880d681SAndroid Build Coastguard Worker public:
341*9880d681SAndroid Build Coastguard Worker   SIScheduleBlockScheduler(SIScheduleDAGMI *DAG,
342*9880d681SAndroid Build Coastguard Worker                            SISchedulerBlockSchedulerVariant Variant,
343*9880d681SAndroid Build Coastguard Worker                            SIScheduleBlocks BlocksStruct);
~SIScheduleBlockScheduler()344*9880d681SAndroid Build Coastguard Worker   ~SIScheduleBlockScheduler() {};
345*9880d681SAndroid Build Coastguard Worker 
getBlocks()346*9880d681SAndroid Build Coastguard Worker   std::vector<SIScheduleBlock*> getBlocks() { return BlocksScheduled; };
347*9880d681SAndroid Build Coastguard Worker 
getVGPRUsage()348*9880d681SAndroid Build Coastguard Worker   unsigned getVGPRUsage() { return maxVregUsage; };
getSGPRUsage()349*9880d681SAndroid Build Coastguard Worker   unsigned getSGPRUsage() { return maxSregUsage; };
350*9880d681SAndroid Build Coastguard Worker 
351*9880d681SAndroid Build Coastguard Worker private:
352*9880d681SAndroid Build Coastguard Worker   struct SIBlockSchedCandidate : SISchedulerCandidate {
353*9880d681SAndroid Build Coastguard Worker     // The best Block candidate.
354*9880d681SAndroid Build Coastguard Worker     SIScheduleBlock *Block;
355*9880d681SAndroid Build Coastguard Worker 
356*9880d681SAndroid Build Coastguard Worker     bool IsHighLatency;
357*9880d681SAndroid Build Coastguard Worker     int VGPRUsageDiff;
358*9880d681SAndroid Build Coastguard Worker     unsigned NumSuccessors;
359*9880d681SAndroid Build Coastguard Worker     unsigned NumHighLatencySuccessors;
360*9880d681SAndroid Build Coastguard Worker     unsigned LastPosHighLatParentScheduled;
361*9880d681SAndroid Build Coastguard Worker     unsigned Height;
362*9880d681SAndroid Build Coastguard Worker 
SIBlockSchedCandidateSIBlockSchedCandidate363*9880d681SAndroid Build Coastguard Worker     SIBlockSchedCandidate()
364*9880d681SAndroid Build Coastguard Worker       : Block(nullptr) {}
365*9880d681SAndroid Build Coastguard Worker 
isValidSIBlockSchedCandidate366*9880d681SAndroid Build Coastguard Worker     bool isValid() const { return Block; }
367*9880d681SAndroid Build Coastguard Worker 
368*9880d681SAndroid Build Coastguard Worker     // Copy the status of another candidate without changing policy.
setBestSIBlockSchedCandidate369*9880d681SAndroid Build Coastguard Worker     void setBest(SIBlockSchedCandidate &Best) {
370*9880d681SAndroid Build Coastguard Worker       assert(Best.Reason != NoCand && "uninitialized Sched candidate");
371*9880d681SAndroid Build Coastguard Worker       Block = Best.Block;
372*9880d681SAndroid Build Coastguard Worker       Reason = Best.Reason;
373*9880d681SAndroid Build Coastguard Worker       IsHighLatency = Best.IsHighLatency;
374*9880d681SAndroid Build Coastguard Worker       VGPRUsageDiff = Best.VGPRUsageDiff;
375*9880d681SAndroid Build Coastguard Worker       NumSuccessors = Best.NumSuccessors;
376*9880d681SAndroid Build Coastguard Worker       NumHighLatencySuccessors = Best.NumHighLatencySuccessors;
377*9880d681SAndroid Build Coastguard Worker       LastPosHighLatParentScheduled = Best.LastPosHighLatParentScheduled;
378*9880d681SAndroid Build Coastguard Worker       Height = Best.Height;
379*9880d681SAndroid Build Coastguard Worker     }
380*9880d681SAndroid Build Coastguard Worker   };
381*9880d681SAndroid Build Coastguard Worker 
382*9880d681SAndroid Build Coastguard Worker   bool tryCandidateLatency(SIBlockSchedCandidate &Cand,
383*9880d681SAndroid Build Coastguard Worker                            SIBlockSchedCandidate &TryCand);
384*9880d681SAndroid Build Coastguard Worker   bool tryCandidateRegUsage(SIBlockSchedCandidate &Cand,
385*9880d681SAndroid Build Coastguard Worker                             SIBlockSchedCandidate &TryCand);
386*9880d681SAndroid Build Coastguard Worker   SIScheduleBlock *pickBlock();
387*9880d681SAndroid Build Coastguard Worker 
388*9880d681SAndroid Build Coastguard Worker   void addLiveRegs(std::set<unsigned> &Regs);
389*9880d681SAndroid Build Coastguard Worker   void decreaseLiveRegs(SIScheduleBlock *Block, std::set<unsigned> &Regs);
390*9880d681SAndroid Build Coastguard Worker   void releaseBlockSuccs(SIScheduleBlock *Parent);
391*9880d681SAndroid Build Coastguard Worker   void blockScheduled(SIScheduleBlock *Block);
392*9880d681SAndroid Build Coastguard Worker 
393*9880d681SAndroid Build Coastguard Worker   // Check register pressure change
394*9880d681SAndroid Build Coastguard Worker   // by scheduling a block with these LiveIn and LiveOut.
395*9880d681SAndroid Build Coastguard Worker   std::vector<int> checkRegUsageImpact(std::set<unsigned> &InRegs,
396*9880d681SAndroid Build Coastguard Worker                                        std::set<unsigned> &OutRegs);
397*9880d681SAndroid Build Coastguard Worker 
398*9880d681SAndroid Build Coastguard Worker   void schedule();
399*9880d681SAndroid Build Coastguard Worker };
400*9880d681SAndroid Build Coastguard Worker 
401*9880d681SAndroid Build Coastguard Worker struct SIScheduleBlockResult {
402*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> SUs;
403*9880d681SAndroid Build Coastguard Worker   unsigned MaxSGPRUsage;
404*9880d681SAndroid Build Coastguard Worker   unsigned MaxVGPRUsage;
405*9880d681SAndroid Build Coastguard Worker };
406*9880d681SAndroid Build Coastguard Worker 
407*9880d681SAndroid Build Coastguard Worker class SIScheduler {
408*9880d681SAndroid Build Coastguard Worker   SIScheduleDAGMI *DAG;
409*9880d681SAndroid Build Coastguard Worker   SIScheduleBlockCreator BlockCreator;
410*9880d681SAndroid Build Coastguard Worker 
411*9880d681SAndroid Build Coastguard Worker public:
SIScheduler(SIScheduleDAGMI * DAG)412*9880d681SAndroid Build Coastguard Worker   SIScheduler(SIScheduleDAGMI *DAG) : DAG(DAG), BlockCreator(DAG) {};
413*9880d681SAndroid Build Coastguard Worker 
~SIScheduler()414*9880d681SAndroid Build Coastguard Worker   ~SIScheduler() {};
415*9880d681SAndroid Build Coastguard Worker 
416*9880d681SAndroid Build Coastguard Worker   struct SIScheduleBlockResult
417*9880d681SAndroid Build Coastguard Worker   scheduleVariant(SISchedulerBlockCreatorVariant BlockVariant,
418*9880d681SAndroid Build Coastguard Worker                   SISchedulerBlockSchedulerVariant ScheduleVariant);
419*9880d681SAndroid Build Coastguard Worker };
420*9880d681SAndroid Build Coastguard Worker 
421*9880d681SAndroid Build Coastguard Worker class SIScheduleDAGMI final : public ScheduleDAGMILive {
422*9880d681SAndroid Build Coastguard Worker   const SIInstrInfo *SITII;
423*9880d681SAndroid Build Coastguard Worker   const SIRegisterInfo *SITRI;
424*9880d681SAndroid Build Coastguard Worker 
425*9880d681SAndroid Build Coastguard Worker   std::vector<SUnit> SUnitsLinksBackup;
426*9880d681SAndroid Build Coastguard Worker 
427*9880d681SAndroid Build Coastguard Worker   // For moveLowLatencies. After all Scheduling variants are tested.
428*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> ScheduledSUnits;
429*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> ScheduledSUnitsInv;
430*9880d681SAndroid Build Coastguard Worker 
431*9880d681SAndroid Build Coastguard Worker   unsigned VGPRSetID;
432*9880d681SAndroid Build Coastguard Worker   unsigned SGPRSetID;
433*9880d681SAndroid Build Coastguard Worker 
434*9880d681SAndroid Build Coastguard Worker public:
435*9880d681SAndroid Build Coastguard Worker   SIScheduleDAGMI(MachineSchedContext *C);
436*9880d681SAndroid Build Coastguard Worker 
437*9880d681SAndroid Build Coastguard Worker   ~SIScheduleDAGMI() override;
438*9880d681SAndroid Build Coastguard Worker 
439*9880d681SAndroid Build Coastguard Worker   // Entry point for the schedule.
440*9880d681SAndroid Build Coastguard Worker   void schedule() override;
441*9880d681SAndroid Build Coastguard Worker 
442*9880d681SAndroid Build Coastguard Worker   // To init Block's RPTracker.
initRPTracker(RegPressureTracker & RPTracker)443*9880d681SAndroid Build Coastguard Worker   void initRPTracker(RegPressureTracker &RPTracker) {
444*9880d681SAndroid Build Coastguard Worker     RPTracker.init(&MF, RegClassInfo, LIS, BB, RegionBegin, false, false);
445*9880d681SAndroid Build Coastguard Worker   }
446*9880d681SAndroid Build Coastguard Worker 
getBB()447*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *getBB() { return BB; }
getCurrentTop()448*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator getCurrentTop() { return CurrentTop; };
getCurrentBottom()449*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator getCurrentBottom() { return CurrentBottom; };
getLIS()450*9880d681SAndroid Build Coastguard Worker   LiveIntervals *getLIS() { return LIS; }
getMRI()451*9880d681SAndroid Build Coastguard Worker   MachineRegisterInfo *getMRI() { return &MRI; }
getTRI()452*9880d681SAndroid Build Coastguard Worker   const TargetRegisterInfo *getTRI() { return TRI; }
getEntrySU()453*9880d681SAndroid Build Coastguard Worker   SUnit& getEntrySU() { return EntrySU; };
getExitSU()454*9880d681SAndroid Build Coastguard Worker   SUnit& getExitSU() { return ExitSU; };
455*9880d681SAndroid Build Coastguard Worker 
456*9880d681SAndroid Build Coastguard Worker   void restoreSULinksLeft();
457*9880d681SAndroid Build Coastguard Worker 
458*9880d681SAndroid Build Coastguard Worker   template<typename _Iterator> void fillVgprSgprCost(_Iterator First,
459*9880d681SAndroid Build Coastguard Worker                                                      _Iterator End,
460*9880d681SAndroid Build Coastguard Worker                                                      unsigned &VgprUsage,
461*9880d681SAndroid Build Coastguard Worker                                                      unsigned &SgprUsage);
getInRegs()462*9880d681SAndroid Build Coastguard Worker   std::set<unsigned> getInRegs() {
463*9880d681SAndroid Build Coastguard Worker     std::set<unsigned> InRegs;
464*9880d681SAndroid Build Coastguard Worker     for (const auto &RegMaskPair : RPTracker.getPressure().LiveInRegs) {
465*9880d681SAndroid Build Coastguard Worker       InRegs.insert(RegMaskPair.RegUnit);
466*9880d681SAndroid Build Coastguard Worker     }
467*9880d681SAndroid Build Coastguard Worker     return InRegs;
468*9880d681SAndroid Build Coastguard Worker   };
469*9880d681SAndroid Build Coastguard Worker 
getVGPRSetID()470*9880d681SAndroid Build Coastguard Worker   unsigned getVGPRSetID() const { return VGPRSetID; }
getSGPRSetID()471*9880d681SAndroid Build Coastguard Worker   unsigned getSGPRSetID() const { return SGPRSetID; }
472*9880d681SAndroid Build Coastguard Worker 
473*9880d681SAndroid Build Coastguard Worker private:
474*9880d681SAndroid Build Coastguard Worker   void topologicalSort();
475*9880d681SAndroid Build Coastguard Worker   // After scheduling is done, improve low latency placements.
476*9880d681SAndroid Build Coastguard Worker   void moveLowLatencies();
477*9880d681SAndroid Build Coastguard Worker 
478*9880d681SAndroid Build Coastguard Worker public:
479*9880d681SAndroid Build Coastguard Worker   // Some stats for scheduling inside blocks.
480*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> IsLowLatencySU;
481*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> LowLatencyOffset;
482*9880d681SAndroid Build Coastguard Worker   std::vector<unsigned> IsHighLatencySU;
483*9880d681SAndroid Build Coastguard Worker   // Topological sort
484*9880d681SAndroid Build Coastguard Worker   // Maps topological index to the node number.
485*9880d681SAndroid Build Coastguard Worker   std::vector<int> TopDownIndex2SU;
486*9880d681SAndroid Build Coastguard Worker   std::vector<int> BottomUpIndex2SU;
487*9880d681SAndroid Build Coastguard Worker };
488*9880d681SAndroid Build Coastguard Worker 
489*9880d681SAndroid Build Coastguard Worker } // namespace llvm
490*9880d681SAndroid Build Coastguard Worker 
491*9880d681SAndroid Build Coastguard Worker #endif /* SIMACHINESCHEDULER_H_ */
492