blob: 9bccca7dd36fe12e19770164d8793fae25be26c8 [file] [log] [blame]
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +00001//===--------------------- Dispatch.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 implements methods declared by class RegisterFile, DispatchUnit
12/// and RetireControlUnit.
13///
14//===----------------------------------------------------------------------===//
15
16#include "Dispatch.h"
17#include "Backend.h"
Clement Courbet844f22d2018-03-13 13:11:01 +000018#include "HWEventListener.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000019#include "Scheduler.h"
20#include "llvm/Support/Debug.h"
21
22using namespace llvm;
23
24#define DEBUG_TYPE "llvm-mca"
25
26namespace mca {
27
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +000028void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
29 // Create a default register file that "sees" all the machine registers
30 // declared by the target. The number of physical registers in the default
31 // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
32 // means: this register file has an unbounded number of physical registers.
33 addRegisterFile({} /* all registers */, NumRegs);
34 if (!SM.hasExtraProcessorInfo())
35 return;
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000036
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +000037 // For each user defined register file, allocate a RegisterMappingTracker
38 // object. The size of every register file, as well as the mapping between
39 // register files and register classes is specified via tablegen.
40 const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
41 for (unsigned I = 0, E = Info.NumRegisterFiles; I < E; ++I) {
42 const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
43 // Skip invalid register files with zero physical registers.
44 unsigned Length = RF.NumRegisterCostEntries;
45 if (!RF.NumPhysRegs)
46 continue;
47 // The cost of a register definition is equivalent to the number of
48 // physical registers that are allocated at register renaming stage.
49 const MCRegisterCostEntry *FirstElt =
50 &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
51 addRegisterFile(ArrayRef<MCRegisterCostEntry>(FirstElt, Length),
52 RF.NumPhysRegs);
53 }
54}
55
56void RegisterFile::addRegisterFile(ArrayRef<MCRegisterCostEntry> Entries,
57 unsigned NumPhysRegs) {
58 // A default register file is always allocated at index #0. That register file
59 // is mainly used to count the total number of mappings created by all
60 // register files at runtime. Users can limit the number of available physical
61 // registers in register file #0 through the command line flag
62 // `-register-file-size`.
63 unsigned RegisterFileIndex = RegisterFiles.size();
64 RegisterFiles.emplace_back(NumPhysRegs);
65
66 // Special case where there is no register class identifier in the set.
67 // An empty set of register classes means: this register file contains all
68 // the physical registers specified by the target.
69 if (Entries.empty()) {
Andrea Di Biagio641cca32018-04-25 10:27:30 +000070 for (std::pair<WriteState *, IndexPlusCostPairTy> &Mapping :
71 RegisterMappings)
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +000072 Mapping.second = std::make_pair(RegisterFileIndex, 1U);
73 return;
74 }
75
76 // Now update the cost of individual registers.
77 for (const MCRegisterCostEntry &RCE : Entries) {
78 const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
79 for (const MCPhysReg Reg : RC) {
80 IndexPlusCostPairTy &Entry = RegisterMappings[Reg].second;
81 if (Entry.first) {
82 // The only register file that is allowed to overlap is the default
83 // register file at index #0. The analysis is inaccurate if register
84 // files overlap.
85 errs() << "warning: register " << MRI.getName(Reg)
86 << " defined in multiple register files.";
87 }
88 Entry.first = RegisterFileIndex;
89 Entry.second = RCE.Cost;
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000090 }
91 }
92}
93
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +000094void RegisterFile::createNewMappings(IndexPlusCostPairTy Entry,
Andrea Di Biagio12ef5262018-03-21 18:11:05 +000095 MutableArrayRef<unsigned> UsedPhysRegs) {
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +000096 unsigned RegisterFileIndex = Entry.first;
97 unsigned Cost = Entry.second;
98 if (RegisterFileIndex) {
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000099 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000100 RMT.NumUsedMappings += Cost;
101 UsedPhysRegs[RegisterFileIndex] += Cost;
102 }
103
104 // Now update the default register mapping tracker.
105 RegisterFiles[0].NumUsedMappings += Cost;
106 UsedPhysRegs[0] += Cost;
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000107}
108
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000109void RegisterFile::removeMappings(IndexPlusCostPairTy Entry,
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000110 MutableArrayRef<unsigned> FreedPhysRegs) {
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000111 unsigned RegisterFileIndex = Entry.first;
112 unsigned Cost = Entry.second;
113 if (RegisterFileIndex) {
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000114 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000115 RMT.NumUsedMappings -= Cost;
116 FreedPhysRegs[RegisterFileIndex] += Cost;
117 }
118
119 // Now update the default register mapping tracker.
120 RegisterFiles[0].NumUsedMappings -= Cost;
121 FreedPhysRegs[0] += Cost;
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000122}
123
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000124void RegisterFile::addRegisterMapping(WriteState &WS,
125 MutableArrayRef<unsigned> UsedPhysRegs) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000126 unsigned RegID = WS.getRegisterID();
127 assert(RegID && "Adding an invalid register definition?");
128
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000129 RegisterMapping &Mapping = RegisterMappings[RegID];
130 Mapping.first = &WS;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000131 for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000132 RegisterMappings[*I].first = &WS;
133
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000134 createNewMappings(Mapping.second, UsedPhysRegs);
135
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000136 // If this is a partial update, then we are done.
137 if (!WS.fullyUpdatesSuperRegs())
138 return;
139
140 for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I)
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000141 RegisterMappings[*I].first = &WS;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000142}
143
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000144void RegisterFile::invalidateRegisterMapping(
145 const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000146 unsigned RegID = WS.getRegisterID();
147 bool ShouldInvalidateSuperRegs = WS.fullyUpdatesSuperRegs();
148
149 assert(RegID != 0 && "Invalidating an already invalid register?");
150 assert(WS.getCyclesLeft() != -512 &&
151 "Invalidating a write of unknown cycles!");
152 assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000153 RegisterMapping &Mapping = RegisterMappings[RegID];
154 if (!Mapping.first)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000155 return;
156
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000157 removeMappings(Mapping.second, FreedPhysRegs);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000158
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000159 if (Mapping.first == &WS)
160 Mapping.first = nullptr;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000161
162 for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000163 if (RegisterMappings[*I].first == &WS)
164 RegisterMappings[*I].first = nullptr;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000165
166 if (!ShouldInvalidateSuperRegs)
167 return;
168
169 for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I)
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000170 if (RegisterMappings[*I].first == &WS)
171 RegisterMappings[*I].first = nullptr;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000172}
173
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000174void RegisterFile::collectWrites(SmallVectorImpl<WriteState *> &Writes,
175 unsigned RegID) const {
176 assert(RegID && RegID < RegisterMappings.size());
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000177 WriteState *WS = RegisterMappings[RegID].first;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000178 if (WS) {
179 DEBUG(dbgs() << "Found a dependent use of RegID=" << RegID << '\n');
180 Writes.push_back(WS);
181 }
182
183 // Handle potential partial register updates.
184 for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000185 WS = RegisterMappings[*I].first;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000186 if (WS && std::find(Writes.begin(), Writes.end(), WS) == Writes.end()) {
187 DEBUG(dbgs() << "Found a dependent use of subReg " << *I << " (part of "
188 << RegID << ")\n");
189 Writes.push_back(WS);
190 }
191 }
192}
193
Andrea Di Biagio847accd2018-03-20 19:06:34 +0000194unsigned RegisterFile::isAvailable(ArrayRef<unsigned> Regs) const {
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000195 SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000196
197 // Find how many new mappings must be created for each register file.
198 for (const unsigned RegID : Regs) {
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000199 const IndexPlusCostPairTy &Entry = RegisterMappings[RegID].second;
200 if (Entry.first)
201 NumPhysRegs[Entry.first] += Entry.second;
202 NumPhysRegs[0] += Entry.second;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000203 }
204
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000205 unsigned Response = 0;
206 for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000207 unsigned NumRegs = NumPhysRegs[I];
208 if (!NumRegs)
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000209 continue;
210
211 const RegisterMappingTracker &RMT = RegisterFiles[I];
212 if (!RMT.TotalMappings) {
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000213 // The register file has an unbounded number of microarchitectural
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000214 // registers.
215 continue;
216 }
217
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000218 if (RMT.TotalMappings < NumRegs) {
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000219 // The current register file is too small. This may occur if the number of
220 // microarchitectural registers in register file #0 was changed by the
221 // users via flag -reg-file-size. Alternatively, the scheduling model
222 // specified a too small number of registers for this register file.
223 report_fatal_error(
224 "Not enough microarchitectural registers in the register file");
225 }
226
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000227 if (RMT.TotalMappings < (RMT.NumUsedMappings + NumRegs))
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000228 Response |= (1U << I);
229 }
230
231 return Response;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000232}
233
234#ifndef NDEBUG
235void RegisterFile::dump() const {
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000236 for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
237 const RegisterMapping &RM = RegisterMappings[I];
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000238 dbgs() << MRI.getName(I) << ", " << I << ", Map=" << RM.second.first
239 << ", ";
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000240 if (RM.first)
241 RM.first->dump();
242 else
243 dbgs() << "(null)\n";
244 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000245
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000246 for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
247 dbgs() << "Register File #" << I;
248 const RegisterMappingTracker &RMT = RegisterFiles[I];
249 dbgs() << "\n TotalMappings: " << RMT.TotalMappings
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000250 << "\n NumUsedMappings: " << RMT.NumUsedMappings << '\n';
251 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000252}
253#endif
254
Andrea Di Biagioc74ad502018-04-05 15:41:41 +0000255RetireControlUnit::RetireControlUnit(const llvm::MCSchedModel &SM,
256 DispatchUnit *DU)
257 : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
258 AvailableSlots(SM.MicroOpBufferSize), MaxRetirePerCycle(0), Owner(DU) {
259 // Check if the scheduling model provides extra information about the machine
260 // processor. If so, then use that information to set the reorder buffer size
261 // and the maximum number of instructions retired per cycle.
262 if (SM.hasExtraProcessorInfo()) {
263 const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
264 if (EPI.ReorderBufferSize)
265 AvailableSlots = EPI.ReorderBufferSize;
266 MaxRetirePerCycle = EPI.MaxRetirePerCycle;
267 }
268
269 assert(AvailableSlots && "Invalid reorder buffer size!");
270 Queue.resize(AvailableSlots);
271}
272
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000273// Reserves a number of slots, and returns a new token.
274unsigned RetireControlUnit::reserveSlot(unsigned Index, unsigned NumMicroOps) {
275 assert(isAvailable(NumMicroOps));
276 unsigned NormalizedQuantity =
277 std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
278 // Zero latency instructions may have zero mOps. Artificially bump this
279 // value to 1. Although zero latency instructions don't consume scheduler
280 // resources, they still consume one slot in the retire queue.
281 NormalizedQuantity = std::max(NormalizedQuantity, 1U);
282 unsigned TokenID = NextAvailableSlotIdx;
283 Queue[NextAvailableSlotIdx] = {Index, NormalizedQuantity, false};
284 NextAvailableSlotIdx += NormalizedQuantity;
285 NextAvailableSlotIdx %= Queue.size();
286 AvailableSlots -= NormalizedQuantity;
287 return TokenID;
288}
289
Andrea Di Biagio94fafdf2018-03-24 16:05:36 +0000290void DispatchUnit::notifyInstructionDispatched(unsigned Index,
291 ArrayRef<unsigned> UsedRegs) {
Clement Courbet844f22d2018-03-13 13:11:01 +0000292 DEBUG(dbgs() << "[E] Instruction Dispatched: " << Index << '\n');
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000293 Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(Index, UsedRegs));
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000294}
295
296void DispatchUnit::notifyInstructionRetired(unsigned Index) {
Clement Courbet844f22d2018-03-13 13:11:01 +0000297 DEBUG(dbgs() << "[E] Instruction Retired: " << Index << '\n');
Clement Courbet844f22d2018-03-13 13:11:01 +0000298 const Instruction &IS = Owner->getInstruction(Index);
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000299 SmallVector<unsigned, 4> FreedRegs(RAT->getNumRegisterFiles());
Andrea Di Biagio43e8f7d2018-03-21 12:49:07 +0000300 for (const std::unique_ptr<WriteState> &WS : IS.getDefs())
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000301 RAT->invalidateRegisterMapping(*WS.get(), FreedRegs);
Andrea Di Biagio43e8f7d2018-03-21 12:49:07 +0000302
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000303 Owner->notifyInstructionEvent(HWInstructionRetiredEvent(Index, FreedRegs));
Clement Courbet844f22d2018-03-13 13:11:01 +0000304 Owner->eraseInstruction(Index);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000305}
306
307void RetireControlUnit::cycleEvent() {
308 if (isEmpty())
309 return;
310
311 unsigned NumRetired = 0;
312 while (!isEmpty()) {
313 if (MaxRetirePerCycle != 0 && NumRetired == MaxRetirePerCycle)
314 break;
315 RUToken &Current = Queue[CurrentInstructionSlotIdx];
316 assert(Current.NumSlots && "Reserved zero slots?");
317 if (!Current.Executed)
318 break;
319 Owner->notifyInstructionRetired(Current.Index);
320 CurrentInstructionSlotIdx += Current.NumSlots;
321 CurrentInstructionSlotIdx %= Queue.size();
322 AvailableSlots += Current.NumSlots;
323 NumRetired++;
324 }
325}
326
327void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
328 assert(Queue.size() > TokenID);
329 assert(Queue[TokenID].Executed == false && Queue[TokenID].Index != ~0U);
330 Queue[TokenID].Executed = true;
331}
332
333#ifndef NDEBUG
334void RetireControlUnit::dump() const {
335 dbgs() << "Retire Unit: { Total Slots=" << Queue.size()
336 << ", Available Slots=" << AvailableSlots << " }\n";
337}
338#endif
339
Andrea Di Biagio91ab2ee2018-03-19 13:23:07 +0000340bool DispatchUnit::checkRAT(unsigned Index, const Instruction &Instr) {
Andrea Di Biagio9ecb4012018-03-27 15:23:41 +0000341 SmallVector<unsigned, 4> RegDefs;
342 for (const std::unique_ptr<WriteState> &RegDef : Instr.getDefs())
343 RegDefs.emplace_back(RegDef->getRegisterID());
344
345 unsigned RegisterMask = RAT->isAvailable(RegDefs);
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000346 // A mask with all zeroes means: register files are available.
347 if (RegisterMask) {
Andrea Di Biagio91ab2ee2018-03-19 13:23:07 +0000348 Owner->notifyStallEvent(
349 HWStallEvent(HWStallEvent::RegisterFileStall, Index));
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000350 return false;
351 }
352
353 return true;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000354}
355
Andrea Di Biagio91ab2ee2018-03-19 13:23:07 +0000356bool DispatchUnit::checkRCU(unsigned Index, const InstrDesc &Desc) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000357 unsigned NumMicroOps = Desc.NumMicroOps;
358 if (RCU->isAvailable(NumMicroOps))
359 return true;
Andrea Di Biagio91ab2ee2018-03-19 13:23:07 +0000360 Owner->notifyStallEvent(
361 HWStallEvent(HWStallEvent::RetireControlUnitStall, Index));
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000362 return false;
363}
364
Andrea Di Biagio91ab2ee2018-03-19 13:23:07 +0000365bool DispatchUnit::checkScheduler(unsigned Index, const InstrDesc &Desc) {
Andrea Di Biagiob24953b2018-04-11 18:05:23 +0000366 return SC->canBeDispatched(Index, Desc);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000367}
368
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000369void DispatchUnit::updateRAWDependencies(ReadState &RS,
370 const MCSubtargetInfo &STI) {
371 SmallVector<WriteState *, 4> DependentWrites;
372
373 collectWrites(DependentWrites, RS.getRegisterID());
374 RS.setDependentWrites(DependentWrites.size());
375 DEBUG(dbgs() << "Found " << DependentWrites.size() << " dependent writes\n");
376 // We know that this read depends on all the writes in DependentWrites.
377 // For each write, check if we have ReadAdvance information, and use it
378 // to figure out in how many cycles this read becomes available.
379 const ReadDescriptor &RD = RS.getDescriptor();
380 if (!RD.HasReadAdvanceEntries) {
381 for (WriteState *WS : DependentWrites)
382 WS->addUser(&RS, /* ReadAdvance */ 0);
383 return;
384 }
385
386 const MCSchedModel &SM = STI.getSchedModel();
387 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
388 for (WriteState *WS : DependentWrites) {
389 unsigned WriteResID = WS->getWriteResourceID();
Andrea Di Biagio0a837ef2018-03-29 14:26:56 +0000390 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000391 WS->addUser(&RS, ReadAdvance);
392 }
393 // Prepare the set for another round.
394 DependentWrites.clear();
395}
396
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000397void DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
398 const MCSubtargetInfo &STI) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000399 assert(!CarryOver && "Cannot dispatch another instruction!");
400 unsigned NumMicroOps = NewInst->getDesc().NumMicroOps;
401 if (NumMicroOps > DispatchWidth) {
402 assert(AvailableEntries == DispatchWidth);
403 AvailableEntries = 0;
404 CarryOver = NumMicroOps - DispatchWidth;
405 } else {
406 assert(AvailableEntries >= NumMicroOps);
407 AvailableEntries -= NumMicroOps;
408 }
409
Andrea Di Biagiodb66efc2018-04-25 09:38:58 +0000410 // Update RAW dependencies if this instruction is not a zero-latency
411 // instruction. The assumption is that a zero-latency instruction doesn't
412 // require to be issued to the scheduler for execution. More importantly, it
413 // doesn't have to wait on the register input operands.
Andrea Di Biagioe047d352018-04-30 15:55:04 +0000414 const InstrDesc &Desc = NewInst->getDesc();
415 if (Desc.MaxLatency || !Desc.Resources.empty())
Andrea Di Biagiodb66efc2018-04-25 09:38:58 +0000416 for (std::unique_ptr<ReadState> &RS : NewInst->getUses())
417 updateRAWDependencies(*RS, STI);
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000418
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000419 // Allocate new mappings.
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000420 SmallVector<unsigned, 4> RegisterFiles(RAT->getNumRegisterFiles());
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000421 for (std::unique_ptr<WriteState> &WS : NewInst->getDefs())
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000422 RAT->addRegisterMapping(*WS, RegisterFiles);
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000423
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000424 // Reserve slots in the RCU, and notify the instruction that it has been
425 // dispatched to the schedulers for execution.
426 NewInst->dispatch(RCU->reserveSlot(IID, NumMicroOps));
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000427
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000428 // Notify listeners of the "instruction dispatched" event.
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000429 notifyInstructionDispatched(IID, RegisterFiles);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000430
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000431 // Now move the instruction into the scheduler's queue.
432 // The scheduler is responsible for checking if this is a zero-latency
433 // instruction that doesn't consume pipeline/scheduler resources.
Andrea Di Biagio44bfcd22018-03-19 19:09:38 +0000434 SC->scheduleInstruction(IID, *NewInst);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000435}
436
437#ifndef NDEBUG
438void DispatchUnit::dump() const {
439 RAT->dump();
440 RCU->dump();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000441}
442#endif
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000443} // namespace mca