blob: 2c0227d33a9945e3a45874711198c3cb784f49dc [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///
Matt Davis6aa5dcd2018-05-01 23:04:01 +000011/// This file implements methods declared by class RegisterFile and
12/// DispatchUnit.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000013///
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) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000179 LLVM_DEBUG(dbgs() << "Found a dependent use of RegID=" << RegID << '\n');
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000180 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()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000187 LLVM_DEBUG(dbgs() << "Found a dependent use of subReg " << *I
188 << " (part of " << RegID << ")\n");
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000189 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
Matt Davis21a8d322018-05-07 18:29:15 +0000255void DispatchUnit::notifyInstructionDispatched(const InstRef &IR,
Andrea Di Biagio94fafdf2018-03-24 16:05:36 +0000256 ArrayRef<unsigned> UsedRegs) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000257 LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: " << IR << '\n');
Matt Davis21a8d322018-05-07 18:29:15 +0000258 Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(IR, UsedRegs));
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000259}
260
Matt Davis21a8d322018-05-07 18:29:15 +0000261void DispatchUnit::notifyInstructionRetired(const InstRef &IR) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000262 LLVM_DEBUG(dbgs() << "[E] Instruction Retired: " << IR << '\n');
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000263 SmallVector<unsigned, 4> FreedRegs(RAT->getNumRegisterFiles());
Matt Davis21a8d322018-05-07 18:29:15 +0000264 for (const std::unique_ptr<WriteState> &WS : IR.getInstruction()->getDefs())
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000265 RAT->invalidateRegisterMapping(*WS.get(), FreedRegs);
Matt Davis21a8d322018-05-07 18:29:15 +0000266 Owner->notifyInstructionEvent(HWInstructionRetiredEvent(IR, FreedRegs));
267 Owner->eraseInstruction(IR);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000268}
269
Matt Davis21a8d322018-05-07 18:29:15 +0000270bool DispatchUnit::checkRAT(const InstRef &IR) {
Andrea Di Biagio9ecb4012018-03-27 15:23:41 +0000271 SmallVector<unsigned, 4> RegDefs;
Matt Davis21a8d322018-05-07 18:29:15 +0000272 for (const std::unique_ptr<WriteState> &RegDef :
273 IR.getInstruction()->getDefs())
Andrea Di Biagio9ecb4012018-03-27 15:23:41 +0000274 RegDefs.emplace_back(RegDef->getRegisterID());
275
276 unsigned RegisterMask = RAT->isAvailable(RegDefs);
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000277 // A mask with all zeroes means: register files are available.
278 if (RegisterMask) {
Matt Davis21a8d322018-05-07 18:29:15 +0000279 Owner->notifyStallEvent(HWStallEvent(HWStallEvent::RegisterFileStall, IR));
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000280 return false;
281 }
282
283 return true;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000284}
285
Matt Davis21a8d322018-05-07 18:29:15 +0000286bool DispatchUnit::checkRCU(const InstRef &IR) {
287 const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000288 if (RCU->isAvailable(NumMicroOps))
289 return true;
Andrea Di Biagio91ab2ee2018-03-19 13:23:07 +0000290 Owner->notifyStallEvent(
Matt Davis21a8d322018-05-07 18:29:15 +0000291 HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000292 return false;
293}
294
Matt Davis21a8d322018-05-07 18:29:15 +0000295bool DispatchUnit::checkScheduler(const InstRef &IR) {
296 return SC->canBeDispatched(IR);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000297}
298
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000299void DispatchUnit::updateRAWDependencies(ReadState &RS,
300 const MCSubtargetInfo &STI) {
301 SmallVector<WriteState *, 4> DependentWrites;
302
303 collectWrites(DependentWrites, RS.getRegisterID());
304 RS.setDependentWrites(DependentWrites.size());
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000305 LLVM_DEBUG(dbgs() << "Found " << DependentWrites.size()
306 << " dependent writes\n");
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000307 // We know that this read depends on all the writes in DependentWrites.
308 // For each write, check if we have ReadAdvance information, and use it
309 // to figure out in how many cycles this read becomes available.
310 const ReadDescriptor &RD = RS.getDescriptor();
311 if (!RD.HasReadAdvanceEntries) {
312 for (WriteState *WS : DependentWrites)
313 WS->addUser(&RS, /* ReadAdvance */ 0);
314 return;
315 }
316
317 const MCSchedModel &SM = STI.getSchedModel();
318 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
319 for (WriteState *WS : DependentWrites) {
320 unsigned WriteResID = WS->getWriteResourceID();
Andrea Di Biagio0a837ef2018-03-29 14:26:56 +0000321 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000322 WS->addUser(&RS, ReadAdvance);
323 }
324 // Prepare the set for another round.
325 DependentWrites.clear();
326}
327
Matt Davis21a8d322018-05-07 18:29:15 +0000328void DispatchUnit::dispatch(InstRef IR, const MCSubtargetInfo &STI) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000329 assert(!CarryOver && "Cannot dispatch another instruction!");
Matt Davis21a8d322018-05-07 18:29:15 +0000330 Instruction &IS = *IR.getInstruction();
331 const InstrDesc &Desc = IS.getDesc();
332 const unsigned NumMicroOps = Desc.NumMicroOps;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000333 if (NumMicroOps > DispatchWidth) {
334 assert(AvailableEntries == DispatchWidth);
335 AvailableEntries = 0;
336 CarryOver = NumMicroOps - DispatchWidth;
337 } else {
338 assert(AvailableEntries >= NumMicroOps);
339 AvailableEntries -= NumMicroOps;
340 }
341
Andrea Di Biagiodb66efc2018-04-25 09:38:58 +0000342 // Update RAW dependencies if this instruction is not a zero-latency
343 // instruction. The assumption is that a zero-latency instruction doesn't
344 // require to be issued to the scheduler for execution. More importantly, it
345 // doesn't have to wait on the register input operands.
Andrea Di Biagioe047d352018-04-30 15:55:04 +0000346 if (Desc.MaxLatency || !Desc.Resources.empty())
Matt Davis21a8d322018-05-07 18:29:15 +0000347 for (std::unique_ptr<ReadState> &RS : IS.getUses())
Andrea Di Biagiodb66efc2018-04-25 09:38:58 +0000348 updateRAWDependencies(*RS, STI);
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000349
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000350 // Allocate new mappings.
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000351 SmallVector<unsigned, 4> RegisterFiles(RAT->getNumRegisterFiles());
Matt Davis21a8d322018-05-07 18:29:15 +0000352 for (std::unique_ptr<WriteState> &WS : IS.getDefs())
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000353 RAT->addRegisterMapping(*WS, RegisterFiles);
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000354
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000355 // Reserve slots in the RCU, and notify the instruction that it has been
356 // dispatched to the schedulers for execution.
Matt Davis21a8d322018-05-07 18:29:15 +0000357 IS.dispatch(RCU->reserveSlot(IR, NumMicroOps));
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000358
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000359 // Notify listeners of the "instruction dispatched" event.
Matt Davis21a8d322018-05-07 18:29:15 +0000360 notifyInstructionDispatched(IR, RegisterFiles);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000361
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000362 // Now move the instruction into the scheduler's queue.
363 // The scheduler is responsible for checking if this is a zero-latency
364 // instruction that doesn't consume pipeline/scheduler resources.
Matt Davis21a8d322018-05-07 18:29:15 +0000365 SC->scheduleInstruction(IR);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000366}
367
368#ifndef NDEBUG
369void DispatchUnit::dump() const {
370 RAT->dump();
371 RCU->dump();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000372}
373#endif
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000374} // namespace mca