LLVM  8.0.1
Scheduler.cpp
Go to the documentation of this file.
1 //===--------------------- Scheduler.cpp ------------------------*- 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 //
10 // A scheduler for processor resource units and processor resource groups.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/Support/Debug.h"
17 
18 namespace llvm {
19 namespace mca {
20 
21 #define DEBUG_TYPE "llvm-mca"
22 
23 void Scheduler::initializeStrategy(std::unique_ptr<SchedulerStrategy> S) {
24  // Ensure we have a valid (non-null) strategy object.
25  Strategy = S ? std::move(S) : llvm::make_unique<DefaultSchedulerStrategy>();
26 }
27 
28 // Anchor the vtable of SchedulerStrategy and DefaultSchedulerStrategy.
31 
32 #ifndef NDEBUG
33 void Scheduler::dump() const {
34  dbgs() << "[SCHEDULER]: WaitSet size is: " << WaitSet.size() << '\n';
35  dbgs() << "[SCHEDULER]: ReadySet size is: " << ReadySet.size() << '\n';
36  dbgs() << "[SCHEDULER]: IssuedSet size is: " << IssuedSet.size() << '\n';
37  Resources->dump();
38 }
39 #endif
40 
42  const InstrDesc &Desc = IR.getInstruction()->getDesc();
43 
44  switch (Resources->canBeDispatched(Desc.Buffers)) {
50  break;
51  }
52 
53  // Give lower priority to LSUnit stall events.
54  switch (LSU.isAvailable(IR)) {
61  }
62 
63  llvm_unreachable("Don't know how to process this LSU state result!");
64 }
65 
66 void Scheduler::issueInstructionImpl(
67  InstRef &IR,
68  SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &UsedResources) {
69  Instruction *IS = IR.getInstruction();
70  const InstrDesc &D = IS->getDesc();
71 
72  // Issue the instruction and collect all the consumed resources
73  // into a vector. That vector is then used to notify the listener.
74  Resources->issueInstruction(D, UsedResources);
75 
76  // Notify the instruction that it started executing.
77  // This updates the internal state of each write.
78  IS->execute();
79 
80  if (IS->isExecuting())
81  IssuedSet.emplace_back(IR);
82  else if (IS->isExecuted())
83  LSU.onInstructionExecuted(IR);
84 }
85 
86 // Release the buffered resources and issue the instruction.
88  InstRef &IR,
89  SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &UsedResources,
90  SmallVectorImpl<InstRef> &ReadyInstructions) {
91  const Instruction &Inst = *IR.getInstruction();
92  bool HasDependentUsers = Inst.hasDependentUsers();
93 
94  Resources->releaseBuffers(Inst.getDesc().Buffers);
95  issueInstructionImpl(IR, UsedResources);
96  // Instructions that have been issued during this cycle might have unblocked
97  // other dependent instructions. Dependent instructions may be issued during
98  // this same cycle if operands have ReadAdvance entries. Promote those
99  // instructions to the ReadySet and notify the caller that those are ready.
100  if (HasDependentUsers)
101  promoteToReadySet(ReadyInstructions);
102 }
103 
104 void Scheduler::promoteToReadySet(SmallVectorImpl<InstRef> &Ready) {
105  // Scan the set of waiting instructions and promote them to the
106  // ready queue if operands are all ready.
107  unsigned RemovedElements = 0;
108  for (auto I = WaitSet.begin(), E = WaitSet.end(); I != E;) {
109  InstRef &IR = *I;
110  if (!IR)
111  break;
112 
113  // Check if this instruction is now ready. In case, force
114  // a transition in state using method 'update()'.
115  Instruction &IS = *IR.getInstruction();
116  if (!IS.isReady())
117  IS.update();
118 
119  // Check if there are still unsolved data dependencies.
120  if (!isReady(IR)) {
121  ++I;
122  continue;
123  }
124 
125  Ready.emplace_back(IR);
126  ReadySet.emplace_back(IR);
127 
128  IR.invalidate();
129  ++RemovedElements;
130  std::iter_swap(I, E - RemovedElements);
131  }
132 
133  WaitSet.resize(WaitSet.size() - RemovedElements);
134 }
135 
137  unsigned QueueIndex = ReadySet.size();
138  for (unsigned I = 0, E = ReadySet.size(); I != E; ++I) {
139  const InstRef &IR = ReadySet[I];
140  if (QueueIndex == ReadySet.size() ||
141  Strategy->compare(IR, ReadySet[QueueIndex])) {
142  const InstrDesc &D = IR.getInstruction()->getDesc();
143  if (Resources->canBeIssued(D))
144  QueueIndex = I;
145  }
146  }
147 
148  if (QueueIndex == ReadySet.size())
149  return InstRef();
150 
151  // We found an instruction to issue.
152  InstRef IR = ReadySet[QueueIndex];
153  std::swap(ReadySet[QueueIndex], ReadySet[ReadySet.size() - 1]);
154  ReadySet.pop_back();
155  return IR;
156 }
157 
158 void Scheduler::updateIssuedSet(SmallVectorImpl<InstRef> &Executed) {
159  unsigned RemovedElements = 0;
160  for (auto I = IssuedSet.begin(), E = IssuedSet.end(); I != E;) {
161  InstRef &IR = *I;
162  if (!IR)
163  break;
164  Instruction &IS = *IR.getInstruction();
165  if (!IS.isExecuted()) {
166  LLVM_DEBUG(dbgs() << "[SCHEDULER]: Instruction #" << IR
167  << " is still executing.\n");
168  ++I;
169  continue;
170  }
171 
172  // Instruction IR has completed execution.
173  LSU.onInstructionExecuted(IR);
174  Executed.emplace_back(IR);
175  ++RemovedElements;
176  IR.invalidate();
177  std::iter_swap(I, E - RemovedElements);
178  }
179 
180  IssuedSet.resize(IssuedSet.size() - RemovedElements);
181 }
182 
184  SmallVectorImpl<InstRef> &Executed,
185  SmallVectorImpl<InstRef> &Ready) {
186  // Release consumed resources.
187  Resources->cycleEvent(Freed);
188 
189  // Propagate the cycle event to the 'Issued' and 'Wait' sets.
190  for (InstRef &IR : IssuedSet)
191  IR.getInstruction()->cycleEvent();
192 
193  updateIssuedSet(Executed);
194 
195  for (InstRef &IR : WaitSet)
196  IR.getInstruction()->cycleEvent();
197 
198  promoteToReadySet(Ready);
199 }
200 
202  const InstrDesc &Desc = IR.getInstruction()->getDesc();
203  if (Desc.isZeroLatency())
204  return true;
205  // Instructions that use an in-order dispatch/issue processor resource must be
206  // issued immediately to the pipeline(s). Any other in-order buffered
207  // resources (i.e. BufferSize=1) is consumed.
208  return Desc.MustIssueImmediately;
209 }
210 
211 void Scheduler::dispatch(const InstRef &IR) {
212  const InstrDesc &Desc = IR.getInstruction()->getDesc();
213  Resources->reserveBuffers(Desc.Buffers);
214 
215  // If necessary, reserve queue entries in the load-store unit (LSU).
216  bool IsMemOp = Desc.MayLoad || Desc.MayStore;
217  if (IsMemOp)
218  LSU.dispatch(IR);
219 
220  if (!isReady(IR)) {
221  LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the WaitSet\n");
222  WaitSet.push_back(IR);
223  return;
224  }
225 
226  // Don't add a zero-latency instruction to the Ready queue.
227  // A zero-latency instruction doesn't consume any scheduler resources. That is
228  // because it doesn't need to be executed, and it is often removed at register
229  // renaming stage. For example, register-register moves are often optimized at
230  // register renaming stage by simply updating register aliases. On some
231  // targets, zero-idiom instructions (for example: a xor that clears the value
232  // of a register) are treated specially, and are often eliminated at register
233  // renaming stage.
234  if (!mustIssueImmediately(IR)) {
235  LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the ReadySet\n");
236  ReadySet.push_back(IR);
237  }
238 }
239 
240 bool Scheduler::isReady(const InstRef &IR) const {
241  const InstrDesc &Desc = IR.getInstruction()->getDesc();
242  bool IsMemOp = Desc.MayLoad || Desc.MayStore;
243  return IR.getInstruction()->isReady() && (!IsMemOp || LSU.isReady(IR));
244 }
245 
246 } // namespace mca
247 } // namespace llvm
void dump() const
Definition: Scheduler.cpp:33
bool isReady(const InstRef &IR) const
Returns true if IR is ready to be executed by the underlying pipelines.
Definition: Scheduler.cpp:240
Instruction * getInstruction()
Definition: Instruction.h:488
Status isAvailable(const InstRef &IR) const
Definition: LSUnit.cpp:88
virtual bool isReady(const InstRef &IR) const
Definition: LSUnit.cpp:97
Status isAvailable(const InstRef &IR) const
Check if the instruction in &#39;IR&#39; can be dispatched and returns an answer in the form of a Status valu...
Definition: Scheduler.cpp:41
An instruction propagated through the simulated instruction pipeline.
Definition: Instruction.h:407
bool hasDependentUsers() const
Definition: Instruction.h:386
void cycleEvent(SmallVectorImpl< ResourceRef > &Freed, SmallVectorImpl< InstRef > &Ready, SmallVectorImpl< InstRef > &Executed)
This routine notifies the Scheduler that a new cycle just started.
Definition: Scheduler.cpp:183
This class represents lattice values for constants.
Definition: AllocatorList.h:24
SmallVector< uint64_t, 4 > Buffers
Definition: Instruction.h:331
InstRef select()
Select the next instruction to issue from the ReadySet.
Definition: Scheduler.cpp:136
void onInstructionExecuted(const InstRef &IR)
Definition: LSUnit.cpp:155
An InstRef contains both a SourceMgr index and Instruction pair.
Definition: Instruction.h:478
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
const InstrDesc & getDesc() const
Definition: Instruction.h:382
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void invalidate()
Invalidate this reference.
Definition: Instruction.h:495
void issueInstruction(InstRef &IR, SmallVectorImpl< std::pair< ResourceRef, ResourceCycles >> &Used, SmallVectorImpl< InstRef > &Ready)
Issue an instruction and populates a vector of used pipeline resources, and a vector of instructions ...
Definition: Scheduler.cpp:87
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:941
bool isReady() const
Definition: Instruction.h:453
An instruction descriptor.
Definition: Instruction.h:322
bool mustIssueImmediately(const InstRef &IR) const
Returns true if IR has to be issued immediately, or if IR is a zero latency instruction.
Definition: Scheduler.cpp:201
void emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:652
bool isExecuting() const
Definition: Instruction.h:454
#define I(x, y, z)
Definition: MD5.cpp:58
bool isZeroLatency() const
Definition: Instruction.h:348
void dispatch(const InstRef &IR)
Definition: LSUnit.cpp:69
bool isExecuted() const
Definition: Instruction.h:455
A scheduler for Processor Resource Units and Processor Resource Groups.
#define LLVM_DEBUG(X)
Definition: Debug.h:123
Statically lint checks LLVM IR
Definition: Lint.cpp:193
void dispatch(const InstRef &IR)
Reserves buffer and LSUnit queue resources that are necessary to issue this instruction.
Definition: Scheduler.cpp:211