13943d2b0SEugene Zelenko //==- SystemZMachineScheduler.h - SystemZ Scheduler Interface ----*- C++ -*-==//
28010b631SJonas Paulsson //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68010b631SJonas Paulsson //
78010b631SJonas Paulsson //===----------------------------------------------------------------------===//
88010b631SJonas Paulsson //
98010b631SJonas Paulsson // -------------------------- Post RA scheduling ---------------------------- //
108010b631SJonas Paulsson // SystemZPostRASchedStrategy is a scheduling strategy which is plugged into
118010b631SJonas Paulsson // the MachineScheduler. It has a sorted Available set of SUs and a pickNode()
128010b631SJonas Paulsson // implementation that looks to optimize decoder grouping and balance the
1357a705d9SJonas Paulsson // usage of processor resources. Scheduler states are saved for the end
1457a705d9SJonas Paulsson // region of each MBB, so that a successor block can learn from it.
158010b631SJonas Paulsson //===----------------------------------------------------------------------===//
168010b631SJonas Paulsson 
178010b631SJonas Paulsson #include "SystemZHazardRecognizer.h"
188010b631SJonas Paulsson #include "llvm/CodeGen/MachineScheduler.h"
193943d2b0SEugene Zelenko #include "llvm/CodeGen/ScheduleDAG.h"
203943d2b0SEugene Zelenko #include <set>
218010b631SJonas Paulsson 
228010b631SJonas Paulsson #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
238010b631SJonas Paulsson #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
248010b631SJonas Paulsson 
258010b631SJonas Paulsson using namespace llvm;
268010b631SJonas Paulsson 
278010b631SJonas Paulsson namespace llvm {
288010b631SJonas Paulsson 
298010b631SJonas Paulsson /// A MachineSchedStrategy implementation for SystemZ post RA scheduling.
308010b631SJonas Paulsson class SystemZPostRASchedStrategy : public MachineSchedStrategy {
3157a705d9SJonas Paulsson 
3257a705d9SJonas Paulsson   const MachineLoopInfo *MLI;
3357a705d9SJonas Paulsson   const SystemZInstrInfo *TII;
3457a705d9SJonas Paulsson 
3557a705d9SJonas Paulsson   // A SchedModel is needed before any DAG is built while advancing past
3657a705d9SJonas Paulsson   // non-scheduled instructions, so it would not always be possible to call
3757a705d9SJonas Paulsson   // DAG->getSchedClass(SU).
3857a705d9SJonas Paulsson   TargetSchedModel SchedModel;
398010b631SJonas Paulsson 
408010b631SJonas Paulsson   /// A candidate during instruction evaluation.
418010b631SJonas Paulsson   struct Candidate {
423943d2b0SEugene Zelenko     SUnit *SU = nullptr;
438010b631SJonas Paulsson 
448010b631SJonas Paulsson     /// The decoding cost.
453943d2b0SEugene Zelenko     int GroupingCost = 0;
468010b631SJonas Paulsson 
478010b631SJonas Paulsson     /// The processor resources cost.
483943d2b0SEugene Zelenko     int ResourcesCost = 0;
498010b631SJonas Paulsson 
503943d2b0SEugene Zelenko     Candidate() = default;
518010b631SJonas Paulsson     Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec);
528010b631SJonas Paulsson 
538010b631SJonas Paulsson     // Compare two candidates.
548010b631SJonas Paulsson     bool operator<(const Candidate &other);
558010b631SJonas Paulsson 
568010b631SJonas Paulsson     // Check if this node is free of cost ("as good as any").
noCostCandidate573943d2b0SEugene Zelenko     bool noCost() const {
588010b631SJonas Paulsson       return (GroupingCost <= 0 && !ResourcesCost);
598010b631SJonas Paulsson     }
6061fbcf58SJonas Paulsson 
6161fbcf58SJonas Paulsson #ifndef NDEBUG
dumpCostsCandidate6261fbcf58SJonas Paulsson     void dumpCosts() {
6361fbcf58SJonas Paulsson       if (GroupingCost != 0)
6461fbcf58SJonas Paulsson         dbgs() << "  Grouping cost:" << GroupingCost;
6561fbcf58SJonas Paulsson       if (ResourcesCost != 0)
6661fbcf58SJonas Paulsson         dbgs() << "  Resource cost:" << ResourcesCost;
6761fbcf58SJonas Paulsson     }
6861fbcf58SJonas Paulsson #endif
698010b631SJonas Paulsson   };
708010b631SJonas Paulsson 
718010b631SJonas Paulsson   // A sorter for the Available set that makes sure that SUs are considered
728010b631SJonas Paulsson   // in the best order.
738010b631SJonas Paulsson   struct SUSorter {
operatorSUSorter748010b631SJonas Paulsson     bool operator() (SUnit *lhs, SUnit *rhs) const {
758010b631SJonas Paulsson       if (lhs->isScheduleHigh && !rhs->isScheduleHigh)
768010b631SJonas Paulsson         return true;
778010b631SJonas Paulsson       if (!lhs->isScheduleHigh && rhs->isScheduleHigh)
788010b631SJonas Paulsson         return false;
798010b631SJonas Paulsson 
808010b631SJonas Paulsson       if (lhs->getHeight() > rhs->getHeight())
818010b631SJonas Paulsson         return true;
828010b631SJonas Paulsson       else if (lhs->getHeight() < rhs->getHeight())
838010b631SJonas Paulsson         return false;
848010b631SJonas Paulsson 
858010b631SJonas Paulsson       return (lhs->NodeNum < rhs->NodeNum);
868010b631SJonas Paulsson     }
878010b631SJonas Paulsson   };
888010b631SJonas Paulsson   // A set of SUs with a sorter and dump method.
898010b631SJonas Paulsson   struct SUSet : std::set<SUnit*, SUSorter> {
908010b631SJonas Paulsson     #ifndef NDEBUG
91705f798bSSam Clegg     void dump(SystemZHazardRecognizer &HazardRec) const;
928010b631SJonas Paulsson     #endif
938010b631SJonas Paulsson   };
948010b631SJonas Paulsson 
958010b631SJonas Paulsson   /// The set of available SUs to schedule next.
968010b631SJonas Paulsson   SUSet Available;
978010b631SJonas Paulsson 
9857a705d9SJonas Paulsson   /// Current MBB
9957a705d9SJonas Paulsson   MachineBasicBlock *MBB;
10057a705d9SJonas Paulsson 
10157a705d9SJonas Paulsson   /// Maintain hazard recognizers for all blocks, so that the scheduler state
10257a705d9SJonas Paulsson   /// can be maintained past BB boundaries when appropariate.
10357a705d9SJonas Paulsson   typedef std::map<MachineBasicBlock*, SystemZHazardRecognizer*> MBB2HazRec;
10457a705d9SJonas Paulsson   MBB2HazRec SchedStates;
10557a705d9SJonas Paulsson 
10657a705d9SJonas Paulsson   /// Pointer to the HazardRecognizer that tracks the scheduler state for
10757a705d9SJonas Paulsson   /// the current region.
10857a705d9SJonas Paulsson   SystemZHazardRecognizer *HazardRec;
10957a705d9SJonas Paulsson 
11057a705d9SJonas Paulsson   /// Update the scheduler state by emitting (non-scheduled) instructions
11157a705d9SJonas Paulsson   /// up to, but not including, NextBegin.
11257a705d9SJonas Paulsson   void advanceTo(MachineBasicBlock::iterator NextBegin);
1138010b631SJonas Paulsson 
1148010b631SJonas Paulsson public:
1158010b631SJonas Paulsson   SystemZPostRASchedStrategy(const MachineSchedContext *C);
11657a705d9SJonas Paulsson   virtual ~SystemZPostRASchedStrategy();
11757a705d9SJonas Paulsson 
11857a705d9SJonas Paulsson   /// Called for a region before scheduling.
11957a705d9SJonas Paulsson   void initPolicy(MachineBasicBlock::iterator Begin,
12057a705d9SJonas Paulsson                   MachineBasicBlock::iterator End,
12157a705d9SJonas Paulsson                   unsigned NumRegionInstrs) override;
1228010b631SJonas Paulsson 
1238010b631SJonas Paulsson   /// PostRA scheduling does not track pressure.
shouldTrackPressure()1248010b631SJonas Paulsson   bool shouldTrackPressure() const override { return false; }
1258010b631SJonas Paulsson 
12657a705d9SJonas Paulsson   // Process scheduling regions top-down so that scheduler states can be
12757a705d9SJonas Paulsson   // transferrred over scheduling boundaries.
doMBBSchedRegionsTopDown()12857a705d9SJonas Paulsson   bool doMBBSchedRegionsTopDown() const override { return true; }
12957a705d9SJonas Paulsson 
13061fbcf58SJonas Paulsson   void initialize(ScheduleDAGMI *dag) override;
13157a705d9SJonas Paulsson 
13257a705d9SJonas Paulsson   /// Tell the strategy that MBB is about to be processed.
13357a705d9SJonas Paulsson   void enterMBB(MachineBasicBlock *NextMBB) override;
13457a705d9SJonas Paulsson 
13557a705d9SJonas Paulsson   /// Tell the strategy that current MBB is done.
13657a705d9SJonas Paulsson   void leaveMBB() override;
1378010b631SJonas Paulsson 
1388010b631SJonas Paulsson   /// Pick the next node to schedule, or return NULL.
1398010b631SJonas Paulsson   SUnit *pickNode(bool &IsTopNode) override;
1408010b631SJonas Paulsson 
1418010b631SJonas Paulsson   /// ScheduleDAGMI has scheduled an instruction - tell HazardRec
1428010b631SJonas Paulsson   /// about it.
1438010b631SJonas Paulsson   void schedNode(SUnit *SU, bool IsTopNode) override;
1448010b631SJonas Paulsson 
1458010b631SJonas Paulsson   /// SU has had all predecessor dependencies resolved. Put it into
1468010b631SJonas Paulsson   /// Available.
1478010b631SJonas Paulsson   void releaseTopNode(SUnit *SU) override;
1488010b631SJonas Paulsson 
1498010b631SJonas Paulsson   /// Currently only scheduling top-down, so this method is empty.
releaseBottomNode(SUnit * SU)1508010b631SJonas Paulsson   void releaseBottomNode(SUnit *SU) override {};
1518010b631SJonas Paulsson };
1528010b631SJonas Paulsson 
1533943d2b0SEugene Zelenko } // end namespace llvm
1548010b631SJonas Paulsson 
1553943d2b0SEugene Zelenko #endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
156