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