llvm.org GIT mirror llvm / 3055634
[MCA] Notify event listeners when instructions transition to the Pending state. NFCI git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359983 91177308-0d34-0410-b5e6-96231b3b80d8 Andrea Di Biagio 1 year, 5 months ago
5 changed file(s) with 49 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
3838 // Events generated by the Retire Control Unit.
3939 Retired,
4040 // Events generated by the Scheduler.
41 Pending,
4142 Ready,
4243 Issued,
4344 Executed,
148148 bool promoteToReadySet(SmallVectorImpl &Ready);
149149
150150 // Try to promote instructions from the WaitSet to the PendingSet.
151 // Add promoted instructions to the 'Pending' vector in input.
151152 // Returns true if at least one instruction was promoted.
152 bool promoteToPendingSet();
153 bool promoteToPendingSet(SmallVectorImpl &Pending);
153154
154155 public:
155156 Scheduler(const MCSchedModel &Model, LSUnit &Lsu)
197198 void issueInstruction(
198199 InstRef &IR,
199200 SmallVectorImpl> &Used,
201 SmallVectorImpl &Pending,
200202 SmallVectorImpl &Ready);
201203
202204 /// Returns true if IR has to be issued immediately, or if IR is a zero
210212 /// have changed in state, and that are now available to new instructions.
211213 /// Instructions executed are added to vector Executed, while vector Ready is
212214 /// populated with instructions that have become ready in this new cycle.
215 /// Vector Pending is popluated by instructions that have transitioned through
216 /// the pending stat during this cycle. The Pending and Ready sets may not be
217 /// disjoint. An instruction is allowed to transition from the WAIT state to
218 /// the READY state (going through the PENDING state) within a single cycle.
219 /// That means, instructions may appear in both the Pending and Ready set.
213220 void cycleEvent(SmallVectorImpl &Freed,
214 SmallVectorImpl &Ready,
215 SmallVectorImpl &Executed);
221 SmallVectorImpl &Executed,
222 SmallVectorImpl &Pending,
223 SmallVectorImpl &Ready);
216224
217225 /// Convert a resource mask into a valid llvm processor resource identifier.
218226 unsigned getResourceID(uint64_t Mask) const {
7575 const InstRef &IR,
7676 MutableArrayRef> Used) const;
7777 void notifyInstructionExecuted(const InstRef &IR) const;
78 void notifyInstructionPending(const InstRef &IR) const;
7879 void notifyInstructionReady(const InstRef &IR) const;
7980 void notifyResourceAvailable(const ResourceRef &RR) const;
8081
9191 void Scheduler::issueInstruction(
9292 InstRef &IR,
9393 SmallVectorImpl> &UsedResources,
94 SmallVectorImpl &PendingInstructions,
9495 SmallVectorImpl &ReadyInstructions) {
9596 const Instruction &Inst = *IR.getInstruction();
9697 bool HasDependentUsers = Inst.hasDependentUsers();
101102 // other dependent instructions. Dependent instructions may be issued during
102103 // this same cycle if operands have ReadAdvance entries. Promote those
103104 // instructions to the ReadySet and notify the caller that those are ready.
104 if (HasDependentUsers && promoteToPendingSet())
105 if (HasDependentUsers && promoteToPendingSet(PendingInstructions))
105106 promoteToReadySet(ReadyInstructions);
106107 }
107108
146147 return PromotedElements;
147148 }
148149
149 bool Scheduler::promoteToPendingSet() {
150 bool Scheduler::promoteToPendingSet(SmallVectorImpl &Pending) {
150151 // Scan the set of waiting instructions and promote them to the
151152 // pending set if operands are all ready.
152153 unsigned RemovedElements = 0;
165166 LLVM_DEBUG(dbgs() << "[SCHEDULER]: Instruction #" << IR
166167 << " promoted to the PENDING set.\n");
167168
169 Pending.emplace_back(IR);
168170 PendingSet.emplace_back(IR);
169171
170172 IR.invalidate();
250252
251253 void Scheduler::cycleEvent(SmallVectorImpl &Freed,
252254 SmallVectorImpl &Executed,
255 SmallVectorImpl &Pending,
253256 SmallVectorImpl &Ready) {
254257 // Release consumed resources.
255258 Resources->cycleEvent(Freed);
264267 for (InstRef &IR : WaitSet)
265268 IR.getInstruction()->cycleEvent();
266269
267 promoteToPendingSet();
270 promoteToPendingSet(Pending);
268271 promoteToReadySet(Ready);
269272
270273 NumDispatchedToThePendingSet = 0;
298301 return false;
299302 }
300303
304 // Memory operations that are not in a ready state are initially assigned to
305 // the WaitSet.
301306 if (!IS.isReady() ||
302307 (IS.isMemOp() && LSU.isReady(IR) != IR.getSourceIndex())) {
303308 LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the WaitSet\n");
5151
5252 Error ExecuteStage::issueInstruction(InstRef &IR) {
5353 SmallVector, 4> Used;
54 SmallVector Pending;
5455 SmallVector Ready;
55 HWS.issueInstruction(IR, Used, Ready);
56
57 HWS.issueInstruction(IR, Used, Pending, Ready);
5658 NumIssuedOpcodes += IR.getInstruction()->getDesc().NumMicroOps;
5759
5860 notifyReservedOrReleasedBuffers(IR, /* Reserved */ false);
6567 return S;
6668 }
6769
70 for (const InstRef &I : Pending)
71 notifyInstructionPending(I);
72
6873 for (const InstRef &I : Ready)
6974 notifyInstructionReady(I);
7075 return ErrorSuccess();
8691 Error ExecuteStage::cycleStart() {
8792 SmallVector Freed;
8893 SmallVector Executed;
94 SmallVector Pending;
8995 SmallVector Ready;
9096
91 HWS.cycleEvent(Freed, Executed, Ready);
97 HWS.cycleEvent(Freed, Executed, Pending, Ready);
9298 NumDispatchedOpcodes = 0;
9399 NumIssuedOpcodes = 0;
94100
101107 if (Error S = moveToTheNextStage(IR))
102108 return S;
103109 }
110
111 for (const InstRef &IR : Pending)
112 notifyInstructionPending(IR);
104113
105114 for (const InstRef &IR : Ready)
106115 notifyInstructionReady(IR);
125134 << format_hex(Mask, 16) << '\n');
126135 HWPressureEvent Ev(HWPressureEvent::RESOURCES, Insts, Mask);
127136 notifyEvent(Ev);
128 return ErrorSuccess();
129137 }
130138
131139 SmallVector RegDeps;
164172 #ifndef NDEBUG
165173 verifyInstructionEliminated(IR);
166174 #endif
175 notifyInstructionPending(IR);
167176 notifyInstructionReady(IR);
168177 notifyInstructionIssued(IR, {});
169178 IR.getInstruction()->forceExecuted();
188197 // be released after MCIS is issued, and all the ResourceCycles for those
189198 // units have been consumed.
190199 bool IsReadyInstruction = HWS.dispatch(IR);
191 NumDispatchedOpcodes += IR.getInstruction()->getDesc().NumMicroOps;
200 const Instruction &Inst = *IR.getInstruction();
201 NumDispatchedOpcodes += Inst.getDesc().NumMicroOps;
192202 notifyReservedOrReleasedBuffers(IR, /* Reserved */ true);
193 if (!IsReadyInstruction)
194 return ErrorSuccess();
203
204 if (!IsReadyInstruction) {
205 if (Inst.isPending())
206 notifyInstructionPending(IR);
207 return ErrorSuccess();
208 }
209
210 notifyInstructionPending(IR);
195211
196212 // If we did not return early, then the scheduler is ready for execution.
197213 notifyInstructionReady(IR);
209225 LLVM_DEBUG(dbgs() << "[E] Instruction Executed: #" << IR << '\n');
210226 notifyEvent(
211227 HWInstructionEvent(HWInstructionEvent::Executed, IR));
228 }
229
230 void ExecuteStage::notifyInstructionPending(const InstRef &IR) const {
231 LLVM_DEBUG(dbgs() << "[E] Instruction Pending: #" << IR << '\n');
232 notifyEvent(
233 HWInstructionEvent(HWInstructionEvent::Pending, IR));
212234 }
213235
214236 void ExecuteStage::notifyInstructionReady(const InstRef &IR) const {