LLVM  8.0.1
ExecuteStage.cpp
Go to the documentation of this file.
1 //===---------------------- ExecuteStage.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 /// \file
10 ///
11 /// This file defines the execution stage of an instruction pipeline.
12 ///
13 /// The ExecuteStage is responsible for managing the hardware scheduler
14 /// and issuing notifications that an instruction has been executed.
15 ///
16 //===----------------------------------------------------------------------===//
17 
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/Support/Debug.h"
21 
22 #define DEBUG_TYPE "llvm-mca"
23 
24 namespace llvm {
25 namespace mca {
26 
28  switch (Status) {
38  return HWStallEvent::Invalid;
39  }
40 
41  llvm_unreachable("Don't know how to process this StallKind!");
42 }
43 
44 bool ExecuteStage::isAvailable(const InstRef &IR) const {
45  if (Scheduler::Status S = HWS.isAvailable(IR)) {
47  notifyEvent<HWStallEvent>(HWStallEvent(ET, IR));
48  return false;
49  }
50 
51  return true;
52 }
53 
54 Error ExecuteStage::issueInstruction(InstRef &IR) {
57  HWS.issueInstruction(IR, Used, Ready);
58 
59  notifyReservedOrReleasedBuffers(IR, /* Reserved */ false);
60 
61  notifyInstructionIssued(IR, Used);
62  if (IR.getInstruction()->isExecuted()) {
64  // FIXME: add a buffer of executed instructions.
65  if (Error S = moveToTheNextStage(IR))
66  return S;
67  }
68 
69  for (const InstRef &I : Ready)
71  return ErrorSuccess();
72 }
73 
74 Error ExecuteStage::issueReadyInstructions() {
75  InstRef IR = HWS.select();
76  while (IR) {
77  if (Error Err = issueInstruction(IR))
78  return Err;
79 
80  // Select the next instruction to issue.
81  IR = HWS.select();
82  }
83 
84  return ErrorSuccess();
85 }
86 
89  SmallVector<InstRef, 4> Executed;
91 
92  HWS.cycleEvent(Freed, Executed, Ready);
93 
94  for (const ResourceRef &RR : Freed)
96 
97  for (InstRef &IR : Executed) {
99  // FIXME: add a buffer of executed instructions.
100  if (Error S = moveToTheNextStage(IR))
101  return S;
102  }
103 
104  for (const InstRef &IR : Ready)
106 
107  return issueReadyInstructions();
108 }
109 
110 #ifndef NDEBUG
111 static void verifyInstructionEliminated(const InstRef &IR) {
112  const Instruction &Inst = *IR.getInstruction();
113  assert(Inst.isEliminated() && "Instruction was not eliminated!");
114  assert(Inst.isReady() && "Instruction in an inconsistent state!");
115 
116  // Ensure that instructions eliminated at register renaming stage are in a
117  // consistent state.
118  const InstrDesc &Desc = Inst.getDesc();
119  assert(!Desc.MayLoad && !Desc.MayStore && "Cannot eliminate a memory op!");
120 }
121 #endif
122 
123 Error ExecuteStage::handleInstructionEliminated(InstRef &IR) {
124 #ifndef NDEBUG
126 #endif
128  notifyInstructionIssued(IR, {});
131  return moveToTheNextStage(IR);
132 }
133 
134 // Schedule the instruction for execution on the hardware.
136  assert(isAvailable(IR) && "Scheduler is not available!");
137 
138 #ifndef NDEBUG
139  // Ensure that the HWS has not stored this instruction in its queues.
140  HWS.sanityCheck(IR);
141 #endif
142 
143  if (IR.getInstruction()->isEliminated())
144  return handleInstructionEliminated(IR);
145 
146  // Reserve a slot in each buffered resource. Also, mark units with
147  // BufferSize=0 as reserved. Resources with a buffer size of zero will only
148  // be released after MCIS is issued, and all the ResourceCycles for those
149  // units have been consumed.
150  HWS.dispatch(IR);
151  notifyReservedOrReleasedBuffers(IR, /* Reserved */ true);
152  if (!HWS.isReady(IR))
153  return ErrorSuccess();
154 
155  // If we did not return early, then the scheduler is ready for execution.
157 
158  // If we cannot issue immediately, the HWS will add IR to its ready queue for
159  // execution later, so we must return early here.
160  if (!HWS.mustIssueImmediately(IR))
161  return ErrorSuccess();
162 
163  // Issue IR to the underlying pipelines.
164  return issueInstruction(IR);
165 }
166 
168  LLVM_DEBUG(dbgs() << "[E] Instruction Executed: #" << IR << '\n');
169  notifyEvent<HWInstructionEvent>(
171 }
172 
174  LLVM_DEBUG(dbgs() << "[E] Instruction Ready: #" << IR << '\n');
175  notifyEvent<HWInstructionEvent>(
177 }
178 
180  LLVM_DEBUG(dbgs() << "[E] Resource Available: [" << RR.first << '.'
181  << RR.second << "]\n");
182  for (HWEventListener *Listener : getListeners())
183  Listener->onResourceAvailable(RR);
184 }
185 
187  const InstRef &IR,
188  MutableArrayRef<std::pair<ResourceRef, ResourceCycles>> Used) const {
189  LLVM_DEBUG({
190  dbgs() << "[E] Instruction Issued: #" << IR << '\n';
191  for (const std::pair<ResourceRef, ResourceCycles> &Resource : Used) {
192  dbgs() << "[E] Resource Used: [" << Resource.first.first << '.'
193  << Resource.first.second << "], ";
194  dbgs() << "cycles: " << Resource.second << '\n';
195  }
196  });
197 
198  // Replace resource masks with valid resource processor IDs.
199  for (std::pair<ResourceRef, ResourceCycles> &Use : Used)
200  Use.first.first = HWS.getResourceID(Use.first.first);
201 
202  notifyEvent<HWInstructionEvent>(HWInstructionIssuedEvent(IR, Used));
203 }
204 
206  bool Reserved) const {
207  const InstrDesc &Desc = IR.getInstruction()->getDesc();
208  if (Desc.Buffers.empty())
209  return;
210 
211  SmallVector<unsigned, 4> BufferIDs(Desc.Buffers.begin(), Desc.Buffers.end());
212  std::transform(Desc.Buffers.begin(), Desc.Buffers.end(), BufferIDs.begin(),
213  [&](uint64_t Op) { return HWS.getResourceID(Op); });
214  if (Reserved) {
215  for (HWEventListener *Listener : getListeners())
216  Listener->onReservedBuffers(IR, BufferIDs);
217  return;
218  }
219 
220  for (HWEventListener *Listener : getListeners())
221  Listener->onReleasedBuffers(IR, BufferIDs);
222 }
223 
224 } // namespace mca
225 } // namespace llvm
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
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
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
void sanityCheck(const InstRef &IR) const
Definition: Scheduler.h:204
SmallVector< uint64_t, 4 > Buffers
Definition: Instruction.h:331
const std::set< HWEventListener * > & getListeners() const
Definition: Stage.h:36
Subclass of Error for the sole purpose of identifying the success path in the type system...
Definition: Error.h:325
void notifyInstructionReady(const InstRef &IR) const
InstRef select()
Select the next instruction to issue from the ReadySet.
Definition: Scheduler.cpp:136
bool isAvailable(const InstRef &IR) const override
Returns true if it can execute IR during this cycle.
An InstRef contains both a SourceMgr index and Instruction pair.
Definition: Instruction.h:478
Error cycleStart() override
Called once at the start of each cycle.
HWStallEvent::GenericEventType toHWStallEventType(Scheduler::Status Status)
void notifyResourceAvailable(const ResourceRef &RR) const
This file defines the execution stage of a default instruction pipeline.
unsigned getResourceID(uint64_t Mask) const
Convert a resource mask into a valid llvm processor resource identifier.
Definition: Scheduler.h:189
A Use represents the edge between a Value definition and its users.
Definition: Use.h:56
static void verifyInstructionEliminated(const InstRef &IR)
bool isEliminated() const
Definition: Instruction.h:458
void notifyInstructionIssued(const InstRef &IR, MutableArrayRef< std::pair< ResourceRef, ResourceCycles >> Used) const
const InstrDesc & getDesc() const
Definition: Instruction.h:382
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:291
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:129
void notifyReservedOrReleasedBuffers(const InstRef &IR, bool Reserved) const
std::pair< uint64_t, uint64_t > ResourceRef
A resource unit identifier.
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.
void notifyInstructionExecuted(const InstRef &IR) const
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
bool isReady() const
Definition: Instruction.h:453
Error moveToTheNextStage(InstRef &IR)
Called when an instruction is ready to move the next pipeline stage.
Definition: Stage.h:71
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
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:133
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:56
#define I(x, y, z)
Definition: MD5.cpp:58
OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere...
Definition: STLExtras.h:1268
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
bool isExecuted() const
Definition: Instruction.h:455
Error execute(InstRef &IR) override
The primary action that this stage performs on instruction IR.
#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