xref: /freebsd/contrib/llvm-project/llvm/lib/MCA/HardwareUnits/Scheduler.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===--------------------- Scheduler.cpp ------------------------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // A scheduler for processor resource units and processor resource groups.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "llvm/MCA/HardwareUnits/Scheduler.h"
14*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
15*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric namespace llvm {
18*0b57cec5SDimitry Andric namespace mca {
19*0b57cec5SDimitry Andric 
20*0b57cec5SDimitry Andric #define DEBUG_TYPE "llvm-mca"
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric void Scheduler::initializeStrategy(std::unique_ptr<SchedulerStrategy> S) {
23*0b57cec5SDimitry Andric   // Ensure we have a valid (non-null) strategy object.
24*0b57cec5SDimitry Andric   Strategy = S ? std::move(S) : llvm::make_unique<DefaultSchedulerStrategy>();
25*0b57cec5SDimitry Andric }
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric // Anchor the vtable of SchedulerStrategy and DefaultSchedulerStrategy.
28*0b57cec5SDimitry Andric SchedulerStrategy::~SchedulerStrategy() = default;
29*0b57cec5SDimitry Andric DefaultSchedulerStrategy::~DefaultSchedulerStrategy() = default;
30*0b57cec5SDimitry Andric 
31*0b57cec5SDimitry Andric #ifndef NDEBUG
32*0b57cec5SDimitry Andric void Scheduler::dump() const {
33*0b57cec5SDimitry Andric   dbgs() << "[SCHEDULER]: WaitSet size is: " << WaitSet.size() << '\n';
34*0b57cec5SDimitry Andric   dbgs() << "[SCHEDULER]: ReadySet size is: " << ReadySet.size() << '\n';
35*0b57cec5SDimitry Andric   dbgs() << "[SCHEDULER]: IssuedSet size is: " << IssuedSet.size() << '\n';
36*0b57cec5SDimitry Andric   Resources->dump();
37*0b57cec5SDimitry Andric }
38*0b57cec5SDimitry Andric #endif
39*0b57cec5SDimitry Andric 
40*0b57cec5SDimitry Andric Scheduler::Status Scheduler::isAvailable(const InstRef &IR) {
41*0b57cec5SDimitry Andric   const InstrDesc &Desc = IR.getInstruction()->getDesc();
42*0b57cec5SDimitry Andric 
43*0b57cec5SDimitry Andric   ResourceStateEvent RSE = Resources->canBeDispatched(Desc.Buffers);
44*0b57cec5SDimitry Andric   HadTokenStall = RSE != RS_BUFFER_AVAILABLE;
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric   switch (RSE) {
47*0b57cec5SDimitry Andric   case ResourceStateEvent::RS_BUFFER_UNAVAILABLE:
48*0b57cec5SDimitry Andric     return Scheduler::SC_BUFFERS_FULL;
49*0b57cec5SDimitry Andric   case ResourceStateEvent::RS_RESERVED:
50*0b57cec5SDimitry Andric     return Scheduler::SC_DISPATCH_GROUP_STALL;
51*0b57cec5SDimitry Andric   case ResourceStateEvent::RS_BUFFER_AVAILABLE:
52*0b57cec5SDimitry Andric     break;
53*0b57cec5SDimitry Andric   }
54*0b57cec5SDimitry Andric 
55*0b57cec5SDimitry Andric   // Give lower priority to LSUnit stall events.
56*0b57cec5SDimitry Andric   LSUnit::Status LSS = LSU.isAvailable(IR);
57*0b57cec5SDimitry Andric   HadTokenStall = LSS != LSUnit::LSU_AVAILABLE;
58*0b57cec5SDimitry Andric 
59*0b57cec5SDimitry Andric   switch (LSS) {
60*0b57cec5SDimitry Andric   case LSUnit::LSU_LQUEUE_FULL:
61*0b57cec5SDimitry Andric     return Scheduler::SC_LOAD_QUEUE_FULL;
62*0b57cec5SDimitry Andric   case LSUnit::LSU_SQUEUE_FULL:
63*0b57cec5SDimitry Andric     return Scheduler::SC_STORE_QUEUE_FULL;
64*0b57cec5SDimitry Andric   case LSUnit::LSU_AVAILABLE:
65*0b57cec5SDimitry Andric     return Scheduler::SC_AVAILABLE;
66*0b57cec5SDimitry Andric   }
67*0b57cec5SDimitry Andric 
68*0b57cec5SDimitry Andric   llvm_unreachable("Don't know how to process this LSU state result!");
69*0b57cec5SDimitry Andric }
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric void Scheduler::issueInstructionImpl(
72*0b57cec5SDimitry Andric     InstRef &IR,
73*0b57cec5SDimitry Andric     SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &UsedResources) {
74*0b57cec5SDimitry Andric   Instruction *IS = IR.getInstruction();
75*0b57cec5SDimitry Andric   const InstrDesc &D = IS->getDesc();
76*0b57cec5SDimitry Andric 
77*0b57cec5SDimitry Andric   // Issue the instruction and collect all the consumed resources
78*0b57cec5SDimitry Andric   // into a vector. That vector is then used to notify the listener.
79*0b57cec5SDimitry Andric   Resources->issueInstruction(D, UsedResources);
80*0b57cec5SDimitry Andric 
81*0b57cec5SDimitry Andric   // Notify the instruction that it started executing.
82*0b57cec5SDimitry Andric   // This updates the internal state of each write.
83*0b57cec5SDimitry Andric   IS->execute(IR.getSourceIndex());
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric   IS->computeCriticalRegDep();
86*0b57cec5SDimitry Andric 
87*0b57cec5SDimitry Andric   if (IS->isMemOp()) {
88*0b57cec5SDimitry Andric     LSU.onInstructionIssued(IR);
89*0b57cec5SDimitry Andric     const MemoryGroup &Group = LSU.getGroup(IS->getLSUTokenID());
90*0b57cec5SDimitry Andric     IS->setCriticalMemDep(Group.getCriticalPredecessor());
91*0b57cec5SDimitry Andric   }
92*0b57cec5SDimitry Andric 
93*0b57cec5SDimitry Andric   if (IS->isExecuting())
94*0b57cec5SDimitry Andric     IssuedSet.emplace_back(IR);
95*0b57cec5SDimitry Andric   else if (IS->isExecuted())
96*0b57cec5SDimitry Andric     LSU.onInstructionExecuted(IR);
97*0b57cec5SDimitry Andric }
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric // Release the buffered resources and issue the instruction.
100*0b57cec5SDimitry Andric void Scheduler::issueInstruction(
101*0b57cec5SDimitry Andric     InstRef &IR,
102*0b57cec5SDimitry Andric     SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &UsedResources,
103*0b57cec5SDimitry Andric     SmallVectorImpl<InstRef> &PendingInstructions,
104*0b57cec5SDimitry Andric     SmallVectorImpl<InstRef> &ReadyInstructions) {
105*0b57cec5SDimitry Andric   const Instruction &Inst = *IR.getInstruction();
106*0b57cec5SDimitry Andric   bool HasDependentUsers = Inst.hasDependentUsers();
107*0b57cec5SDimitry Andric   HasDependentUsers |= Inst.isMemOp() && LSU.hasDependentUsers(IR);
108*0b57cec5SDimitry Andric 
109*0b57cec5SDimitry Andric   Resources->releaseBuffers(Inst.getDesc().Buffers);
110*0b57cec5SDimitry Andric   issueInstructionImpl(IR, UsedResources);
111*0b57cec5SDimitry Andric   // Instructions that have been issued during this cycle might have unblocked
112*0b57cec5SDimitry Andric   // other dependent instructions. Dependent instructions may be issued during
113*0b57cec5SDimitry Andric   // this same cycle if operands have ReadAdvance entries.  Promote those
114*0b57cec5SDimitry Andric   // instructions to the ReadySet and notify the caller that those are ready.
115*0b57cec5SDimitry Andric   if (HasDependentUsers)
116*0b57cec5SDimitry Andric     if (promoteToPendingSet(PendingInstructions))
117*0b57cec5SDimitry Andric       promoteToReadySet(ReadyInstructions);
118*0b57cec5SDimitry Andric }
119*0b57cec5SDimitry Andric 
120*0b57cec5SDimitry Andric bool Scheduler::promoteToReadySet(SmallVectorImpl<InstRef> &Ready) {
121*0b57cec5SDimitry Andric   // Scan the set of waiting instructions and promote them to the
122*0b57cec5SDimitry Andric   // ready set if operands are all ready.
123*0b57cec5SDimitry Andric   unsigned PromotedElements = 0;
124*0b57cec5SDimitry Andric   for (auto I = PendingSet.begin(), E = PendingSet.end(); I != E;) {
125*0b57cec5SDimitry Andric     InstRef &IR = *I;
126*0b57cec5SDimitry Andric     if (!IR)
127*0b57cec5SDimitry Andric       break;
128*0b57cec5SDimitry Andric 
129*0b57cec5SDimitry Andric     // Check if there are unsolved register dependencies.
130*0b57cec5SDimitry Andric     Instruction &IS = *IR.getInstruction();
131*0b57cec5SDimitry Andric     if (!IS.isReady() && !IS.updatePending()) {
132*0b57cec5SDimitry Andric       ++I;
133*0b57cec5SDimitry Andric       continue;
134*0b57cec5SDimitry Andric     }
135*0b57cec5SDimitry Andric     // Check if there are unsolved memory dependencies.
136*0b57cec5SDimitry Andric     if (IS.isMemOp() && !LSU.isReady(IR)) {
137*0b57cec5SDimitry Andric       ++I;
138*0b57cec5SDimitry Andric       continue;
139*0b57cec5SDimitry Andric     }
140*0b57cec5SDimitry Andric 
141*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "[SCHEDULER]: Instruction #" << IR
142*0b57cec5SDimitry Andric                       << " promoted to the READY set.\n");
143*0b57cec5SDimitry Andric 
144*0b57cec5SDimitry Andric     Ready.emplace_back(IR);
145*0b57cec5SDimitry Andric     ReadySet.emplace_back(IR);
146*0b57cec5SDimitry Andric 
147*0b57cec5SDimitry Andric     IR.invalidate();
148*0b57cec5SDimitry Andric     ++PromotedElements;
149*0b57cec5SDimitry Andric     std::iter_swap(I, E - PromotedElements);
150*0b57cec5SDimitry Andric   }
151*0b57cec5SDimitry Andric 
152*0b57cec5SDimitry Andric   PendingSet.resize(PendingSet.size() - PromotedElements);
153*0b57cec5SDimitry Andric   return PromotedElements;
154*0b57cec5SDimitry Andric }
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric bool Scheduler::promoteToPendingSet(SmallVectorImpl<InstRef> &Pending) {
157*0b57cec5SDimitry Andric   // Scan the set of waiting instructions and promote them to the
158*0b57cec5SDimitry Andric   // pending set if operands are all ready.
159*0b57cec5SDimitry Andric   unsigned RemovedElements = 0;
160*0b57cec5SDimitry Andric   for (auto I = WaitSet.begin(), E = WaitSet.end(); I != E;) {
161*0b57cec5SDimitry Andric     InstRef &IR = *I;
162*0b57cec5SDimitry Andric     if (!IR)
163*0b57cec5SDimitry Andric       break;
164*0b57cec5SDimitry Andric 
165*0b57cec5SDimitry Andric     // Check if this instruction is now ready. In case, force
166*0b57cec5SDimitry Andric     // a transition in state using method 'updateDispatched()'.
167*0b57cec5SDimitry Andric     Instruction &IS = *IR.getInstruction();
168*0b57cec5SDimitry Andric     if (IS.isDispatched() && !IS.updateDispatched()) {
169*0b57cec5SDimitry Andric       ++I;
170*0b57cec5SDimitry Andric       continue;
171*0b57cec5SDimitry Andric     }
172*0b57cec5SDimitry Andric 
173*0b57cec5SDimitry Andric     if (IS.isMemOp() && LSU.isWaiting(IR)) {
174*0b57cec5SDimitry Andric       ++I;
175*0b57cec5SDimitry Andric       continue;
176*0b57cec5SDimitry Andric     }
177*0b57cec5SDimitry Andric 
178*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "[SCHEDULER]: Instruction #" << IR
179*0b57cec5SDimitry Andric                       << " promoted to the PENDING set.\n");
180*0b57cec5SDimitry Andric 
181*0b57cec5SDimitry Andric     Pending.emplace_back(IR);
182*0b57cec5SDimitry Andric     PendingSet.emplace_back(IR);
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric     IR.invalidate();
185*0b57cec5SDimitry Andric     ++RemovedElements;
186*0b57cec5SDimitry Andric     std::iter_swap(I, E - RemovedElements);
187*0b57cec5SDimitry Andric   }
188*0b57cec5SDimitry Andric 
189*0b57cec5SDimitry Andric   WaitSet.resize(WaitSet.size() - RemovedElements);
190*0b57cec5SDimitry Andric   return RemovedElements;
191*0b57cec5SDimitry Andric }
192*0b57cec5SDimitry Andric 
193*0b57cec5SDimitry Andric InstRef Scheduler::select() {
194*0b57cec5SDimitry Andric   unsigned QueueIndex = ReadySet.size();
195*0b57cec5SDimitry Andric   for (unsigned I = 0, E = ReadySet.size(); I != E; ++I) {
196*0b57cec5SDimitry Andric     InstRef &IR = ReadySet[I];
197*0b57cec5SDimitry Andric     if (QueueIndex == ReadySet.size() ||
198*0b57cec5SDimitry Andric         Strategy->compare(IR, ReadySet[QueueIndex])) {
199*0b57cec5SDimitry Andric       Instruction &IS = *IR.getInstruction();
200*0b57cec5SDimitry Andric       uint64_t BusyResourceMask = Resources->checkAvailability(IS.getDesc());
201*0b57cec5SDimitry Andric       if (BusyResourceMask)
202*0b57cec5SDimitry Andric         IS.setCriticalResourceMask(BusyResourceMask);
203*0b57cec5SDimitry Andric       BusyResourceUnits |= BusyResourceMask;
204*0b57cec5SDimitry Andric       if (!BusyResourceMask)
205*0b57cec5SDimitry Andric         QueueIndex = I;
206*0b57cec5SDimitry Andric     }
207*0b57cec5SDimitry Andric   }
208*0b57cec5SDimitry Andric 
209*0b57cec5SDimitry Andric   if (QueueIndex == ReadySet.size())
210*0b57cec5SDimitry Andric     return InstRef();
211*0b57cec5SDimitry Andric 
212*0b57cec5SDimitry Andric   // We found an instruction to issue.
213*0b57cec5SDimitry Andric   InstRef IR = ReadySet[QueueIndex];
214*0b57cec5SDimitry Andric   std::swap(ReadySet[QueueIndex], ReadySet[ReadySet.size() - 1]);
215*0b57cec5SDimitry Andric   ReadySet.pop_back();
216*0b57cec5SDimitry Andric   return IR;
217*0b57cec5SDimitry Andric }
218*0b57cec5SDimitry Andric 
219*0b57cec5SDimitry Andric void Scheduler::updateIssuedSet(SmallVectorImpl<InstRef> &Executed) {
220*0b57cec5SDimitry Andric   unsigned RemovedElements = 0;
221*0b57cec5SDimitry Andric   for (auto I = IssuedSet.begin(), E = IssuedSet.end(); I != E;) {
222*0b57cec5SDimitry Andric     InstRef &IR = *I;
223*0b57cec5SDimitry Andric     if (!IR)
224*0b57cec5SDimitry Andric       break;
225*0b57cec5SDimitry Andric     Instruction &IS = *IR.getInstruction();
226*0b57cec5SDimitry Andric     if (!IS.isExecuted()) {
227*0b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "[SCHEDULER]: Instruction #" << IR
228*0b57cec5SDimitry Andric                         << " is still executing.\n");
229*0b57cec5SDimitry Andric       ++I;
230*0b57cec5SDimitry Andric       continue;
231*0b57cec5SDimitry Andric     }
232*0b57cec5SDimitry Andric 
233*0b57cec5SDimitry Andric     // Instruction IR has completed execution.
234*0b57cec5SDimitry Andric     LSU.onInstructionExecuted(IR);
235*0b57cec5SDimitry Andric     Executed.emplace_back(IR);
236*0b57cec5SDimitry Andric     ++RemovedElements;
237*0b57cec5SDimitry Andric     IR.invalidate();
238*0b57cec5SDimitry Andric     std::iter_swap(I, E - RemovedElements);
239*0b57cec5SDimitry Andric   }
240*0b57cec5SDimitry Andric 
241*0b57cec5SDimitry Andric   IssuedSet.resize(IssuedSet.size() - RemovedElements);
242*0b57cec5SDimitry Andric }
243*0b57cec5SDimitry Andric 
244*0b57cec5SDimitry Andric uint64_t Scheduler::analyzeResourcePressure(SmallVectorImpl<InstRef> &Insts) {
245*0b57cec5SDimitry Andric   Insts.insert(Insts.end(), ReadySet.begin(), ReadySet.end());
246*0b57cec5SDimitry Andric   return BusyResourceUnits;
247*0b57cec5SDimitry Andric }
248*0b57cec5SDimitry Andric 
249*0b57cec5SDimitry Andric void Scheduler::analyzeDataDependencies(SmallVectorImpl<InstRef> &RegDeps,
250*0b57cec5SDimitry Andric                                         SmallVectorImpl<InstRef> &MemDeps) {
251*0b57cec5SDimitry Andric   const auto EndIt = PendingSet.end() - NumDispatchedToThePendingSet;
252*0b57cec5SDimitry Andric   for (const InstRef &IR : make_range(PendingSet.begin(), EndIt)) {
253*0b57cec5SDimitry Andric     const Instruction &IS = *IR.getInstruction();
254*0b57cec5SDimitry Andric     if (Resources->checkAvailability(IS.getDesc()))
255*0b57cec5SDimitry Andric       continue;
256*0b57cec5SDimitry Andric 
257*0b57cec5SDimitry Andric     if (IS.isMemOp() && LSU.isPending(IR))
258*0b57cec5SDimitry Andric       MemDeps.emplace_back(IR);
259*0b57cec5SDimitry Andric 
260*0b57cec5SDimitry Andric     if (IS.isPending())
261*0b57cec5SDimitry Andric       RegDeps.emplace_back(IR);
262*0b57cec5SDimitry Andric   }
263*0b57cec5SDimitry Andric }
264*0b57cec5SDimitry Andric 
265*0b57cec5SDimitry Andric void Scheduler::cycleEvent(SmallVectorImpl<ResourceRef> &Freed,
266*0b57cec5SDimitry Andric                            SmallVectorImpl<InstRef> &Executed,
267*0b57cec5SDimitry Andric                            SmallVectorImpl<InstRef> &Pending,
268*0b57cec5SDimitry Andric                            SmallVectorImpl<InstRef> &Ready) {
269*0b57cec5SDimitry Andric   LSU.cycleEvent();
270*0b57cec5SDimitry Andric 
271*0b57cec5SDimitry Andric   // Release consumed resources.
272*0b57cec5SDimitry Andric   Resources->cycleEvent(Freed);
273*0b57cec5SDimitry Andric 
274*0b57cec5SDimitry Andric   for (InstRef &IR : IssuedSet)
275*0b57cec5SDimitry Andric     IR.getInstruction()->cycleEvent();
276*0b57cec5SDimitry Andric   updateIssuedSet(Executed);
277*0b57cec5SDimitry Andric 
278*0b57cec5SDimitry Andric   for (InstRef &IR : PendingSet)
279*0b57cec5SDimitry Andric     IR.getInstruction()->cycleEvent();
280*0b57cec5SDimitry Andric 
281*0b57cec5SDimitry Andric   for (InstRef &IR : WaitSet)
282*0b57cec5SDimitry Andric     IR.getInstruction()->cycleEvent();
283*0b57cec5SDimitry Andric 
284*0b57cec5SDimitry Andric   promoteToPendingSet(Pending);
285*0b57cec5SDimitry Andric   promoteToReadySet(Ready);
286*0b57cec5SDimitry Andric 
287*0b57cec5SDimitry Andric   NumDispatchedToThePendingSet = 0;
288*0b57cec5SDimitry Andric   BusyResourceUnits = 0;
289*0b57cec5SDimitry Andric }
290*0b57cec5SDimitry Andric 
291*0b57cec5SDimitry Andric bool Scheduler::mustIssueImmediately(const InstRef &IR) const {
292*0b57cec5SDimitry Andric   const InstrDesc &Desc = IR.getInstruction()->getDesc();
293*0b57cec5SDimitry Andric   if (Desc.isZeroLatency())
294*0b57cec5SDimitry Andric     return true;
295*0b57cec5SDimitry Andric   // Instructions that use an in-order dispatch/issue processor resource must be
296*0b57cec5SDimitry Andric   // issued immediately to the pipeline(s). Any other in-order buffered
297*0b57cec5SDimitry Andric   // resources (i.e. BufferSize=1) is consumed.
298*0b57cec5SDimitry Andric   return Desc.MustIssueImmediately;
299*0b57cec5SDimitry Andric }
300*0b57cec5SDimitry Andric 
301*0b57cec5SDimitry Andric bool Scheduler::dispatch(InstRef &IR) {
302*0b57cec5SDimitry Andric   Instruction &IS = *IR.getInstruction();
303*0b57cec5SDimitry Andric   const InstrDesc &Desc = IS.getDesc();
304*0b57cec5SDimitry Andric   Resources->reserveBuffers(Desc.Buffers);
305*0b57cec5SDimitry Andric 
306*0b57cec5SDimitry Andric   // If necessary, reserve queue entries in the load-store unit (LSU).
307*0b57cec5SDimitry Andric   if (IS.isMemOp())
308*0b57cec5SDimitry Andric     IS.setLSUTokenID(LSU.dispatch(IR));
309*0b57cec5SDimitry Andric 
310*0b57cec5SDimitry Andric   if (IS.isDispatched() || (IS.isMemOp() && LSU.isWaiting(IR))) {
311*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the WaitSet\n");
312*0b57cec5SDimitry Andric     WaitSet.push_back(IR);
313*0b57cec5SDimitry Andric     return false;
314*0b57cec5SDimitry Andric   }
315*0b57cec5SDimitry Andric 
316*0b57cec5SDimitry Andric   if (IS.isPending() || (IS.isMemOp() && LSU.isPending(IR))) {
317*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR
318*0b57cec5SDimitry Andric                       << " to the PendingSet\n");
319*0b57cec5SDimitry Andric     PendingSet.push_back(IR);
320*0b57cec5SDimitry Andric     ++NumDispatchedToThePendingSet;
321*0b57cec5SDimitry Andric     return false;
322*0b57cec5SDimitry Andric   }
323*0b57cec5SDimitry Andric 
324*0b57cec5SDimitry Andric   assert(IS.isReady() && (!IS.isMemOp() || LSU.isReady(IR)) &&
325*0b57cec5SDimitry Andric          "Unexpected internal state found!");
326*0b57cec5SDimitry Andric   // Don't add a zero-latency instruction to the Ready queue.
327*0b57cec5SDimitry Andric   // A zero-latency instruction doesn't consume any scheduler resources. That is
328*0b57cec5SDimitry Andric   // because it doesn't need to be executed, and it is often removed at register
329*0b57cec5SDimitry Andric   // renaming stage. For example, register-register moves are often optimized at
330*0b57cec5SDimitry Andric   // register renaming stage by simply updating register aliases. On some
331*0b57cec5SDimitry Andric   // targets, zero-idiom instructions (for example: a xor that clears the value
332*0b57cec5SDimitry Andric   // of a register) are treated specially, and are often eliminated at register
333*0b57cec5SDimitry Andric   // renaming stage.
334*0b57cec5SDimitry Andric   if (!mustIssueImmediately(IR)) {
335*0b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the ReadySet\n");
336*0b57cec5SDimitry Andric     ReadySet.push_back(IR);
337*0b57cec5SDimitry Andric   }
338*0b57cec5SDimitry Andric 
339*0b57cec5SDimitry Andric   return true;
340*0b57cec5SDimitry Andric }
341*0b57cec5SDimitry Andric 
342*0b57cec5SDimitry Andric } // namespace mca
343*0b57cec5SDimitry Andric } // namespace llvm
344