blob: d6da6c08a1cb4868bc7c3f0f91aef2219d0d6ee9 [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 Davis488ac4c2018-06-14 01:20:18 +000018#include "HWEventListener.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000019#include "Instruction.h"
20#include "LSUnit.h"
Matt Davis5b79ffc5b2018-05-25 18:00:25 +000021#include "RetireControlUnit.h"
Matt Davis488ac4c2018-06-14 01:20:18 +000022#include "llvm/ADT/ArrayRef.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000023#include "llvm/ADT/DenseMap.h"
Matt Davis488ac4c2018-06-14 01:20:18 +000024#include "llvm/ADT/SmallVector.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000025#include "llvm/MC/MCSubtargetInfo.h"
26#include <map>
27
28namespace mca {
29
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000030/// Used to notify the internal state of a processor resource.
31///
32/// A processor resource is available if it is not reserved, and there are
33/// available slots in the buffer. A processor resource is unavailable if it
34/// is either reserved, or the associated buffer is full. A processor resource
35/// with a buffer size of -1 is always available if it is not reserved.
36///
37/// Values of type ResourceStateEvent are returned by method
38/// ResourceState::isBufferAvailable(), which is used to query the internal
39/// state of a resource.
40///
41/// The naming convention for resource state events is:
42/// * Event names start with prefix RS_
43/// * Prefix RS_ is followed by a string describing the actual resource state.
44enum ResourceStateEvent {
45 RS_BUFFER_AVAILABLE,
46 RS_BUFFER_UNAVAILABLE,
47 RS_RESERVED
48};
49
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000050/// A descriptor for processor resources.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000051///
52/// Each object of class ResourceState is associated to a specific processor
53/// resource. There is an instance of this class for every processor resource
54/// defined by the scheduling model.
55/// A ResourceState dynamically tracks the availability of units of a processor
56/// resource. For example, the ResourceState of a ProcResGroup tracks the
57/// availability of resource units which are part of the group.
58///
59/// Internally, ResourceState uses a round-robin selector to identify
60/// which unit of the group shall be used next.
61class ResourceState {
Andrea Di Biagio0c541292018-03-10 16:55:07 +000062 // Index to the MCProcResourceDesc in the processor Model.
63 unsigned ProcResourceDescIndex;
Andrea Di Biagio4704f032018-03-20 12:25:54 +000064 // A resource mask. This is generated by the tool with the help of
65 // function `mca::createProcResourceMasks' (see Support.h).
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000066 uint64_t ResourceMask;
67
68 // A ProcResource can specify a number of units. For the purpose of dynamic
69 // scheduling, a processor resource with more than one unit behaves like a
70 // group. This field has one bit set for every unit/resource that is part of
71 // the group.
72 // For groups, this field defaults to 'ResourceMask'. For non-group
73 // resources, the number of bits set in this mask is equivalent to the
74 // number of units (i.e. field 'NumUnits' in 'ProcResourceUnits').
75 uint64_t ResourceSizeMask;
76
77 // A simple round-robin selector for processor resources.
78 // Each bit of the mask identifies a sub resource within this group.
79 //
80 // As an example, lets assume that this ResourceState describes a
81 // processor resource group composed of the following three units:
82 // ResourceA -- 0b001
83 // ResourceB -- 0b010
84 // ResourceC -- 0b100
85 //
86 // Each unit is identified by a ResourceMask which always contains a
87 // single bit set. Field NextInSequenceMask is initially set to value
88 // 0xb111. That value is obtained by OR'ing the resource masks of
89 // processor resource that are part of the group.
90 //
91 // NextInSequenceMask -- 0b111
92 //
93 // Field NextInSequenceMask is used by the resource manager (i.e.
94 // an object of class ResourceManager) to select the "next available resource"
95 // from the set. The algorithm would prioritize resources with a bigger
96 // ResourceMask value.
97 //
98 // In this example, there are three resources in the set, and 'ResourceC'
99 // has the highest mask value. The round-robin selector would firstly select
100 // 'ResourceC', then 'ResourceB', and eventually 'ResourceA'.
101 //
102 // When a resource R is used, its corresponding bit is cleared from the set.
103 //
104 // Back to the example:
105 // If 'ResourceC' is selected, then the new value of NextInSequenceMask
106 // becomes 0xb011.
107 //
108 // When NextInSequenceMask becomes zero, it is reset to its original value
109 // (in this example, that value would be 0b111).
110 uint64_t NextInSequenceMask;
111
112 // Some instructions can only be issued on very specific pipeline resources.
113 // For those instructions, we know exactly which resource would be consumed
114 // without having to dynamically select it using field 'NextInSequenceMask'.
115 //
116 // The resource mask bit associated to the (statically) selected
117 // processor resource is still cleared from the 'NextInSequenceMask'.
118 // If that bit was already zero in NextInSequenceMask, then we update
119 // mask 'RemovedFromNextInSequence'.
120 //
121 // When NextInSequenceMask is reset back to its initial value, the algorithm
122 // removes any bits which are set in RemoveFromNextInSequence.
123 uint64_t RemovedFromNextInSequence;
124
125 // A mask of ready units.
126 uint64_t ReadyMask;
127
128 // Buffered resources will have this field set to a positive number bigger
129 // than 0. A buffered resource behaves like a separate reservation station
130 // implementing its own buffer for out-of-order execution.
131 // A buffer of 1 is for units that force in-order execution.
132 // A value of 0 is treated specially. In particular, a resource with
133 // A BufferSize = 0 is for an in-order issue/dispatch resource.
134 // That means, this resource is reserved starting from the dispatch event,
135 // until all the "resource cycles" are consumed after the issue event.
136 // While this resource is reserved, no other instruction may be dispatched.
137 int BufferSize;
138
139 // Available slots in the buffer (zero, if this is not a buffered resource).
140 unsigned AvailableSlots;
141
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000142 // True if this is resource is currently unavailable.
143 // An instruction may "reserve" a resource for a number of cycles.
144 // During those cycles, the reserved resource cannot be used for other
145 // instructions, even if the ReadyMask is set.
146 bool Unavailable;
147
148 bool isSubResourceReady(uint64_t ID) const { return ReadyMask & ID; }
149
150 /// Returns the mask identifier of the next available resource in the set.
151 uint64_t getNextInSequence() const {
152 assert(NextInSequenceMask);
153 return llvm::PowerOf2Floor(NextInSequenceMask);
154 }
155
156 /// Returns the mask of the next available resource within the set,
157 /// and updates the resource selector.
158 void updateNextInSequence() {
159 NextInSequenceMask ^= getNextInSequence();
160 if (!NextInSequenceMask)
161 NextInSequenceMask = ResourceSizeMask;
162 }
163
164 uint64_t computeResourceSizeMaskForGroup(uint64_t ResourceMask) {
165 assert(llvm::countPopulation(ResourceMask) > 1);
166 return ResourceMask ^ llvm::PowerOf2Floor(ResourceMask);
167 }
168
169public:
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000170 ResourceState(const llvm::MCProcResourceDesc &Desc, unsigned Index,
171 uint64_t Mask)
172 : ProcResourceDescIndex(Index), ResourceMask(Mask) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000173 bool IsAGroup = llvm::countPopulation(ResourceMask) > 1;
174 ResourceSizeMask = IsAGroup ? computeResourceSizeMaskForGroup(ResourceMask)
175 : ((1ULL << Desc.NumUnits) - 1);
176 NextInSequenceMask = ResourceSizeMask;
177 RemovedFromNextInSequence = 0;
178 ReadyMask = ResourceSizeMask;
179 BufferSize = Desc.BufferSize;
180 AvailableSlots = BufferSize == -1 ? 0U : static_cast<unsigned>(BufferSize);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000181 Unavailable = false;
182 }
183
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000184 unsigned getProcResourceID() const { return ProcResourceDescIndex; }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000185 uint64_t getResourceMask() const { return ResourceMask; }
186 int getBufferSize() const { return BufferSize; }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000187
188 bool isBuffered() const { return BufferSize > 0; }
189 bool isInOrder() const { return BufferSize == 1; }
190 bool isADispatchHazard() const { return BufferSize == 0; }
191 bool isReserved() const { return Unavailable; }
192
193 void setReserved() { Unavailable = true; }
194 void clearReserved() { Unavailable = false; }
195
196 // A resource is ready if it is not reserved, and if there are enough
197 // available units.
198 // If a resource is also a dispatch hazard, then we don't check if
199 // it is reserved because that check would always return true.
200 // A resource marked as "dispatch hazard" is always reserved at
201 // dispatch time. When this method is called, the assumption is that
202 // the user of this resource has been already dispatched.
203 bool isReady(unsigned NumUnits = 1) const {
204 return (!isReserved() || isADispatchHazard()) &&
205 llvm::countPopulation(ReadyMask) >= NumUnits;
206 }
207 bool isAResourceGroup() const {
208 return llvm::countPopulation(ResourceMask) > 1;
209 }
210
211 bool containsResource(uint64_t ID) const { return ResourceMask & ID; }
212
213 void markSubResourceAsUsed(uint64_t ID) {
214 assert(isSubResourceReady(ID));
215 ReadyMask ^= ID;
216 }
217
218 void releaseSubResource(uint64_t ID) {
219 assert(!isSubResourceReady(ID));
220 ReadyMask ^= ID;
221 }
222
223 unsigned getNumUnits() const {
224 return isAResourceGroup() ? 1U : llvm::countPopulation(ResourceSizeMask);
225 }
226
227 uint64_t selectNextInSequence();
228 void removeFromNextInSequence(uint64_t ID);
229
230 ResourceStateEvent isBufferAvailable() const {
231 if (isADispatchHazard() && isReserved())
232 return RS_RESERVED;
233 if (!isBuffered() || AvailableSlots)
234 return RS_BUFFER_AVAILABLE;
235 return RS_BUFFER_UNAVAILABLE;
236 }
237
238 void reserveBuffer() {
239 if (AvailableSlots)
240 AvailableSlots--;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000241 }
242
243 void releaseBuffer() {
244 if (BufferSize > 0)
245 AvailableSlots++;
246 assert(AvailableSlots <= static_cast<unsigned>(BufferSize));
247 }
248
249#ifndef NDEBUG
250 void dump() const;
251#endif
252};
253
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000254/// A resource unit identifier.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000255///
256/// This is used to identify a specific processor resource unit using a pair
257/// of indices where the 'first' index is a processor resource mask, and the
258/// 'second' index is an index for a "sub-resource" (i.e. unit).
259typedef std::pair<uint64_t, uint64_t> ResourceRef;
260
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000261// First: a MCProcResourceDesc index identifying a buffered resource.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000262// Second: max number of buffer entries used in this resource.
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000263typedef std::pair<unsigned, unsigned> BufferUsageEntry;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000264
265/// A resource manager for processor resource units and groups.
266///
267/// This class owns all the ResourceState objects, and it is responsible for
268/// acting on requests from a Scheduler by updating the internal state of
269/// ResourceState objects.
270/// This class doesn't know about instruction itineraries and functional units.
271/// In future, it can be extended to support itineraries too through the same
272/// public interface.
273class ResourceManager {
274 // The resource manager owns all the ResourceState.
275 using UniqueResourceState = std::unique_ptr<ResourceState>;
276 llvm::SmallDenseMap<uint64_t, UniqueResourceState> Resources;
277
278 // Keeps track of which resources are busy, and how many cycles are left
279 // before those become usable again.
280 llvm::SmallDenseMap<ResourceRef, unsigned> BusyResources;
281
282 // A table to map processor resource IDs to processor resource masks.
283 llvm::SmallVector<uint64_t, 8> ProcResID2Mask;
284
285 // Adds a new resource state in Resources, as well as a new descriptor in
286 // ResourceDescriptor.
Andrea Di Biagio0c541292018-03-10 16:55:07 +0000287 void addResource(const llvm::MCProcResourceDesc &Desc, unsigned Index,
288 uint64_t Mask);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000289
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000290 // Populate resource descriptors.
Andrea Di Biagio4704f032018-03-20 12:25:54 +0000291 void initialize(const llvm::MCSchedModel &SM);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000292
293 // Returns the actual resource unit that will be used.
294 ResourceRef selectPipe(uint64_t ResourceID);
295
296 void use(ResourceRef RR);
297 void release(ResourceRef RR);
298
299 unsigned getNumUnits(uint64_t ResourceID) const {
300 assert(Resources.find(ResourceID) != Resources.end());
301 return Resources.find(ResourceID)->getSecond()->getNumUnits();
302 }
303
304 // Reserve a specific Resource kind.
305 void reserveBuffer(uint64_t ResourceID) {
306 assert(isBufferAvailable(ResourceID) ==
307 ResourceStateEvent::RS_BUFFER_AVAILABLE);
308 ResourceState &Resource = *Resources[ResourceID];
309 Resource.reserveBuffer();
310 }
311
312 void releaseBuffer(uint64_t ResourceID) {
313 Resources[ResourceID]->releaseBuffer();
314 }
315
316 ResourceStateEvent isBufferAvailable(uint64_t ResourceID) const {
317 const ResourceState &Resource = *Resources.find(ResourceID)->second;
318 return Resource.isBufferAvailable();
319 }
320
321 bool isReady(uint64_t ResourceID, unsigned NumUnits) const {
322 const ResourceState &Resource = *Resources.find(ResourceID)->second;
323 return Resource.isReady(NumUnits);
324 }
325
326public:
Andrea Di Biagio4704f032018-03-20 12:25:54 +0000327 ResourceManager(const llvm::MCSchedModel &SM)
328 : ProcResID2Mask(SM.getNumProcResourceKinds()) {
329 initialize(SM);
330 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000331
Andrea Di Biagio44bfcd22018-03-19 19:09:38 +0000332 // Returns RS_BUFFER_AVAILABLE if buffered resources are not reserved, and if
333 // there are enough available slots in the buffers.
Andrea Di Biagioa3f2e482018-03-20 18:20:39 +0000334 ResourceStateEvent canBeDispatched(llvm::ArrayRef<uint64_t> Buffers) const;
335
336 // Return the processor resource identifier associated to this Mask.
337 unsigned resolveResourceMask(uint64_t Mask) const {
338 return Resources.find(Mask)->second->getProcResourceID();
339 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000340
Andrea Di Biagio44bfcd22018-03-19 19:09:38 +0000341 // Consume a slot in every buffered resource from array 'Buffers'. Resource
342 // units that are dispatch hazards (i.e. BufferSize=0) are marked as reserved.
Andrea Di Biagio847accd2018-03-20 19:06:34 +0000343 void reserveBuffers(llvm::ArrayRef<uint64_t> Buffers);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000344
Andrea Di Biagio44bfcd22018-03-19 19:09:38 +0000345 // Release buffer entries previously allocated by method reserveBuffers.
Andrea Di Biagio847accd2018-03-20 19:06:34 +0000346 void releaseBuffers(llvm::ArrayRef<uint64_t> Buffers);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000347
348 void reserveResource(uint64_t ResourceID) {
349 ResourceState &Resource = *Resources[ResourceID];
350 assert(!Resource.isReserved());
351 Resource.setReserved();
352 }
353
354 void releaseResource(uint64_t ResourceID) {
355 ResourceState &Resource = *Resources[ResourceID];
356 Resource.clearReserved();
357 }
358
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000359 // Returns true if all resources are in-order, and there is at least one
360 // resource which is a dispatch hazard (BufferSize = 0).
361 bool mustIssueImmediately(const InstrDesc &Desc);
362
363 bool canBeIssued(const InstrDesc &Desc) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000364
365 void issueInstruction(
Matt Davisad78e662018-04-26 22:30:40 +0000366 const InstrDesc &Desc,
Andrea Di Biagio51dba7d2018-03-23 17:36:07 +0000367 llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000368
369 void cycleEvent(llvm::SmallVectorImpl<ResourceRef> &ResourcesFreed);
370
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000371#ifndef NDEBUG
372 void dump() const {
373 for (const std::pair<uint64_t, UniqueResourceState> &Resource : Resources)
374 Resource.second->dump();
375 }
376#endif
377}; // namespace mca
378
379/// Class Scheduler is responsible for issuing instructions to pipeline
380/// resources. Internally, it delegates to a ResourceManager the management of
381/// processor resources.
382/// This class is also responsible for tracking the progress of instructions
383/// from the dispatch stage, until the write-back stage.
384///
385/// An nstruction dispatched to the Scheduler is initially placed into either
386/// the 'WaitQueue' or the 'ReadyQueue' depending on the availability of the
387/// input operands. Instructions in the WaitQueue are ordered by instruction
388/// index. An instruction is moved from the WaitQueue to the ReadyQueue when
389/// register operands become available, and all memory dependencies are met.
390/// Instructions that are moved from the WaitQueue to the ReadyQueue transition
391/// from state 'IS_AVAILABLE' to state 'IS_READY'.
392///
393/// At the beginning of each cycle, the Scheduler checks if there are
394/// instructions in the WaitQueue that can be moved to the ReadyQueue. If the
395/// ReadyQueue is not empty, then older instructions from the queue are issued
396/// to the processor pipelines, and the underlying ResourceManager is updated
397/// accordingly. The ReadyQueue is ordered by instruction index to guarantee
398/// that the first instructions in the set are also the oldest.
399///
400/// An Instruction is moved from the ReadyQueue the `IssuedQueue` when it is
401/// issued to a (one or more) pipeline(s). This event also causes an instruction
402/// state transition (i.e. from state IS_READY, to state IS_EXECUTING).
403/// An Instruction leaves the IssuedQueue when it reaches the write-back stage.
404class Scheduler {
405 const llvm::MCSchedModel &SM;
406
407 // Hardware resources that are managed by this scheduler.
408 std::unique_ptr<ResourceManager> Resources;
409 std::unique_ptr<LSUnit> LSU;
410
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000411 using QueueEntryTy = std::pair<unsigned, Instruction *>;
412 std::map<unsigned, Instruction *> WaitQueue;
413 std::map<unsigned, Instruction *> ReadyQueue;
414 std::map<unsigned, Instruction *> IssuedQueue;
415
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000416 /// Issue an instruction without updating the ready queue.
Andrea Di Biagio27c4b092018-04-24 14:53:16 +0000417 void issueInstructionImpl(
Matt Davis21a8d322018-05-07 18:29:15 +0000418 InstRef &IR,
Andrea Di Biagio27c4b092018-04-24 14:53:16 +0000419 llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
420
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000421public:
Matt Davis488ac4c2018-06-14 01:20:18 +0000422 Scheduler(const llvm::MCSchedModel &Model, unsigned LoadQueueSize,
423 unsigned StoreQueueSize, bool AssumeNoAlias)
424 : SM(Model), Resources(llvm::make_unique<ResourceManager>(SM)),
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000425 LSU(llvm::make_unique<LSUnit>(LoadQueueSize, StoreQueueSize,
Matt Davis488ac4c2018-06-14 01:20:18 +0000426 AssumeNoAlias)) {}
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000427
Matt Davis21a8d322018-05-07 18:29:15 +0000428 /// Check if the instruction in 'IR' can be dispatched.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000429 ///
Matt Davis679083e2018-05-17 19:22:29 +0000430 /// The DispatchStage is responsible for querying the Scheduler before
Matt Davis488ac4c2018-06-14 01:20:18 +0000431 /// dispatching new instructions. This routine is used for performing such
432 /// a query. If the instruction 'IR' can be dispatched, then true is
433 /// returned, otherwise false is returned with Event set to the stall type.
434 bool canBeDispatched(const InstRef &IR,
435 HWStallEvent::GenericEventType &Event) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000436
Matt Davis488ac4c2018-06-14 01:20:18 +0000437 /// Returns true if there is availibility for IR in the LSU.
438 bool isReady(const InstRef &IR) const { return LSU->isReady(IR); }
439
440 /// Issue an instruction. The Used container is populated with
441 /// the resource objects consumed on behalf of issuing this instruction.
442 void
443 issueInstruction(InstRef &IR,
444 llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Used);
445
446 /// This routine will attempt to issue an instruction immediately (for
447 /// zero-latency instructions).
448 ///
449 /// Returns true if the instruction is issued immediately. If this does not
450 /// occur, then the instruction will be added to the Scheduler's ReadyQueue.
451 bool issueImmediately(InstRef &IR);
Andrea Di Biagio27c4b092018-04-24 14:53:16 +0000452
453 /// Reserve one entry in each buffered resource.
454 void reserveBuffers(llvm::ArrayRef<uint64_t> Buffers) {
455 Resources->reserveBuffers(Buffers);
456 }
457
458 /// Release buffer entries previously allocated by method reserveBuffers.
459 void releaseBuffers(llvm::ArrayRef<uint64_t> Buffers) {
460 Resources->releaseBuffers(Buffers);
461 }
462
Matt Davis488ac4c2018-06-14 01:20:18 +0000463 /// Update the resources managed by the scheduler.
464 /// This routine is to be called at the start of a new cycle, and is
465 /// responsible for updating scheduler resources. Resources are released
466 /// once they have been fully consumed.
467 void reclaimSimulatedResources(llvm::SmallVectorImpl<ResourceRef> &Freed);
468
469 /// Move instructions from the WaitQueue to the ReadyQueue if input operands
470 /// are all available.
471 void promoteToReadyQueue(llvm::SmallVectorImpl<InstRef> &Ready);
472
473 /// Update the ready queue.
474 void updatePendingQueue(llvm::SmallVectorImpl<InstRef> &Ready);
475
476 /// Update the issued queue.
477 void updateIssuedQueue(llvm::SmallVectorImpl<InstRef> &Executed);
478
479 /// Updates the Scheduler's resources to reflect that an instruction has just
480 /// been executed.
481 void onInstructionExecuted(const InstRef &IR);
482
483 /// Obtain the processor's resource identifier for the given
484 /// resource mask.
485 unsigned getResourceID(uint64_t Mask) {
486 return Resources->resolveResourceMask(Mask);
487 }
488
489 /// Reserve resources necessary to issue the instruction.
490 /// Returns true if the resources are ready and the (LSU) can
491 /// execute the given instruction immediately.
492 bool reserveResources(InstRef &IR);
493
494 /// Select the next instruction to issue from the ReadyQueue.
495 /// This method gives priority to older instructions.
496 InstRef select();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000497
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000498#ifndef NDEBUG
Matt Davis488ac4c2018-06-14 01:20:18 +0000499 // Update the ready queues.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000500 void dump() const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000501
Matt Davis488ac4c2018-06-14 01:20:18 +0000502 // This routine performs a sanity check. This routine should only be called
503 // when we know that 'IR' is not in the scheduler's instruction queues.
504 void sanityCheck(const InstRef &IR) const {
505 const unsigned Idx = IR.getSourceIndex();
506 assert(WaitQueue.find(Idx) == WaitQueue.end());
507 assert(ReadyQueue.find(Idx) == ReadyQueue.end());
508 assert(IssuedQueue.find(Idx) == IssuedQueue.end());
509 }
510#endif // !NDEBUG
511};
512} // namespace mca
513
514#endif // LLVM_TOOLS_LLVM_MCA_SCHEDULER_H