1*9880d681SAndroid Build Coastguard Worker //===-- HexagonMachineScheduler.h - Custom Hexagon MI scheduler. ----===// 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 // Custom Hexagon MI scheduler. 11*9880d681SAndroid Build Coastguard Worker // 12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 13*9880d681SAndroid Build Coastguard Worker 14*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H 15*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H 16*9880d681SAndroid Build Coastguard Worker 17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/PriorityQueue.h" 18*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AliasAnalysis.h" 19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/LiveIntervalAnalysis.h" 20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineScheduler.h" 21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h" 22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterClassInfo.h" 23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterPressure.h" 24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ResourcePriorityQueue.h" 25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleDAGInstrs.h" 26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleHazardRecognizer.h" 27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h" 28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h" 29*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h" 30*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h" 31*9880d681SAndroid Build Coastguard Worker 32*9880d681SAndroid Build Coastguard Worker using namespace llvm; 33*9880d681SAndroid Build Coastguard Worker 34*9880d681SAndroid Build Coastguard Worker namespace llvm { 35*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 36*9880d681SAndroid Build Coastguard Worker // ConvergingVLIWScheduler - Implementation of the standard 37*9880d681SAndroid Build Coastguard Worker // MachineSchedStrategy. 38*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 39*9880d681SAndroid Build Coastguard Worker 40*9880d681SAndroid Build Coastguard Worker class VLIWResourceModel { 41*9880d681SAndroid Build Coastguard Worker /// ResourcesModel - Represents VLIW state. 42*9880d681SAndroid Build Coastguard Worker /// Not limited to VLIW targets per say, but assumes 43*9880d681SAndroid Build Coastguard Worker /// definition of DFA by a target. 44*9880d681SAndroid Build Coastguard Worker DFAPacketizer *ResourcesModel; 45*9880d681SAndroid Build Coastguard Worker 46*9880d681SAndroid Build Coastguard Worker const TargetSchedModel *SchedModel; 47*9880d681SAndroid Build Coastguard Worker 48*9880d681SAndroid Build Coastguard Worker /// Local packet/bundle model. Purely 49*9880d681SAndroid Build Coastguard Worker /// internal to the MI schedulre at the time. 50*9880d681SAndroid Build Coastguard Worker std::vector<SUnit*> Packet; 51*9880d681SAndroid Build Coastguard Worker 52*9880d681SAndroid Build Coastguard Worker /// Total packets created. 53*9880d681SAndroid Build Coastguard Worker unsigned TotalPackets; 54*9880d681SAndroid Build Coastguard Worker 55*9880d681SAndroid Build Coastguard Worker public: VLIWResourceModel(const TargetSubtargetInfo & STI,const TargetSchedModel * SM)56*9880d681SAndroid Build Coastguard Worker VLIWResourceModel(const TargetSubtargetInfo &STI, const TargetSchedModel *SM) 57*9880d681SAndroid Build Coastguard Worker : SchedModel(SM), TotalPackets(0) { 58*9880d681SAndroid Build Coastguard Worker ResourcesModel = STI.getInstrInfo()->CreateTargetScheduleState(STI); 59*9880d681SAndroid Build Coastguard Worker 60*9880d681SAndroid Build Coastguard Worker // This hard requirement could be relaxed, 61*9880d681SAndroid Build Coastguard Worker // but for now do not let it proceed. 62*9880d681SAndroid Build Coastguard Worker assert(ResourcesModel && "Unimplemented CreateTargetScheduleState."); 63*9880d681SAndroid Build Coastguard Worker 64*9880d681SAndroid Build Coastguard Worker Packet.resize(SchedModel->getIssueWidth()); 65*9880d681SAndroid Build Coastguard Worker Packet.clear(); 66*9880d681SAndroid Build Coastguard Worker ResourcesModel->clearResources(); 67*9880d681SAndroid Build Coastguard Worker } 68*9880d681SAndroid Build Coastguard Worker ~VLIWResourceModel()69*9880d681SAndroid Build Coastguard Worker ~VLIWResourceModel() { 70*9880d681SAndroid Build Coastguard Worker delete ResourcesModel; 71*9880d681SAndroid Build Coastguard Worker } 72*9880d681SAndroid Build Coastguard Worker resetPacketState()73*9880d681SAndroid Build Coastguard Worker void resetPacketState() { 74*9880d681SAndroid Build Coastguard Worker Packet.clear(); 75*9880d681SAndroid Build Coastguard Worker } 76*9880d681SAndroid Build Coastguard Worker resetDFA()77*9880d681SAndroid Build Coastguard Worker void resetDFA() { 78*9880d681SAndroid Build Coastguard Worker ResourcesModel->clearResources(); 79*9880d681SAndroid Build Coastguard Worker } 80*9880d681SAndroid Build Coastguard Worker reset()81*9880d681SAndroid Build Coastguard Worker void reset() { 82*9880d681SAndroid Build Coastguard Worker Packet.clear(); 83*9880d681SAndroid Build Coastguard Worker ResourcesModel->clearResources(); 84*9880d681SAndroid Build Coastguard Worker } 85*9880d681SAndroid Build Coastguard Worker 86*9880d681SAndroid Build Coastguard Worker bool isResourceAvailable(SUnit *SU); 87*9880d681SAndroid Build Coastguard Worker bool reserveResources(SUnit *SU); getTotalPackets()88*9880d681SAndroid Build Coastguard Worker unsigned getTotalPackets() const { return TotalPackets; } 89*9880d681SAndroid Build Coastguard Worker }; 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker /// Extend the standard ScheduleDAGMI to provide more context and override the 92*9880d681SAndroid Build Coastguard Worker /// top-level schedule() driver. 93*9880d681SAndroid Build Coastguard Worker class VLIWMachineScheduler : public ScheduleDAGMILive { 94*9880d681SAndroid Build Coastguard Worker public: VLIWMachineScheduler(MachineSchedContext * C,std::unique_ptr<MachineSchedStrategy> S)95*9880d681SAndroid Build Coastguard Worker VLIWMachineScheduler(MachineSchedContext *C, 96*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MachineSchedStrategy> S) 97*9880d681SAndroid Build Coastguard Worker : ScheduleDAGMILive(C, std::move(S)) {} 98*9880d681SAndroid Build Coastguard Worker 99*9880d681SAndroid Build Coastguard Worker /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's 100*9880d681SAndroid Build Coastguard Worker /// time to do some work. 101*9880d681SAndroid Build Coastguard Worker void schedule() override; 102*9880d681SAndroid Build Coastguard Worker /// Perform platform-specific DAG postprocessing. 103*9880d681SAndroid Build Coastguard Worker void postprocessDAG(); 104*9880d681SAndroid Build Coastguard Worker }; 105*9880d681SAndroid Build Coastguard Worker 106*9880d681SAndroid Build Coastguard Worker /// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics 107*9880d681SAndroid Build Coastguard Worker /// to balance the schedule. 108*9880d681SAndroid Build Coastguard Worker class ConvergingVLIWScheduler : public MachineSchedStrategy { 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Worker /// Store the state used by ConvergingVLIWScheduler heuristics, required 111*9880d681SAndroid Build Coastguard Worker /// for the lifetime of one invocation of pickNode(). 112*9880d681SAndroid Build Coastguard Worker struct SchedCandidate { 113*9880d681SAndroid Build Coastguard Worker // The best SUnit candidate. 114*9880d681SAndroid Build Coastguard Worker SUnit *SU; 115*9880d681SAndroid Build Coastguard Worker 116*9880d681SAndroid Build Coastguard Worker // Register pressure values for the best candidate. 117*9880d681SAndroid Build Coastguard Worker RegPressureDelta RPDelta; 118*9880d681SAndroid Build Coastguard Worker 119*9880d681SAndroid Build Coastguard Worker // Best scheduling cost. 120*9880d681SAndroid Build Coastguard Worker int SCost; 121*9880d681SAndroid Build Coastguard Worker SchedCandidateSchedCandidate122*9880d681SAndroid Build Coastguard Worker SchedCandidate(): SU(nullptr), SCost(0) {} 123*9880d681SAndroid Build Coastguard Worker }; 124*9880d681SAndroid Build Coastguard Worker /// Represent the type of SchedCandidate found within a single queue. 125*9880d681SAndroid Build Coastguard Worker enum CandResult { 126*9880d681SAndroid Build Coastguard Worker NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure, 127*9880d681SAndroid Build Coastguard Worker BestCost}; 128*9880d681SAndroid Build Coastguard Worker 129*9880d681SAndroid Build Coastguard Worker /// Each Scheduling boundary is associated with ready queues. It tracks the 130*9880d681SAndroid Build Coastguard Worker /// current cycle in whichever direction at has moved, and maintains the state 131*9880d681SAndroid Build Coastguard Worker /// of "hazards" and other interlocks at the current cycle. 132*9880d681SAndroid Build Coastguard Worker struct VLIWSchedBoundary { 133*9880d681SAndroid Build Coastguard Worker VLIWMachineScheduler *DAG; 134*9880d681SAndroid Build Coastguard Worker const TargetSchedModel *SchedModel; 135*9880d681SAndroid Build Coastguard Worker 136*9880d681SAndroid Build Coastguard Worker ReadyQueue Available; 137*9880d681SAndroid Build Coastguard Worker ReadyQueue Pending; 138*9880d681SAndroid Build Coastguard Worker bool CheckPending; 139*9880d681SAndroid Build Coastguard Worker 140*9880d681SAndroid Build Coastguard Worker ScheduleHazardRecognizer *HazardRec; 141*9880d681SAndroid Build Coastguard Worker VLIWResourceModel *ResourceModel; 142*9880d681SAndroid Build Coastguard Worker 143*9880d681SAndroid Build Coastguard Worker unsigned CurrCycle; 144*9880d681SAndroid Build Coastguard Worker unsigned IssueCount; 145*9880d681SAndroid Build Coastguard Worker 146*9880d681SAndroid Build Coastguard Worker /// MinReadyCycle - Cycle of the soonest available instruction. 147*9880d681SAndroid Build Coastguard Worker unsigned MinReadyCycle; 148*9880d681SAndroid Build Coastguard Worker 149*9880d681SAndroid Build Coastguard Worker // Remember the greatest min operand latency. 150*9880d681SAndroid Build Coastguard Worker unsigned MaxMinLatency; 151*9880d681SAndroid Build Coastguard Worker 152*9880d681SAndroid Build Coastguard Worker /// Pending queues extend the ready queues with the same ID and the 153*9880d681SAndroid Build Coastguard Worker /// PendingFlag set. VLIWSchedBoundaryVLIWSchedBoundary154*9880d681SAndroid Build Coastguard Worker VLIWSchedBoundary(unsigned ID, const Twine &Name): 155*9880d681SAndroid Build Coastguard Worker DAG(nullptr), SchedModel(nullptr), Available(ID, Name+".A"), 156*9880d681SAndroid Build Coastguard Worker Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"), 157*9880d681SAndroid Build Coastguard Worker CheckPending(false), HazardRec(nullptr), ResourceModel(nullptr), 158*9880d681SAndroid Build Coastguard Worker CurrCycle(0), IssueCount(0), 159*9880d681SAndroid Build Coastguard Worker MinReadyCycle(UINT_MAX), MaxMinLatency(0) {} 160*9880d681SAndroid Build Coastguard Worker ~VLIWSchedBoundaryVLIWSchedBoundary161*9880d681SAndroid Build Coastguard Worker ~VLIWSchedBoundary() { 162*9880d681SAndroid Build Coastguard Worker delete ResourceModel; 163*9880d681SAndroid Build Coastguard Worker delete HazardRec; 164*9880d681SAndroid Build Coastguard Worker } 165*9880d681SAndroid Build Coastguard Worker initVLIWSchedBoundary166*9880d681SAndroid Build Coastguard Worker void init(VLIWMachineScheduler *dag, const TargetSchedModel *smodel) { 167*9880d681SAndroid Build Coastguard Worker DAG = dag; 168*9880d681SAndroid Build Coastguard Worker SchedModel = smodel; 169*9880d681SAndroid Build Coastguard Worker } 170*9880d681SAndroid Build Coastguard Worker isTopVLIWSchedBoundary171*9880d681SAndroid Build Coastguard Worker bool isTop() const { 172*9880d681SAndroid Build Coastguard Worker return Available.getID() == ConvergingVLIWScheduler::TopQID; 173*9880d681SAndroid Build Coastguard Worker } 174*9880d681SAndroid Build Coastguard Worker 175*9880d681SAndroid Build Coastguard Worker bool checkHazard(SUnit *SU); 176*9880d681SAndroid Build Coastguard Worker 177*9880d681SAndroid Build Coastguard Worker void releaseNode(SUnit *SU, unsigned ReadyCycle); 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Worker void bumpCycle(); 180*9880d681SAndroid Build Coastguard Worker 181*9880d681SAndroid Build Coastguard Worker void bumpNode(SUnit *SU); 182*9880d681SAndroid Build Coastguard Worker 183*9880d681SAndroid Build Coastguard Worker void releasePending(); 184*9880d681SAndroid Build Coastguard Worker 185*9880d681SAndroid Build Coastguard Worker void removeReady(SUnit *SU); 186*9880d681SAndroid Build Coastguard Worker 187*9880d681SAndroid Build Coastguard Worker SUnit *pickOnlyChoice(); 188*9880d681SAndroid Build Coastguard Worker }; 189*9880d681SAndroid Build Coastguard Worker 190*9880d681SAndroid Build Coastguard Worker VLIWMachineScheduler *DAG; 191*9880d681SAndroid Build Coastguard Worker const TargetSchedModel *SchedModel; 192*9880d681SAndroid Build Coastguard Worker 193*9880d681SAndroid Build Coastguard Worker // State of the top and bottom scheduled instruction boundaries. 194*9880d681SAndroid Build Coastguard Worker VLIWSchedBoundary Top; 195*9880d681SAndroid Build Coastguard Worker VLIWSchedBoundary Bot; 196*9880d681SAndroid Build Coastguard Worker 197*9880d681SAndroid Build Coastguard Worker public: 198*9880d681SAndroid Build Coastguard Worker /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both) 199*9880d681SAndroid Build Coastguard Worker enum { 200*9880d681SAndroid Build Coastguard Worker TopQID = 1, 201*9880d681SAndroid Build Coastguard Worker BotQID = 2, 202*9880d681SAndroid Build Coastguard Worker LogMaxQID = 2 203*9880d681SAndroid Build Coastguard Worker }; 204*9880d681SAndroid Build Coastguard Worker ConvergingVLIWScheduler()205*9880d681SAndroid Build Coastguard Worker ConvergingVLIWScheduler() 206*9880d681SAndroid Build Coastguard Worker : DAG(nullptr), SchedModel(nullptr), Top(TopQID, "TopQ"), 207*9880d681SAndroid Build Coastguard Worker Bot(BotQID, "BotQ") {} 208*9880d681SAndroid Build Coastguard Worker 209*9880d681SAndroid Build Coastguard Worker void initialize(ScheduleDAGMI *dag) override; 210*9880d681SAndroid Build Coastguard Worker 211*9880d681SAndroid Build Coastguard Worker SUnit *pickNode(bool &IsTopNode) override; 212*9880d681SAndroid Build Coastguard Worker 213*9880d681SAndroid Build Coastguard Worker void schedNode(SUnit *SU, bool IsTopNode) override; 214*9880d681SAndroid Build Coastguard Worker 215*9880d681SAndroid Build Coastguard Worker void releaseTopNode(SUnit *SU) override; 216*9880d681SAndroid Build Coastguard Worker 217*9880d681SAndroid Build Coastguard Worker void releaseBottomNode(SUnit *SU) override; 218*9880d681SAndroid Build Coastguard Worker ReportPackets()219*9880d681SAndroid Build Coastguard Worker unsigned ReportPackets() { 220*9880d681SAndroid Build Coastguard Worker return Top.ResourceModel->getTotalPackets() + 221*9880d681SAndroid Build Coastguard Worker Bot.ResourceModel->getTotalPackets(); 222*9880d681SAndroid Build Coastguard Worker } 223*9880d681SAndroid Build Coastguard Worker 224*9880d681SAndroid Build Coastguard Worker protected: 225*9880d681SAndroid Build Coastguard Worker SUnit *pickNodeBidrectional(bool &IsTopNode); 226*9880d681SAndroid Build Coastguard Worker 227*9880d681SAndroid Build Coastguard Worker int SchedulingCost(ReadyQueue &Q, 228*9880d681SAndroid Build Coastguard Worker SUnit *SU, SchedCandidate &Candidate, 229*9880d681SAndroid Build Coastguard Worker RegPressureDelta &Delta, bool verbose); 230*9880d681SAndroid Build Coastguard Worker 231*9880d681SAndroid Build Coastguard Worker CandResult pickNodeFromQueue(ReadyQueue &Q, 232*9880d681SAndroid Build Coastguard Worker const RegPressureTracker &RPTracker, 233*9880d681SAndroid Build Coastguard Worker SchedCandidate &Candidate); 234*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG 235*9880d681SAndroid Build Coastguard Worker void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU, 236*9880d681SAndroid Build Coastguard Worker PressureChange P = PressureChange()); 237*9880d681SAndroid Build Coastguard Worker #endif 238*9880d681SAndroid Build Coastguard Worker }; 239*9880d681SAndroid Build Coastguard Worker 240*9880d681SAndroid Build Coastguard Worker } // namespace 241*9880d681SAndroid Build Coastguard Worker 242*9880d681SAndroid Build Coastguard Worker 243*9880d681SAndroid Build Coastguard Worker #endif 244