blob: 61bbf3fcf3643a6aedcd2a1ffbfba994081c6687 [file] [log] [blame]
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +00001//===--------------------- Scheduler.h ------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10///
11/// A scheduler for Processor Resource Units and Processor Resource Groups.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_TOOLS_LLVM_MCA_SCHEDULER_H
16#define LLVM_TOOLS_LLVM_MCA_SCHEDULER_H
17
Matt Davis271ce762018-08-27 17:16:32 +000018#include "HardwareUnits/HardwareUnit.h"
19#include "HardwareUnits/LSUnit.h"
Matt Davis673412e2018-08-24 22:59:13 +000020#include "ResourceManager.h"
Matt Davis488ac4c2018-06-14 01:20:18 +000021#include "llvm/ADT/SmallVector.h"
Matt Davis673412e2018-08-24 22:59:13 +000022#include "llvm/MC/MCSchedule.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000023
24namespace mca {
25
Andrea Di Biagiof3374f02018-08-21 18:20:16 +000026class SchedulerStrategy {
27public:
28 SchedulerStrategy() = default;
29 virtual ~SchedulerStrategy();
30
31 /// Returns true if Lhs should take priority over Rhs.
32 ///
33 /// This method is used by class Scheduler to select the "best" ready
34 /// instruction to issue to the underlying pipelines.
35 virtual bool compare(const InstRef &Lhs, const InstRef &Rhs) const = 0;
36};
37
38/// Default instruction selection strategy used by class Scheduler.
39class DefaultSchedulerStrategy : public SchedulerStrategy {
40 /// This method ranks instructions based on their age, and the number of known
41 /// users. The lower the rank value, the better.
42 int computeRank(const InstRef &Lhs) const {
43 return Lhs.getSourceIndex() - Lhs.getInstruction()->getNumUsers();
44 }
45
46public:
47 DefaultSchedulerStrategy() = default;
48 virtual ~DefaultSchedulerStrategy();
49
50 bool compare(const InstRef &Lhs, const InstRef &Rhs) const override {
51 int LhsRank = computeRank(Lhs);
52 int RhsRank = computeRank(Rhs);
53
54 /// Prioritize older instructions over younger instructions to minimize the
55 /// pressure on the reorder buffer.
56 if (LhsRank == RhsRank)
57 return Lhs.getSourceIndex() < Rhs.getSourceIndex();
58 return LhsRank < RhsRank;
59 }
60};
61
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000062/// Class Scheduler is responsible for issuing instructions to pipeline
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +000063/// resources.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000064///
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +000065/// Internally, it delegates to a ResourceManager the management of processor
66/// resources. This class is also responsible for tracking the progress of
67/// instructions from the dispatch stage, until the write-back stage.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000068///
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +000069/// An instruction dispatched to the Scheduler is initially placed into either
70/// the 'WaitSet' or the 'ReadySet' depending on the availability of the input
71/// operands.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000072///
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +000073/// An instruction is moved from the WaitSet to the ReadySet when register
74/// operands become available, and all memory dependencies are met.
75/// Instructions that are moved from the WaitSet to the ReadySet transition
76/// in state from 'IS_AVAILABLE' to 'IS_READY'.
77///
78/// On every cycle, the Scheduler checks if it can promote instructions from the
79/// WaitSet to the ReadySet.
80///
81/// An Instruction is moved from the ReadySet the `IssuedSet` when it is issued
82/// to a (one or more) pipeline(s). This event also causes an instruction state
83/// transition (i.e. from state IS_READY, to state IS_EXECUTING). An Instruction
84/// leaves the IssuedSet when it reaches the write-back stage.
Matt Davis362ea5f2018-07-06 18:03:14 +000085class Scheduler : public HardwareUnit {
Andrea Di Biagio0875e752018-08-20 14:41:36 +000086 LSUnit *LSU;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000087
Andrea Di Biagiof3374f02018-08-21 18:20:16 +000088 // Instruction selection strategy for this Scheduler.
89 std::unique_ptr<SchedulerStrategy> Strategy;
90
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000091 // Hardware resources that are managed by this scheduler.
92 std::unique_ptr<ResourceManager> Resources;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000093
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +000094 std::vector<InstRef> WaitSet;
95 std::vector<InstRef> ReadySet;
96 std::vector<InstRef> IssuedSet;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000097
Matt Davis0f70bc02018-08-23 18:42:37 +000098 /// Verify the given selection strategy and set the Strategy member
99 /// accordingly. If no strategy is provided, the DefaultSchedulerStrategy is
100 /// used.
101 void initializeStrategy(std::unique_ptr<SchedulerStrategy> S);
102
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000103 /// Issue an instruction without updating the ready queue.
Andrea Di Biagio27c4b092018-04-24 14:53:16 +0000104 void issueInstructionImpl(
Matt Davis21a8d322018-05-07 18:29:15 +0000105 InstRef &IR,
Andrea Di Biagio27c4b092018-04-24 14:53:16 +0000106 llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
107
Andrea Di Biagio51849952018-08-21 12:40:15 +0000108 // Identify instructions that have finished executing, and remove them from
109 // the IssuedSet. References to executed instructions are added to input
110 // vector 'Executed'.
111 void updateIssuedSet(llvm::SmallVectorImpl<InstRef> &Executed);
112
113 // Try to promote instructions from WaitSet to ReadySet.
114 // Add promoted instructions to the 'Ready' vector in input.
115 void promoteToReadySet(llvm::SmallVectorImpl<InstRef> &Ready);
116
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000117public:
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000118 Scheduler(const llvm::MCSchedModel &Model, LSUnit *Lsu)
Matt Davis0f70bc02018-08-23 18:42:37 +0000119 : LSU(Lsu), Resources(llvm::make_unique<ResourceManager>(Model)) {
120 initializeStrategy(nullptr);
121 }
Andrea Di Biagiof3374f02018-08-21 18:20:16 +0000122 Scheduler(const llvm::MCSchedModel &Model, LSUnit *Lsu,
123 std::unique_ptr<SchedulerStrategy> SelectStrategy)
Matt Davis0f70bc02018-08-23 18:42:37 +0000124 : LSU(Lsu), Resources(llvm::make_unique<ResourceManager>(Model)) {
125 initializeStrategy(std::move(SelectStrategy));
126 }
Andrea Di Biagiof3374f02018-08-21 18:20:16 +0000127 Scheduler(std::unique_ptr<ResourceManager> RM, LSUnit *Lsu,
128 std::unique_ptr<SchedulerStrategy> SelectStrategy)
Matt Davis0f70bc02018-08-23 18:42:37 +0000129 : LSU(Lsu), Resources(std::move(RM)) {
130 initializeStrategy(std::move(SelectStrategy));
131 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000132
Andrea Di Biagio163419f2018-08-17 15:01:37 +0000133 // Stalls generated by the scheduler.
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000134 enum Status {
135 SC_AVAILABLE,
136 SC_LOAD_QUEUE_FULL,
137 SC_STORE_QUEUE_FULL,
138 SC_BUFFERS_FULL,
139 SC_DISPATCH_GROUP_STALL,
Andrea Di Biagio163419f2018-08-17 15:01:37 +0000140 };
141
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000142 /// Check if the instruction in 'IR' can be dispatched and returns an answer
143 /// in the form of a Status value.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000144 ///
Matt Davis679083e2018-05-17 19:22:29 +0000145 /// The DispatchStage is responsible for querying the Scheduler before
Matt Davis488ac4c2018-06-14 01:20:18 +0000146 /// dispatching new instructions. This routine is used for performing such
147 /// a query. If the instruction 'IR' can be dispatched, then true is
148 /// returned, otherwise false is returned with Event set to the stall type.
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000149 /// Internally, it also checks if the load/store unit is available.
150 Status isAvailable(const InstRef &IR) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000151
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000152 /// Reserves buffer and LSUnit queue resources that are necessary to issue
153 /// this instruction.
154 ///
155 /// Returns true if instruction IR is ready to be issued to the underlying
156 /// pipelines. Note that this operation cannot fail; it assumes that a
157 /// previous call to method `isAvailable(IR)` returned `SC_AVAILABLE`.
158 void dispatch(const InstRef &IR);
159
160 /// Returns true if IR is ready to be executed by the underlying pipelines.
161 /// This method assumes that IR has been previously dispatched.
162 bool isReady(const InstRef &IR) const;
Matt Davis488ac4c2018-06-14 01:20:18 +0000163
Andrea Di Biagio51849952018-08-21 12:40:15 +0000164 /// Issue an instruction and populates a vector of used pipeline resources,
165 /// and a vector of instructions that transitioned to the ready state as a
166 /// result of this event.
Andrea Di Biagio4660fd22018-08-22 10:23:28 +0000167 void
168 issueInstruction(InstRef &IR,
Andrea Di Biagio51849952018-08-21 12:40:15 +0000169 llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Used,
170 llvm::SmallVectorImpl<InstRef> &Ready);
Matt Davis488ac4c2018-06-14 01:20:18 +0000171
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000172 /// Returns true if IR has to be issued immediately, or if IR is a zero
173 /// latency instruction.
174 bool mustIssueImmediately(const InstRef &IR) const;
Andrea Di Biagio27c4b092018-04-24 14:53:16 +0000175
Andrea Di Biagio51849952018-08-21 12:40:15 +0000176 /// This routine notifies the Scheduler that a new cycle just started.
177 ///
178 /// It notifies the underlying ResourceManager that a new cycle just started.
179 /// Vector `Freed` is populated with resourceRef related to resources that
180 /// have changed in state, and that are now available to new instructions.
181 /// Instructions executed are added to vector Executed, while vector Ready is
182 /// populated with instructions that have become ready in this new cycle.
183 void cycleEvent(llvm::SmallVectorImpl<ResourceRef> &Freed,
184 llvm::SmallVectorImpl<InstRef> &Ready,
185 llvm::SmallVectorImpl<InstRef> &Executed);
Matt Davis488ac4c2018-06-14 01:20:18 +0000186
Andrea Di Biagio51849952018-08-21 12:40:15 +0000187 /// Convert a resource mask into a valid llvm processor resource identifier.
188 unsigned getResourceID(uint64_t Mask) const {
Matt Davis488ac4c2018-06-14 01:20:18 +0000189 return Resources->resolveResourceMask(Mask);
190 }
191
Andrea Di Biagiof3374f02018-08-21 18:20:16 +0000192 /// Select the next instruction to issue from the ReadySet. Returns an invalid
193 /// instruction reference if there are no ready instructions, or if processor
194 /// resources are not available.
Matt Davis488ac4c2018-06-14 01:20:18 +0000195 InstRef select();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000196
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000197#ifndef NDEBUG
Matt Davis488ac4c2018-06-14 01:20:18 +0000198 // Update the ready queues.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000199 void dump() const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000200
Matt Davis488ac4c2018-06-14 01:20:18 +0000201 // This routine performs a sanity check. This routine should only be called
202 // when we know that 'IR' is not in the scheduler's instruction queues.
203 void sanityCheck(const InstRef &IR) const {
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +0000204 assert(llvm::find(WaitSet, IR) == WaitSet.end());
205 assert(llvm::find(ReadySet, IR) == ReadySet.end());
206 assert(llvm::find(IssuedSet, IR) == IssuedSet.end());
Matt Davis488ac4c2018-06-14 01:20:18 +0000207 }
208#endif // !NDEBUG
209};
210} // namespace mca
211
212#endif // LLVM_TOOLS_LLVM_MCA_SCHEDULER_H