xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZMachineScheduler.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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