1//==- SystemZMachineScheduler.h - SystemZ Scheduler Interface ----*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// -------------------------- Post RA scheduling ---------------------------- //
10// SystemZPostRASchedStrategy is a scheduling strategy which is plugged into
11// the MachineScheduler. It has a sorted Available set of SUs and a pickNode()
12// implementation that looks to optimize decoder grouping and balance the
13// usage of processor resources. Scheduler states are saved for the end
14// region of each MBB, so that a successor block can learn from it.
15//===----------------------------------------------------------------------===//
16
17#include "SystemZHazardRecognizer.h"
18#include "llvm/CodeGen/MachineScheduler.h"
19#include "llvm/CodeGen/ScheduleDAG.h"
20#include <set>
21
22#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
23#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
24
25using namespace llvm;
26
27namespace llvm {
28
29/// A MachineSchedStrategy implementation for SystemZ post RA scheduling.
30class SystemZPostRASchedStrategy : public MachineSchedStrategy {
31
32  const MachineLoopInfo *MLI;
33  const SystemZInstrInfo *TII;
34
35  // A SchedModel is needed before any DAG is built while advancing past
36  // non-scheduled instructions, so it would not always be possible to call
37  // DAG->getSchedClass(SU).
38  TargetSchedModel SchedModel;
39
40  /// A candidate during instruction evaluation.
41  struct Candidate {
42    SUnit *SU = nullptr;
43
44    /// The decoding cost.
45    int GroupingCost = 0;
46
47    /// The processor resources cost.
48    int ResourcesCost = 0;
49
50    Candidate() = default;
51    Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec);
52
53    // Compare two candidates.
54    bool operator<(const Candidate &other);
55
56    // Check if this node is free of cost ("as good as any").
57    bool noCost() const {
58      return (GroupingCost <= 0 && !ResourcesCost);
59    }
60
61#ifndef NDEBUG
62    void dumpCosts() {
63      if (GroupingCost != 0)
64        dbgs() << "  Grouping cost:" << GroupingCost;
65      if (ResourcesCost != 0)
66        dbgs() << "  Resource cost:" << ResourcesCost;
67    }
68#endif
69  };
70
71  // A sorter for the Available set that makes sure that SUs are considered
72  // in the best order.
73  struct SUSorter {
74    bool operator() (SUnit *lhs, SUnit *rhs) const {
75      if (lhs->isScheduleHigh && !rhs->isScheduleHigh)
76        return true;
77      if (!lhs->isScheduleHigh && rhs->isScheduleHigh)
78        return false;
79
80      if (lhs->getHeight() > rhs->getHeight())
81        return true;
82      else if (lhs->getHeight() < rhs->getHeight())
83        return false;
84
85      return (lhs->NodeNum < rhs->NodeNum);
86    }
87  };
88  // A set of SUs with a sorter and dump method.
89  struct SUSet : std::set<SUnit*, SUSorter> {
90    #ifndef NDEBUG
91    void dump(SystemZHazardRecognizer &HazardRec) const;
92    #endif
93  };
94
95  /// The set of available SUs to schedule next.
96  SUSet Available;
97
98  /// Current MBB
99  MachineBasicBlock *MBB;
100
101  /// Maintain hazard recognizers for all blocks, so that the scheduler state
102  /// can be maintained past BB boundaries when appropariate.
103  typedef std::map<MachineBasicBlock*, SystemZHazardRecognizer*> MBB2HazRec;
104  MBB2HazRec SchedStates;
105
106  /// Pointer to the HazardRecognizer that tracks the scheduler state for
107  /// the current region.
108  SystemZHazardRecognizer *HazardRec;
109
110  /// Update the scheduler state by emitting (non-scheduled) instructions
111  /// up to, but not including, NextBegin.
112  void advanceTo(MachineBasicBlock::iterator NextBegin);
113
114public:
115  SystemZPostRASchedStrategy(const MachineSchedContext *C);
116  virtual ~SystemZPostRASchedStrategy();
117
118  /// Called for a region before scheduling.
119  void initPolicy(MachineBasicBlock::iterator Begin,
120                  MachineBasicBlock::iterator End,
121                  unsigned NumRegionInstrs) override;
122
123  /// PostRA scheduling does not track pressure.
124  bool shouldTrackPressure() const override { return false; }
125
126  // Process scheduling regions top-down so that scheduler states can be
127  // transferrred over scheduling boundaries.
128  bool doMBBSchedRegionsTopDown() const override { return true; }
129
130  void initialize(ScheduleDAGMI *dag) override;
131
132  /// Tell the strategy that MBB is about to be processed.
133  void enterMBB(MachineBasicBlock *NextMBB) override;
134
135  /// Tell the strategy that current MBB is done.
136  void leaveMBB() override;
137
138  /// Pick the next node to schedule, or return NULL.
139  SUnit *pickNode(bool &IsTopNode) override;
140
141  /// ScheduleDAGMI has scheduled an instruction - tell HazardRec
142  /// about it.
143  void schedNode(SUnit *SU, bool IsTopNode) override;
144
145  /// SU has had all predecessor dependencies resolved. Put it into
146  /// Available.
147  void releaseTopNode(SUnit *SU) override;
148
149  /// Currently only scheduling top-down, so this method is empty.
150  void releaseBottomNode(SUnit *SU) override {};
151};
152
153} // end namespace llvm
154
155#endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZMACHINESCHEDULER_H
156