10b57cec5SDimitry Andric //==- SystemZMachineScheduler.h - SystemZ Scheduler Interface ----*- C++ -*-==// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // -------------------------- Post RA scheduling ---------------------------- // 100b57cec5SDimitry Andric // SystemZPostRASchedStrategy is a scheduling strategy which is plugged into 110b57cec5SDimitry Andric // the MachineScheduler. It has a sorted Available set of SUs and a pickNode() 120b57cec5SDimitry Andric // implementation that looks to optimize decoder grouping and balance the 130b57cec5SDimitry Andric // usage of processor resources. Scheduler states are saved for the end 140b57cec5SDimitry Andric // region of each MBB, so that a successor block can learn from it. 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 17*06c3fb27SDimitry Andric #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H 18*06c3fb27SDimitry Andric #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H 19*06c3fb27SDimitry Andric 200b57cec5SDimitry Andric #include "SystemZHazardRecognizer.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 230b57cec5SDimitry Andric #include <set> 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric namespace llvm { 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric /// A MachineSchedStrategy implementation for SystemZ post RA scheduling. 300b57cec5SDimitry Andric class SystemZPostRASchedStrategy : public MachineSchedStrategy { 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric const MachineLoopInfo *MLI; 330b57cec5SDimitry Andric const SystemZInstrInfo *TII; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric // A SchedModel is needed before any DAG is built while advancing past 360b57cec5SDimitry Andric // non-scheduled instructions, so it would not always be possible to call 370b57cec5SDimitry Andric // DAG->getSchedClass(SU). 380b57cec5SDimitry Andric TargetSchedModel SchedModel; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric /// A candidate during instruction evaluation. 410b57cec5SDimitry Andric struct Candidate { 420b57cec5SDimitry Andric SUnit *SU = nullptr; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric /// The decoding cost. 450b57cec5SDimitry Andric int GroupingCost = 0; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric /// The processor resources cost. 480b57cec5SDimitry Andric int ResourcesCost = 0; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric Candidate() = default; 510b57cec5SDimitry Andric Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric // Compare two candidates. 540b57cec5SDimitry Andric bool operator<(const Candidate &other); 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric // Check if this node is free of cost ("as good as any"). noCostCandidate570b57cec5SDimitry Andric bool noCost() const { 580b57cec5SDimitry Andric return (GroupingCost <= 0 && !ResourcesCost); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric #ifndef NDEBUG dumpCostsCandidate620b57cec5SDimitry Andric void dumpCosts() { 630b57cec5SDimitry Andric if (GroupingCost != 0) 640b57cec5SDimitry Andric dbgs() << " Grouping cost:" << GroupingCost; 650b57cec5SDimitry Andric if (ResourcesCost != 0) 660b57cec5SDimitry Andric dbgs() << " Resource cost:" << ResourcesCost; 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric #endif 690b57cec5SDimitry Andric }; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric // A sorter for the Available set that makes sure that SUs are considered 720b57cec5SDimitry Andric // in the best order. 730b57cec5SDimitry Andric struct SUSorter { operatorSUSorter740b57cec5SDimitry Andric bool operator() (SUnit *lhs, SUnit *rhs) const { 750b57cec5SDimitry Andric if (lhs->isScheduleHigh && !rhs->isScheduleHigh) 760b57cec5SDimitry Andric return true; 770b57cec5SDimitry Andric if (!lhs->isScheduleHigh && rhs->isScheduleHigh) 780b57cec5SDimitry Andric return false; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric if (lhs->getHeight() > rhs->getHeight()) 810b57cec5SDimitry Andric return true; 820b57cec5SDimitry Andric else if (lhs->getHeight() < rhs->getHeight()) 830b57cec5SDimitry Andric return false; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric return (lhs->NodeNum < rhs->NodeNum); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric }; 880b57cec5SDimitry Andric // A set of SUs with a sorter and dump method. 890b57cec5SDimitry Andric struct SUSet : std::set<SUnit*, SUSorter> { 900b57cec5SDimitry Andric #ifndef NDEBUG 910b57cec5SDimitry Andric void dump(SystemZHazardRecognizer &HazardRec) const; 920b57cec5SDimitry Andric #endif 930b57cec5SDimitry Andric }; 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric /// The set of available SUs to schedule next. 960b57cec5SDimitry Andric SUSet Available; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric /// Current MBB 990b57cec5SDimitry Andric MachineBasicBlock *MBB; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric /// Maintain hazard recognizers for all blocks, so that the scheduler state 1020b57cec5SDimitry Andric /// can be maintained past BB boundaries when appropariate. 1030b57cec5SDimitry Andric typedef std::map<MachineBasicBlock*, SystemZHazardRecognizer*> MBB2HazRec; 1040b57cec5SDimitry Andric MBB2HazRec SchedStates; 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric /// Pointer to the HazardRecognizer that tracks the scheduler state for 1070b57cec5SDimitry Andric /// the current region. 1080b57cec5SDimitry Andric SystemZHazardRecognizer *HazardRec; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric /// Update the scheduler state by emitting (non-scheduled) instructions 1110b57cec5SDimitry Andric /// up to, but not including, NextBegin. 1120b57cec5SDimitry Andric void advanceTo(MachineBasicBlock::iterator NextBegin); 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric public: 1150b57cec5SDimitry Andric SystemZPostRASchedStrategy(const MachineSchedContext *C); 1160b57cec5SDimitry Andric virtual ~SystemZPostRASchedStrategy(); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric /// Called for a region before scheduling. 1190b57cec5SDimitry Andric void initPolicy(MachineBasicBlock::iterator Begin, 1200b57cec5SDimitry Andric MachineBasicBlock::iterator End, 1210b57cec5SDimitry Andric unsigned NumRegionInstrs) override; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric /// PostRA scheduling does not track pressure. shouldTrackPressure()1240b57cec5SDimitry Andric bool shouldTrackPressure() const override { return false; } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric // Process scheduling regions top-down so that scheduler states can be 1270b57cec5SDimitry Andric // transferrred over scheduling boundaries. doMBBSchedRegionsTopDown()1280b57cec5SDimitry Andric bool doMBBSchedRegionsTopDown() const override { return true; } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric void initialize(ScheduleDAGMI *dag) override; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric /// Tell the strategy that MBB is about to be processed. 1330b57cec5SDimitry Andric void enterMBB(MachineBasicBlock *NextMBB) override; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric /// Tell the strategy that current MBB is done. 1360b57cec5SDimitry Andric void leaveMBB() override; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric /// Pick the next node to schedule, or return NULL. 1390b57cec5SDimitry Andric SUnit *pickNode(bool &IsTopNode) override; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric /// ScheduleDAGMI has scheduled an instruction - tell HazardRec 1420b57cec5SDimitry Andric /// about it. 1430b57cec5SDimitry Andric void schedNode(SUnit *SU, bool IsTopNode) override; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric /// SU has had all predecessor dependencies resolved. Put it into 1460b57cec5SDimitry Andric /// Available. 1470b57cec5SDimitry Andric void releaseTopNode(SUnit *SU) override; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric /// Currently only scheduling top-down, so this method is empty. releaseBottomNode(SUnit * SU)1500b57cec5SDimitry Andric void releaseBottomNode(SUnit *SU) override {}; 1510b57cec5SDimitry Andric }; 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric } // end namespace llvm 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H 156