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