blob: 341c66ea2cedec657dfcceb002e293e454b002b5 [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 Davis362ea5f2018-07-06 18:03:14 +000018#include "HardwareUnit.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000019#include "Instruction.h"
20#include "LSUnit.h"
Matt Davis488ac4c2018-06-14 01:20:18 +000021#include "llvm/ADT/ArrayRef.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000022#include "llvm/ADT/DenseMap.h"
Matt Davis488ac4c2018-06-14 01:20:18 +000023#include "llvm/ADT/SmallVector.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000024#include "llvm/MC/MCSubtargetInfo.h"
25#include <map>
26
27namespace mca {
28
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000029/// Used to notify the internal state of a processor resource.
30///
31/// A processor resource is available if it is not reserved, and there are
32/// available slots in the buffer. A processor resource is unavailable if it
33/// is either reserved, or the associated buffer is full. A processor resource
34/// with a buffer size of -1 is always available if it is not reserved.
35///
36/// Values of type ResourceStateEvent are returned by method
37/// ResourceState::isBufferAvailable(), which is used to query the internal
38/// state of a resource.
39///
40/// The naming convention for resource state events is:
41/// * Event names start with prefix RS_
42/// * Prefix RS_ is followed by a string describing the actual resource state.
43enum ResourceStateEvent {
44 RS_BUFFER_AVAILABLE,
45 RS_BUFFER_UNAVAILABLE,
46 RS_RESERVED
47};
48
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000049/// A descriptor for processor resources.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000050///
51/// Each object of class ResourceState is associated to a specific processor
52/// resource. There is an instance of this class for every processor resource
53/// defined by the scheduling model.
54/// A ResourceState dynamically tracks the availability of units of a processor
55/// resource. For example, the ResourceState of a ProcResGroup tracks the
56/// availability of resource units which are part of the group.
57///
58/// Internally, ResourceState uses a round-robin selector to identify
59/// which unit of the group shall be used next.
60class ResourceState {
Andrea Di Biagio0c541292018-03-10 16:55:07 +000061 // Index to the MCProcResourceDesc in the processor Model.
62 unsigned ProcResourceDescIndex;
Andrea Di Biagio4704f032018-03-20 12:25:54 +000063 // A resource mask. This is generated by the tool with the help of
64 // function `mca::createProcResourceMasks' (see Support.h).
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000065 uint64_t ResourceMask;
66
67 // A ProcResource can specify a number of units. For the purpose of dynamic
68 // scheduling, a processor resource with more than one unit behaves like a
69 // group. This field has one bit set for every unit/resource that is part of
70 // the group.
71 // For groups, this field defaults to 'ResourceMask'. For non-group
72 // resources, the number of bits set in this mask is equivalent to the
73 // number of units (i.e. field 'NumUnits' in 'ProcResourceUnits').
74 uint64_t ResourceSizeMask;
75
76 // A simple round-robin selector for processor resources.
77 // Each bit of the mask identifies a sub resource within this group.
78 //
79 // As an example, lets assume that this ResourceState describes a
80 // processor resource group composed of the following three units:
81 // ResourceA -- 0b001
82 // ResourceB -- 0b010
83 // ResourceC -- 0b100
84 //
85 // Each unit is identified by a ResourceMask which always contains a
86 // single bit set. Field NextInSequenceMask is initially set to value
87 // 0xb111. That value is obtained by OR'ing the resource masks of
88 // processor resource that are part of the group.
89 //
90 // NextInSequenceMask -- 0b111
91 //
92 // Field NextInSequenceMask is used by the resource manager (i.e.
93 // an object of class ResourceManager) to select the "next available resource"
94 // from the set. The algorithm would prioritize resources with a bigger
95 // ResourceMask value.
96 //
97 // In this example, there are three resources in the set, and 'ResourceC'
98 // has the highest mask value. The round-robin selector would firstly select
99 // 'ResourceC', then 'ResourceB', and eventually 'ResourceA'.
100 //
101 // When a resource R is used, its corresponding bit is cleared from the set.
102 //
103 // Back to the example:
104 // If 'ResourceC' is selected, then the new value of NextInSequenceMask
105 // becomes 0xb011.
106 //
107 // When NextInSequenceMask becomes zero, it is reset to its original value
108 // (in this example, that value would be 0b111).
109 uint64_t NextInSequenceMask;
110
111 // Some instructions can only be issued on very specific pipeline resources.
112 // For those instructions, we know exactly which resource would be consumed
113 // without having to dynamically select it using field 'NextInSequenceMask'.
114 //
115 // The resource mask bit associated to the (statically) selected
116 // processor resource is still cleared from the 'NextInSequenceMask'.
117 // If that bit was already zero in NextInSequenceMask, then we update
118 // mask 'RemovedFromNextInSequence'.
119 //
120 // When NextInSequenceMask is reset back to its initial value, the algorithm
121 // removes any bits which are set in RemoveFromNextInSequence.
122 uint64_t RemovedFromNextInSequence;
123
124 // A mask of ready units.
125 uint64_t ReadyMask;
126
127 // Buffered resources will have this field set to a positive number bigger
128 // than 0. A buffered resource behaves like a separate reservation station
129 // implementing its own buffer for out-of-order execution.
130 // A buffer of 1 is for units that force in-order execution.
131 // A value of 0 is treated specially. In particular, a resource with
132 // A BufferSize = 0 is for an in-order issue/dispatch resource.
133 // That means, this resource is reserved starting from the dispatch event,
134 // until all the "resource cycles" are consumed after the issue event.
135 // While this resource is reserved, no other instruction may be dispatched.
136 int BufferSize;
137
138 // Available slots in the buffer (zero, if this is not a buffered resource).
139 unsigned AvailableSlots;
140
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000141 // True if this is resource is currently unavailable.
142 // An instruction may "reserve" a resource for a number of cycles.
143 // During those cycles, the reserved resource cannot be used for other
144 // instructions, even if the ReadyMask is set.
145 bool Unavailable;
146
147 bool isSubResourceReady(uint64_t ID) const { return ReadyMask & ID; }
148
149 /// Returns the mask identifier of the next available resource in the set.
150 uint64_t getNextInSequence() const {
151 assert(NextInSequenceMask);
152 return llvm::PowerOf2Floor(NextInSequenceMask);
153 }
154
155 /// Returns the mask of the next available resource within the set,
156 /// and updates the resource selector.
157 void updateNextInSequence() {
158 NextInSequenceMask ^= getNextInSequence();
159 if (!NextInSequenceMask)
160 NextInSequenceMask = ResourceSizeMask;
161 }
162
163 uint64_t computeResourceSizeMaskForGroup(uint64_t ResourceMask) {
164 assert(llvm::countPopulation(ResourceMask) > 1);
165 return ResourceMask ^ llvm::PowerOf2Floor(ResourceMask);
166 }
167
168public:
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000169 ResourceState(const llvm::MCProcResourceDesc &Desc, unsigned Index,
170 uint64_t Mask)
171 : ProcResourceDescIndex(Index), ResourceMask(Mask) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000172 bool IsAGroup = llvm::countPopulation(ResourceMask) > 1;
173 ResourceSizeMask = IsAGroup ? computeResourceSizeMaskForGroup(ResourceMask)
174 : ((1ULL << Desc.NumUnits) - 1);
175 NextInSequenceMask = ResourceSizeMask;
176 RemovedFromNextInSequence = 0;
177 ReadyMask = ResourceSizeMask;
178 BufferSize = Desc.BufferSize;
179 AvailableSlots = BufferSize == -1 ? 0U : static_cast<unsigned>(BufferSize);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000180 Unavailable = false;
181 }
182
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000183 unsigned getProcResourceID() const { return ProcResourceDescIndex; }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000184 uint64_t getResourceMask() const { return ResourceMask; }
185 int getBufferSize() const { return BufferSize; }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000186
187 bool isBuffered() const { return BufferSize > 0; }
188 bool isInOrder() const { return BufferSize == 1; }
189 bool isADispatchHazard() const { return BufferSize == 0; }
190 bool isReserved() const { return Unavailable; }
191
192 void setReserved() { Unavailable = true; }
193 void clearReserved() { Unavailable = false; }
194
195 // A resource is ready if it is not reserved, and if there are enough
196 // available units.
197 // If a resource is also a dispatch hazard, then we don't check if
198 // it is reserved because that check would always return true.
199 // A resource marked as "dispatch hazard" is always reserved at
200 // dispatch time. When this method is called, the assumption is that
201 // the user of this resource has been already dispatched.
202 bool isReady(unsigned NumUnits = 1) const {
203 return (!isReserved() || isADispatchHazard()) &&
204 llvm::countPopulation(ReadyMask) >= NumUnits;
205 }
206 bool isAResourceGroup() const {
207 return llvm::countPopulation(ResourceMask) > 1;
208 }
209
210 bool containsResource(uint64_t ID) const { return ResourceMask & ID; }
211
212 void markSubResourceAsUsed(uint64_t ID) {
213 assert(isSubResourceReady(ID));
214 ReadyMask ^= ID;
215 }
216
217 void releaseSubResource(uint64_t ID) {
218 assert(!isSubResourceReady(ID));
219 ReadyMask ^= ID;
220 }
221
222 unsigned getNumUnits() const {
223 return isAResourceGroup() ? 1U : llvm::countPopulation(ResourceSizeMask);
224 }
225
226 uint64_t selectNextInSequence();
227 void removeFromNextInSequence(uint64_t ID);
228
229 ResourceStateEvent isBufferAvailable() const {
230 if (isADispatchHazard() && isReserved())
231 return RS_RESERVED;
232 if (!isBuffered() || AvailableSlots)
233 return RS_BUFFER_AVAILABLE;
234 return RS_BUFFER_UNAVAILABLE;
235 }
236
237 void reserveBuffer() {
238 if (AvailableSlots)
239 AvailableSlots--;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000240 }
241
242 void releaseBuffer() {
243 if (BufferSize > 0)
244 AvailableSlots++;
245 assert(AvailableSlots <= static_cast<unsigned>(BufferSize));
246 }
247
248#ifndef NDEBUG
249 void dump() const;
250#endif
251};
252
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000253/// A resource unit identifier.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000254///
255/// This is used to identify a specific processor resource unit using a pair
256/// of indices where the 'first' index is a processor resource mask, and the
257/// 'second' index is an index for a "sub-resource" (i.e. unit).
258typedef std::pair<uint64_t, uint64_t> ResourceRef;
259
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000260// First: a MCProcResourceDesc index identifying a buffered resource.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000261// Second: max number of buffer entries used in this resource.
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000262typedef std::pair<unsigned, unsigned> BufferUsageEntry;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000263
264/// A resource manager for processor resource units and groups.
265///
266/// This class owns all the ResourceState objects, and it is responsible for
267/// acting on requests from a Scheduler by updating the internal state of
268/// ResourceState objects.
269/// This class doesn't know about instruction itineraries and functional units.
270/// In future, it can be extended to support itineraries too through the same
271/// public interface.
272class ResourceManager {
273 // The resource manager owns all the ResourceState.
274 using UniqueResourceState = std::unique_ptr<ResourceState>;
Andrea Di Biagioc2619a22018-08-02 11:12:35 +0000275 std::vector<UniqueResourceState> Resources;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000276
277 // Keeps track of which resources are busy, and how many cycles are left
278 // before those become usable again.
279 llvm::SmallDenseMap<ResourceRef, unsigned> BusyResources;
280
281 // A table to map processor resource IDs to processor resource masks.
282 llvm::SmallVector<uint64_t, 8> ProcResID2Mask;
283
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000284 // Populate resource descriptors.
Andrea Di Biagio4704f032018-03-20 12:25:54 +0000285 void initialize(const llvm::MCSchedModel &SM);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000286
287 // Returns the actual resource unit that will be used.
288 ResourceRef selectPipe(uint64_t ResourceID);
289
Andrea Di Biagioc2619a22018-08-02 11:12:35 +0000290 void use(const ResourceRef &RR);
291 void release(const ResourceRef &RR);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000292
Andrea Di Biagioc2619a22018-08-02 11:12:35 +0000293 unsigned getNumUnits(uint64_t ResourceID) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000294
295public:
Andrea Di Biagio4704f032018-03-20 12:25:54 +0000296 ResourceManager(const llvm::MCSchedModel &SM)
297 : ProcResID2Mask(SM.getNumProcResourceKinds()) {
298 initialize(SM);
299 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000300
Andrea Di Biagio44bfcd22018-03-19 19:09:38 +0000301 // Returns RS_BUFFER_AVAILABLE if buffered resources are not reserved, and if
302 // there are enough available slots in the buffers.
Andrea Di Biagioa3f2e482018-03-20 18:20:39 +0000303 ResourceStateEvent canBeDispatched(llvm::ArrayRef<uint64_t> Buffers) const;
304
305 // Return the processor resource identifier associated to this Mask.
Andrea Di Biagioc2619a22018-08-02 11:12:35 +0000306 unsigned resolveResourceMask(uint64_t Mask) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000307
Andrea Di Biagio44bfcd22018-03-19 19:09:38 +0000308 // Consume a slot in every buffered resource from array 'Buffers'. Resource
309 // units that are dispatch hazards (i.e. BufferSize=0) are marked as reserved.
Andrea Di Biagio847accd2018-03-20 19:06:34 +0000310 void reserveBuffers(llvm::ArrayRef<uint64_t> Buffers);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000311
Andrea Di Biagio44bfcd22018-03-19 19:09:38 +0000312 // Release buffer entries previously allocated by method reserveBuffers.
Andrea Di Biagio847accd2018-03-20 19:06:34 +0000313 void releaseBuffers(llvm::ArrayRef<uint64_t> Buffers);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000314
Andrea Di Biagioc2619a22018-08-02 11:12:35 +0000315 // Reserve a processor resource. A reserved resource is not available for
Matt Davis06ac6af2018-08-17 18:06:01 +0000316 // instruction issue until it is released.
Andrea Di Biagioc2619a22018-08-02 11:12:35 +0000317 void reserveResource(uint64_t ResourceID);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000318
Andrea Di Biagioc2619a22018-08-02 11:12:35 +0000319 // Release a previously reserved processor resource.
320 void releaseResource(uint64_t ResourceID);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000321
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000322 // Returns true if all resources are in-order, and there is at least one
323 // resource which is a dispatch hazard (BufferSize = 0).
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000324 bool mustIssueImmediately(const InstrDesc &Desc) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000325
326 bool canBeIssued(const InstrDesc &Desc) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000327
328 void issueInstruction(
Matt Davisad78e662018-04-26 22:30:40 +0000329 const InstrDesc &Desc,
Andrea Di Biagio51dba7d2018-03-23 17:36:07 +0000330 llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000331
332 void cycleEvent(llvm::SmallVectorImpl<ResourceRef> &ResourcesFreed);
333
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000334#ifndef NDEBUG
335 void dump() const {
Andrea Di Biagioc2619a22018-08-02 11:12:35 +0000336 for (const UniqueResourceState &Resource : Resources)
337 Resource->dump();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000338 }
339#endif
340}; // namespace mca
341
342/// Class Scheduler is responsible for issuing instructions to pipeline
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +0000343/// resources.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000344///
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +0000345/// Internally, it delegates to a ResourceManager the management of processor
346/// resources. This class is also responsible for tracking the progress of
347/// instructions from the dispatch stage, until the write-back stage.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000348///
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +0000349/// An instruction dispatched to the Scheduler is initially placed into either
350/// the 'WaitSet' or the 'ReadySet' depending on the availability of the input
351/// operands.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000352///
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +0000353/// An instruction is moved from the WaitSet to the ReadySet when register
354/// operands become available, and all memory dependencies are met.
355/// Instructions that are moved from the WaitSet to the ReadySet transition
356/// in state from 'IS_AVAILABLE' to 'IS_READY'.
357///
358/// On every cycle, the Scheduler checks if it can promote instructions from the
359/// WaitSet to the ReadySet.
360///
361/// An Instruction is moved from the ReadySet the `IssuedSet` when it is issued
362/// to a (one or more) pipeline(s). This event also causes an instruction state
363/// transition (i.e. from state IS_READY, to state IS_EXECUTING). An Instruction
364/// leaves the IssuedSet when it reaches the write-back stage.
Matt Davis362ea5f2018-07-06 18:03:14 +0000365class Scheduler : public HardwareUnit {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000366 const llvm::MCSchedModel &SM;
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000367 LSUnit *LSU;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000368
369 // Hardware resources that are managed by this scheduler.
370 std::unique_ptr<ResourceManager> Resources;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000371
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +0000372 std::vector<InstRef> WaitSet;
373 std::vector<InstRef> ReadySet;
374 std::vector<InstRef> IssuedSet;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000375
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000376 /// Issue an instruction without updating the ready queue.
Andrea Di Biagio27c4b092018-04-24 14:53:16 +0000377 void issueInstructionImpl(
Matt Davis21a8d322018-05-07 18:29:15 +0000378 InstRef &IR,
Andrea Di Biagio27c4b092018-04-24 14:53:16 +0000379 llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
380
Andrea Di Biagio51849952018-08-21 12:40:15 +0000381 // Identify instructions that have finished executing, and remove them from
382 // the IssuedSet. References to executed instructions are added to input
383 // vector 'Executed'.
384 void updateIssuedSet(llvm::SmallVectorImpl<InstRef> &Executed);
385
386 // Try to promote instructions from WaitSet to ReadySet.
387 // Add promoted instructions to the 'Ready' vector in input.
388 void promoteToReadySet(llvm::SmallVectorImpl<InstRef> &Ready);
389
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000390public:
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000391 Scheduler(const llvm::MCSchedModel &Model, LSUnit *Lsu)
392 : SM(Model), LSU(Lsu), Resources(llvm::make_unique<ResourceManager>(SM)) {
393 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000394
Andrea Di Biagio163419f2018-08-17 15:01:37 +0000395 // Stalls generated by the scheduler.
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000396 enum Status {
397 SC_AVAILABLE,
398 SC_LOAD_QUEUE_FULL,
399 SC_STORE_QUEUE_FULL,
400 SC_BUFFERS_FULL,
401 SC_DISPATCH_GROUP_STALL,
Andrea Di Biagio163419f2018-08-17 15:01:37 +0000402 };
403
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000404 /// Check if the instruction in 'IR' can be dispatched and returns an answer
405 /// in the form of a Status value.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000406 ///
Matt Davis679083e2018-05-17 19:22:29 +0000407 /// The DispatchStage is responsible for querying the Scheduler before
Matt Davis488ac4c2018-06-14 01:20:18 +0000408 /// dispatching new instructions. This routine is used for performing such
409 /// a query. If the instruction 'IR' can be dispatched, then true is
410 /// returned, otherwise false is returned with Event set to the stall type.
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000411 /// Internally, it also checks if the load/store unit is available.
412 Status isAvailable(const InstRef &IR) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000413
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000414 /// Reserves buffer and LSUnit queue resources that are necessary to issue
415 /// this instruction.
416 ///
417 /// Returns true if instruction IR is ready to be issued to the underlying
418 /// pipelines. Note that this operation cannot fail; it assumes that a
419 /// previous call to method `isAvailable(IR)` returned `SC_AVAILABLE`.
420 void dispatch(const InstRef &IR);
421
422 /// Returns true if IR is ready to be executed by the underlying pipelines.
423 /// This method assumes that IR has been previously dispatched.
424 bool isReady(const InstRef &IR) const;
Matt Davis488ac4c2018-06-14 01:20:18 +0000425
Andrea Di Biagio51849952018-08-21 12:40:15 +0000426 /// Issue an instruction and populates a vector of used pipeline resources,
427 /// and a vector of instructions that transitioned to the ready state as a
428 /// result of this event.
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000429 void issueInstruction(InstRef &IR,
Andrea Di Biagio51849952018-08-21 12:40:15 +0000430 llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Used,
431 llvm::SmallVectorImpl<InstRef> &Ready);
Matt Davis488ac4c2018-06-14 01:20:18 +0000432
Andrea Di Biagio0875e752018-08-20 14:41:36 +0000433 /// Returns true if IR has to be issued immediately, or if IR is a zero
434 /// latency instruction.
435 bool mustIssueImmediately(const InstRef &IR) const;
Andrea Di Biagio27c4b092018-04-24 14:53:16 +0000436
Andrea Di Biagio51849952018-08-21 12:40:15 +0000437 /// This routine notifies the Scheduler that a new cycle just started.
438 ///
439 /// It notifies the underlying ResourceManager that a new cycle just started.
440 /// Vector `Freed` is populated with resourceRef related to resources that
441 /// have changed in state, and that are now available to new instructions.
442 /// Instructions executed are added to vector Executed, while vector Ready is
443 /// populated with instructions that have become ready in this new cycle.
444 void cycleEvent(llvm::SmallVectorImpl<ResourceRef> &Freed,
445 llvm::SmallVectorImpl<InstRef> &Ready,
446 llvm::SmallVectorImpl<InstRef> &Executed);
Matt Davis488ac4c2018-06-14 01:20:18 +0000447
Andrea Di Biagio51849952018-08-21 12:40:15 +0000448 /// Convert a resource mask into a valid llvm processor resource identifier.
449 unsigned getResourceID(uint64_t Mask) const {
Matt Davis488ac4c2018-06-14 01:20:18 +0000450 return Resources->resolveResourceMask(Mask);
451 }
452
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +0000453 /// Select the next instruction to issue from the ReadySet.
Andrea Di Biagio51849952018-08-21 12:40:15 +0000454 ///
455 /// The default implementation of this method ranks instructions based on
456 /// their age, and the number of known users. It prioritizes older
457 /// instructions over younger instructions to minimize the pressure on the
458 /// reorder buffer. It also gives a little priority boost to instructions
459 /// with multiple users to better expose ILP.
Matt Davis488ac4c2018-06-14 01:20:18 +0000460 InstRef select();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000461
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000462#ifndef NDEBUG
Matt Davis488ac4c2018-06-14 01:20:18 +0000463 // Update the ready queues.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000464 void dump() const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000465
Matt Davis488ac4c2018-06-14 01:20:18 +0000466 // This routine performs a sanity check. This routine should only be called
467 // when we know that 'IR' is not in the scheduler's instruction queues.
468 void sanityCheck(const InstRef &IR) const {
Andrea Di Biagio1c3bcc62018-08-03 12:55:28 +0000469 assert(llvm::find(WaitSet, IR) == WaitSet.end());
470 assert(llvm::find(ReadySet, IR) == ReadySet.end());
471 assert(llvm::find(IssuedSet, IR) == IssuedSet.end());
Matt Davis488ac4c2018-06-14 01:20:18 +0000472 }
473#endif // !NDEBUG
474};
475} // namespace mca
476
477#endif // LLVM_TOOLS_LLVM_MCA_SCHEDULER_H