| //==- SystemZMachineScheduler.h - SystemZ Scheduler Interface ----*- C++ -*-==// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // -------------------------- Post RA scheduling ---------------------------- // |
| // SystemZPostRASchedStrategy is a scheduling strategy which is plugged into |
| // the MachineScheduler. It has a sorted Available set of SUs and a pickNode() |
| // implementation that looks to optimize decoder grouping and balance the |
| // usage of processor resources. Scheduler states are saved for the end |
| // region of each MBB, so that a successor block can learn from it. |
| //===----------------------------------------------------------------------===// |
| |
| #include "SystemZHazardRecognizer.h" |
| #include "llvm/CodeGen/MachineScheduler.h" |
| #include "llvm/CodeGen/ScheduleDAG.h" |
| #include <set> |
| |
| #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H |
| #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H |
| |
| using namespace llvm; |
| |
| namespace llvm { |
| |
| /// A MachineSchedStrategy implementation for SystemZ post RA scheduling. |
| class SystemZPostRASchedStrategy : public MachineSchedStrategy { |
| |
| const MachineLoopInfo *MLI; |
| const SystemZInstrInfo *TII; |
| |
| // A SchedModel is needed before any DAG is built while advancing past |
| // non-scheduled instructions, so it would not always be possible to call |
| // DAG->getSchedClass(SU). |
| TargetSchedModel SchedModel; |
| |
| /// A candidate during instruction evaluation. |
| struct Candidate { |
| SUnit *SU = nullptr; |
| |
| /// The decoding cost. |
| int GroupingCost = 0; |
| |
| /// The processor resources cost. |
| int ResourcesCost = 0; |
| |
| Candidate() = default; |
| Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec); |
| |
| // Compare two candidates. |
| bool operator<(const Candidate &other); |
| |
| // Check if this node is free of cost ("as good as any"). |
| bool noCost() const { |
| return (GroupingCost <= 0 && !ResourcesCost); |
| } |
| |
| #ifndef NDEBUG |
| void dumpCosts() { |
| if (GroupingCost != 0) |
| dbgs() << " Grouping cost:" << GroupingCost; |
| if (ResourcesCost != 0) |
| dbgs() << " Resource cost:" << ResourcesCost; |
| } |
| #endif |
| }; |
| |
| // A sorter for the Available set that makes sure that SUs are considered |
| // in the best order. |
| struct SUSorter { |
| bool operator() (SUnit *lhs, SUnit *rhs) const { |
| if (lhs->isScheduleHigh && !rhs->isScheduleHigh) |
| return true; |
| if (!lhs->isScheduleHigh && rhs->isScheduleHigh) |
| return false; |
| |
| if (lhs->getHeight() > rhs->getHeight()) |
| return true; |
| else if (lhs->getHeight() < rhs->getHeight()) |
| return false; |
| |
| return (lhs->NodeNum < rhs->NodeNum); |
| } |
| }; |
| // A set of SUs with a sorter and dump method. |
| struct SUSet : std::set<SUnit*, SUSorter> { |
| #ifndef NDEBUG |
| void dump(SystemZHazardRecognizer &HazardRec) const; |
| #endif |
| }; |
| |
| /// The set of available SUs to schedule next. |
| SUSet Available; |
| |
| /// Current MBB |
| MachineBasicBlock *MBB; |
| |
| /// Maintain hazard recognizers for all blocks, so that the scheduler state |
| /// can be maintained past BB boundaries when appropariate. |
| typedef std::map<MachineBasicBlock*, SystemZHazardRecognizer*> MBB2HazRec; |
| MBB2HazRec SchedStates; |
| |
| /// Pointer to the HazardRecognizer that tracks the scheduler state for |
| /// the current region. |
| SystemZHazardRecognizer *HazardRec; |
| |
| /// Update the scheduler state by emitting (non-scheduled) instructions |
| /// up to, but not including, NextBegin. |
| void advanceTo(MachineBasicBlock::iterator NextBegin); |
| |
| public: |
| SystemZPostRASchedStrategy(const MachineSchedContext *C); |
| virtual ~SystemZPostRASchedStrategy(); |
| |
| /// Called for a region before scheduling. |
| void initPolicy(MachineBasicBlock::iterator Begin, |
| MachineBasicBlock::iterator End, |
| unsigned NumRegionInstrs) override; |
| |
| /// PostRA scheduling does not track pressure. |
| bool shouldTrackPressure() const override { return false; } |
| |
| // Process scheduling regions top-down so that scheduler states can be |
| // transferrred over scheduling boundaries. |
| bool doMBBSchedRegionsTopDown() const override { return true; } |
| |
| void initialize(ScheduleDAGMI *dag) override; |
| |
| /// Tell the strategy that MBB is about to be processed. |
| void enterMBB(MachineBasicBlock *NextMBB) override; |
| |
| /// Tell the strategy that current MBB is done. |
| void leaveMBB() override; |
| |
| /// Pick the next node to schedule, or return NULL. |
| SUnit *pickNode(bool &IsTopNode) override; |
| |
| /// ScheduleDAGMI has scheduled an instruction - tell HazardRec |
| /// about it. |
| void schedNode(SUnit *SU, bool IsTopNode) override; |
| |
| /// SU has had all predecessor dependencies resolved. Put it into |
| /// Available. |
| void releaseTopNode(SUnit *SU) override; |
| |
| /// Currently only scheduling top-down, so this method is empty. |
| void releaseBottomNode(SUnit *SU) override {}; |
| }; |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H |