[llvm-shlib] Fix the version naming style of libLLVM for Windows (#85710)
[llvm-project.git] / llvm / lib / MCA / HardwareUnits / RegisterFile.cpp
blob53663a10e8a7d9db83d7edc092af33b87ba2255e
1 //===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file defines a register mapping file class. This class is responsible
11 /// for managing hardware register files and the tracking of data dependencies
12 /// between registers.
13 ///
14 //===----------------------------------------------------------------------===//
16 #include "llvm/MCA/HardwareUnits/RegisterFile.h"
17 #include "llvm/MCA/Instruction.h"
18 #include "llvm/Support/Debug.h"
20 #define DEBUG_TYPE "llvm-mca"
22 namespace llvm {
23 namespace mca {
25 const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
27 WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
28 : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
29 Write(WS) {}
31 void WriteRef::commit() {
32 assert(Write && Write->isExecuted() && "Cannot commit before write back!");
33 RegisterID = Write->getRegisterID();
34 WriteResID = Write->getWriteResourceID();
35 Write = nullptr;
38 void WriteRef::notifyExecuted(unsigned Cycle) {
39 assert(Write && Write->isExecuted() && "Not executed!");
40 WriteBackCycle = Cycle;
43 bool WriteRef::hasKnownWriteBackCycle() const {
44 return isValid() && (!Write || Write->isExecuted());
47 bool WriteRef::isWriteZero() const {
48 assert(isValid() && "Invalid null WriteState found!");
49 return getWriteState()->isWriteZero();
52 unsigned WriteRef::getWriteResourceID() const {
53 if (Write)
54 return Write->getWriteResourceID();
55 return WriteResID;
58 MCPhysReg WriteRef::getRegisterID() const {
59 if (Write)
60 return Write->getRegisterID();
61 return RegisterID;
64 RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,
65 unsigned NumRegs)
66 : MRI(mri),
67 RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),
68 ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {
69 initialize(SM, NumRegs);
72 void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
73 // Create a default register file that "sees" all the machine registers
74 // declared by the target. The number of physical registers in the default
75 // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
76 // means: this register file has an unbounded number of physical registers.
77 RegisterFiles.emplace_back(NumRegs);
78 if (!SM.hasExtraProcessorInfo())
79 return;
81 // For each user defined register file, allocate a RegisterMappingTracker
82 // object. The size of every register file, as well as the mapping between
83 // register files and register classes is specified via tablegen.
84 const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
86 // Skip invalid register file at index 0.
87 for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {
88 const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
89 assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");
91 // The cost of a register definition is equivalent to the number of
92 // physical registers that are allocated at register renaming stage.
93 unsigned Length = RF.NumRegisterCostEntries;
94 const MCRegisterCostEntry *FirstElt =
95 &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
96 addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length));
100 void RegisterFile::cycleStart() {
101 for (RegisterMappingTracker &RMT : RegisterFiles)
102 RMT.NumMoveEliminated = 0;
105 void RegisterFile::onInstructionExecuted(Instruction *IS) {
106 assert(IS && IS->isExecuted() && "Unexpected internal state found!");
107 for (WriteState &WS : IS->getDefs()) {
108 if (WS.isEliminated())
109 return;
111 MCPhysReg RegID = WS.getRegisterID();
113 // This allows InstrPostProcess to remove register Defs
114 // by setting their RegisterID to 0.
115 if (!RegID)
116 continue;
118 assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
119 "The number of cycles should be known at this point!");
120 assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
122 MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
123 if (RenameAs && RenameAs != RegID)
124 RegID = RenameAs;
126 WriteRef &WR = RegisterMappings[RegID].first;
127 if (WR.getWriteState() == &WS)
128 WR.notifyExecuted(CurrentCycle);
130 for (MCPhysReg I : MRI.subregs(RegID)) {
131 WriteRef &OtherWR = RegisterMappings[I].first;
132 if (OtherWR.getWriteState() == &WS)
133 OtherWR.notifyExecuted(CurrentCycle);
136 if (!WS.clearsSuperRegisters())
137 continue;
139 for (MCPhysReg I : MRI.superregs(RegID)) {
140 WriteRef &OtherWR = RegisterMappings[I].first;
141 if (OtherWR.getWriteState() == &WS)
142 OtherWR.notifyExecuted(CurrentCycle);
147 void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,
148 ArrayRef<MCRegisterCostEntry> Entries) {
149 // A default register file is always allocated at index #0. That register file
150 // is mainly used to count the total number of mappings created by all
151 // register files at runtime. Users can limit the number of available physical
152 // registers in register file #0 through the command line flag
153 // `-register-file-size`.
154 unsigned RegisterFileIndex = RegisterFiles.size();
155 RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,
156 RF.AllowZeroMoveEliminationOnly);
158 // Special case where there is no register class identifier in the set.
159 // An empty set of register classes means: this register file contains all
160 // the physical registers specified by the target.
161 // We optimistically assume that a register can be renamed at the cost of a
162 // single physical register. The constructor of RegisterFile ensures that
163 // a RegisterMapping exists for each logical register defined by the Target.
164 if (Entries.empty())
165 return;
167 // Now update the cost of individual registers.
168 for (const MCRegisterCostEntry &RCE : Entries) {
169 const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
170 for (const MCPhysReg Reg : RC) {
171 RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
172 IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
173 if (IPC.first && IPC.first != RegisterFileIndex) {
174 // The only register file that is allowed to overlap is the default
175 // register file at index #0. The analysis is inaccurate if register
176 // files overlap.
177 errs() << "warning: register " << MRI.getName(Reg)
178 << " defined in multiple register files.";
180 IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
181 Entry.RenameAs = Reg;
182 Entry.AllowMoveElimination = RCE.AllowMoveElimination;
184 // Assume the same cost for each sub-register.
185 for (MCPhysReg I : MRI.subregs(Reg)) {
186 RegisterRenamingInfo &OtherEntry = RegisterMappings[I].second;
187 if (!OtherEntry.IndexPlusCost.first &&
188 (!OtherEntry.RenameAs ||
189 MRI.isSuperRegister(I, OtherEntry.RenameAs))) {
190 OtherEntry.IndexPlusCost = IPC;
191 OtherEntry.RenameAs = Reg;
198 void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
199 MutableArrayRef<unsigned> UsedPhysRegs) {
200 unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
201 unsigned Cost = Entry.IndexPlusCost.second;
202 if (RegisterFileIndex) {
203 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
204 RMT.NumUsedPhysRegs += Cost;
205 UsedPhysRegs[RegisterFileIndex] += Cost;
208 // Now update the default register mapping tracker.
209 RegisterFiles[0].NumUsedPhysRegs += Cost;
210 UsedPhysRegs[0] += Cost;
213 void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
214 MutableArrayRef<unsigned> FreedPhysRegs) {
215 unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
216 unsigned Cost = Entry.IndexPlusCost.second;
217 if (RegisterFileIndex) {
218 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
219 RMT.NumUsedPhysRegs -= Cost;
220 FreedPhysRegs[RegisterFileIndex] += Cost;
223 // Now update the default register mapping tracker.
224 RegisterFiles[0].NumUsedPhysRegs -= Cost;
225 FreedPhysRegs[0] += Cost;
228 void RegisterFile::addRegisterWrite(WriteRef Write,
229 MutableArrayRef<unsigned> UsedPhysRegs) {
230 WriteState &WS = *Write.getWriteState();
231 MCPhysReg RegID = WS.getRegisterID();
233 // This allows InstrPostProcess to remove register Defs
234 // by setting their RegisterID to 0.
235 if (!RegID)
236 return;
238 LLVM_DEBUG({
239 dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "
240 << MRI.getName(RegID) << "]\n";
243 // If RenameAs is equal to RegID, then RegID is subject to register renaming
244 // and false dependencies on RegID are all eliminated.
246 // If RenameAs references the invalid register, then we optimistically assume
247 // that it can be renamed. In the absence of tablegen descriptors for register
248 // files, RenameAs is always set to the invalid register ID. In all other
249 // cases, RenameAs must be either equal to RegID, or it must reference a
250 // super-register of RegID.
252 // If RenameAs is a super-register of RegID, then a write to RegID has always
253 // a false dependency on RenameAs. The only exception is for when the write
254 // implicitly clears the upper portion of the underlying register.
255 // If a write clears its super-registers, then it is renamed as `RenameAs`.
256 bool IsWriteZero = WS.isWriteZero();
257 bool IsEliminated = WS.isEliminated();
258 bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
259 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
260 WS.setPRF(RRI.IndexPlusCost.first);
262 if (RRI.RenameAs && RRI.RenameAs != RegID) {
263 RegID = RRI.RenameAs;
264 WriteRef &OtherWrite = RegisterMappings[RegID].first;
266 if (!WS.clearsSuperRegisters()) {
267 // The processor keeps the definition of `RegID` together with register
268 // `RenameAs`. Since this partial write is not renamed, no physical
269 // register is allocated.
270 ShouldAllocatePhysRegs = false;
272 WriteState *OtherWS = OtherWrite.getWriteState();
273 if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
274 // This partial write has a false dependency on RenameAs.
275 assert(!IsEliminated && "Unexpected partial update!");
276 OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);
281 // Update zero registers.
282 MCPhysReg ZeroRegisterID =
283 WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
284 ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
285 for (MCPhysReg I : MRI.subregs(ZeroRegisterID))
286 ZeroRegisters.setBitVal(I, IsWriteZero);
288 // If this move has been eliminated, then method tryEliminateMoveOrSwap should
289 // have already updated all the register mappings.
290 if (!IsEliminated) {
291 // Check if this is one of multiple writes performed by this
292 // instruction to register RegID.
293 const WriteRef &OtherWrite = RegisterMappings[RegID].first;
294 const WriteState *OtherWS = OtherWrite.getWriteState();
295 if (OtherWS && OtherWrite.getSourceIndex() == Write.getSourceIndex()) {
296 if (OtherWS->getLatency() > WS.getLatency()) {
297 // Conservatively keep the slowest write on RegID.
298 if (ShouldAllocatePhysRegs)
299 allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
300 return;
304 // Update the mapping for register RegID including its sub-registers.
305 RegisterMappings[RegID].first = Write;
306 RegisterMappings[RegID].second.AliasRegID = 0U;
307 for (MCPhysReg I : MRI.subregs(RegID)) {
308 RegisterMappings[I].first = Write;
309 RegisterMappings[I].second.AliasRegID = 0U;
312 // No physical registers are allocated for instructions that are optimized
313 // in hardware. For example, zero-latency data-dependency breaking
314 // instructions don't consume physical registers.
315 if (ShouldAllocatePhysRegs)
316 allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
319 if (!WS.clearsSuperRegisters())
320 return;
322 for (MCPhysReg I : MRI.superregs(RegID)) {
323 if (!IsEliminated) {
324 RegisterMappings[I].first = Write;
325 RegisterMappings[I].second.AliasRegID = 0U;
328 ZeroRegisters.setBitVal(I, IsWriteZero);
332 void RegisterFile::removeRegisterWrite(
333 const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
334 // Early exit if this write was eliminated. A write eliminated at register
335 // renaming stage generates an alias, and it is not added to the PRF.
336 if (WS.isEliminated())
337 return;
339 MCPhysReg RegID = WS.getRegisterID();
341 // This allows InstrPostProcess to remove register Defs
342 // by setting their RegisterID to 0.
343 if (!RegID)
344 return;
346 assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
347 "Invalidating a write of unknown cycles!");
348 assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
350 bool ShouldFreePhysRegs = !WS.isWriteZero();
351 MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
352 if (RenameAs && RenameAs != RegID) {
353 RegID = RenameAs;
355 if (!WS.clearsSuperRegisters()) {
356 // Keep the definition of `RegID` together with register `RenameAs`.
357 ShouldFreePhysRegs = false;
361 if (ShouldFreePhysRegs)
362 freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
364 WriteRef &WR = RegisterMappings[RegID].first;
365 if (WR.getWriteState() == &WS)
366 WR.commit();
368 for (MCPhysReg I : MRI.subregs(RegID)) {
369 WriteRef &OtherWR = RegisterMappings[I].first;
370 if (OtherWR.getWriteState() == &WS)
371 OtherWR.commit();
374 if (!WS.clearsSuperRegisters())
375 return;
377 for (MCPhysReg I : MRI.superregs(RegID)) {
378 WriteRef &OtherWR = RegisterMappings[I].first;
379 if (OtherWR.getWriteState() == &WS)
380 OtherWR.commit();
384 bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,
385 unsigned RegisterFileIndex) const {
386 const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
387 const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
388 const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
390 // From and To must be owned by the PRF at index `RegisterFileIndex`.
391 const RegisterRenamingInfo &RRIFrom = RMFrom.second;
392 if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)
393 return false;
395 const RegisterRenamingInfo &RRITo = RMTo.second;
396 if (RRITo.IndexPlusCost.first != RegisterFileIndex)
397 return false;
399 // Early exit if the destination register is from a register class that
400 // doesn't allow move elimination.
401 if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)
402 return false;
404 // We only allow move elimination for writes that update a full physical
405 // register. On X86, move elimination is possible with 32-bit general purpose
406 // registers because writes to those registers are not partial writes. If a
407 // register move is a partial write, then we conservatively assume that move
408 // elimination fails, since it would either trigger a partial update, or the
409 // issue of a merge opcode.
411 // Note that this constraint may be lifted in future. For example, we could
412 // make this model more flexible, and let users customize the set of registers
413 // (i.e. register classes) that allow move elimination.
415 // For now, we assume that there is a strong correlation between registers
416 // that allow move elimination, and how those same registers are renamed in
417 // hardware.
418 if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())
419 if (!WS.clearsSuperRegisters())
420 return false;
422 bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];
423 return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);
426 bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
427 MutableArrayRef<ReadState> Reads) {
428 if (Writes.size() != Reads.size())
429 return false;
431 // This logic assumes that writes and reads are contributed by a register move
432 // or a register swap operation. In particular, it assumes a simple register
433 // move if there is only one write. It assumes a swap operation if there are
434 // exactly two writes.
435 if (Writes.empty() || Writes.size() > 2)
436 return false;
438 // All registers must be owned by the same PRF.
439 const RegisterRenamingInfo &RRInfo =
440 RegisterMappings[Writes[0].getRegisterID()].second;
441 unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;
442 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
444 // Early exit if the PRF cannot eliminate more moves/xchg in this cycle.
445 if (RMT.MaxMoveEliminatedPerCycle &&
446 (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)
447 return false;
449 for (size_t I = 0, E = Writes.size(); I < E; ++I) {
450 const ReadState &RS = Reads[I];
451 const WriteState &WS = Writes[E - (I + 1)];
452 if (!canEliminateMove(WS, RS, RegisterFileIndex))
453 return false;
456 for (size_t I = 0, E = Writes.size(); I < E; ++I) {
457 ReadState &RS = Reads[I];
458 WriteState &WS = Writes[E - (I + 1)];
460 const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
461 const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
462 const RegisterRenamingInfo &RRIFrom = RMFrom.second;
463 const RegisterRenamingInfo &RRITo = RMTo.second;
465 // Construct an alias.
466 MCPhysReg AliasedReg =
467 RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();
468 MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();
470 const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;
471 if (RMAlias.AliasRegID)
472 AliasedReg = RMAlias.AliasRegID;
474 RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
475 for (MCPhysReg I : MRI.subregs(AliasReg))
476 RegisterMappings[I].second.AliasRegID = AliasedReg;
478 if (ZeroRegisters[RS.getRegisterID()]) {
479 WS.setWriteZero();
480 RS.setReadZero();
483 WS.setEliminated();
484 RMT.NumMoveEliminated++;
487 return true;
490 unsigned WriteRef::getWriteBackCycle() const {
491 assert(hasKnownWriteBackCycle() && "Instruction not executed!");
492 assert((!Write || Write->getCyclesLeft() <= 0) &&
493 "Inconsistent state found!");
494 return WriteBackCycle;
497 unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {
498 assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");
499 return CurrentCycle - WR.getWriteBackCycle();
502 void RegisterFile::collectWrites(
503 const MCSubtargetInfo &STI, const ReadState &RS,
504 SmallVectorImpl<WriteRef> &Writes,
505 SmallVectorImpl<WriteRef> &CommittedWrites) const {
506 const ReadDescriptor &RD = RS.getDescriptor();
507 const MCSchedModel &SM = STI.getSchedModel();
508 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
509 MCPhysReg RegID = RS.getRegisterID();
510 assert(RegID && RegID < RegisterMappings.size());
511 LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "
512 << MRI.getName(RegID) << '\n');
514 // Check if this is an alias.
515 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
516 if (RRI.AliasRegID)
517 RegID = RRI.AliasRegID;
519 const WriteRef &WR = RegisterMappings[RegID].first;
520 if (WR.getWriteState()) {
521 Writes.push_back(WR);
522 } else if (WR.hasKnownWriteBackCycle()) {
523 unsigned WriteResID = WR.getWriteResourceID();
524 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
525 if (ReadAdvance < 0) {
526 unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
527 if (Elapsed < static_cast<unsigned>(-ReadAdvance))
528 CommittedWrites.push_back(WR);
532 // Handle potential partial register updates.
533 for (MCPhysReg I : MRI.subregs(RegID)) {
534 const WriteRef &WR = RegisterMappings[I].first;
535 if (WR.getWriteState()) {
536 Writes.push_back(WR);
537 } else if (WR.hasKnownWriteBackCycle()) {
538 unsigned WriteResID = WR.getWriteResourceID();
539 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
540 if (ReadAdvance < 0) {
541 unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
542 if (Elapsed < static_cast<unsigned>(-ReadAdvance))
543 CommittedWrites.push_back(WR);
548 // Remove duplicate entries and resize the input vector.
549 if (Writes.size() > 1) {
550 sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) {
551 return Lhs.getWriteState() < Rhs.getWriteState();
553 auto It = std::unique(Writes.begin(), Writes.end());
554 Writes.resize(std::distance(Writes.begin(), It));
557 LLVM_DEBUG({
558 for (const WriteRef &WR : Writes) {
559 const WriteState &WS = *WR.getWriteState();
560 dbgs() << "[PRF] Found a dependent use of Register "
561 << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"
562 << WR.getSourceIndex() << ")\n";
567 RegisterFile::RAWHazard
568 RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI,
569 const ReadState &RS) const {
570 RAWHazard Hazard;
571 SmallVector<WriteRef, 4> Writes;
572 SmallVector<WriteRef, 4> CommittedWrites;
574 const MCSchedModel &SM = STI.getSchedModel();
575 const ReadDescriptor &RD = RS.getDescriptor();
576 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
578 collectWrites(STI, RS, Writes, CommittedWrites);
579 for (const WriteRef &WR : Writes) {
580 const WriteState *WS = WR.getWriteState();
581 unsigned WriteResID = WS->getWriteResourceID();
582 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
584 if (WS->getCyclesLeft() == UNKNOWN_CYCLES) {
585 if (Hazard.isValid())
586 continue;
588 Hazard.RegisterID = WR.getRegisterID();
589 Hazard.CyclesLeft = UNKNOWN_CYCLES;
590 continue;
593 int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;
594 if (CyclesLeft > 0) {
595 if (Hazard.CyclesLeft < CyclesLeft) {
596 Hazard.RegisterID = WR.getRegisterID();
597 Hazard.CyclesLeft = CyclesLeft;
601 Writes.clear();
603 for (const WriteRef &WR : CommittedWrites) {
604 unsigned WriteResID = WR.getWriteResourceID();
605 int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
606 int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR));
607 int CyclesLeft = NegReadAdvance - Elapsed;
608 assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");
609 if (Hazard.CyclesLeft < CyclesLeft) {
610 Hazard.RegisterID = WR.getRegisterID();
611 Hazard.CyclesLeft = CyclesLeft;
615 return Hazard;
618 void RegisterFile::addRegisterRead(ReadState &RS,
619 const MCSubtargetInfo &STI) const {
620 MCPhysReg RegID = RS.getRegisterID();
621 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
622 RS.setPRF(RRI.IndexPlusCost.first);
623 if (RS.isIndependentFromDef())
624 return;
626 if (ZeroRegisters[RS.getRegisterID()])
627 RS.setReadZero();
629 SmallVector<WriteRef, 4> DependentWrites;
630 SmallVector<WriteRef, 4> CompletedWrites;
631 collectWrites(STI, RS, DependentWrites, CompletedWrites);
632 RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());
634 // We know that this read depends on all the writes in DependentWrites.
635 // For each write, check if we have ReadAdvance information, and use it
636 // to figure out in how many cycles this read will be available.
637 const ReadDescriptor &RD = RS.getDescriptor();
638 const MCSchedModel &SM = STI.getSchedModel();
639 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
640 for (WriteRef &WR : DependentWrites) {
641 unsigned WriteResID = WR.getWriteResourceID();
642 WriteState &WS = *WR.getWriteState();
643 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
644 WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);
647 for (WriteRef &WR : CompletedWrites) {
648 unsigned WriteResID = WR.getWriteResourceID();
649 assert(WR.hasKnownWriteBackCycle() && "Invalid write!");
650 assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);
651 unsigned ReadAdvance = static_cast<unsigned>(
652 -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));
653 unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
654 assert(Elapsed < ReadAdvance && "Should not have been added to the set!");
655 RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),
656 ReadAdvance - Elapsed);
660 unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {
661 SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
663 // Find how many new mappings must be created for each register file.
664 for (const MCPhysReg RegID : Regs) {
665 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
666 const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
667 if (Entry.first)
668 NumPhysRegs[Entry.first] += Entry.second;
669 NumPhysRegs[0] += Entry.second;
672 unsigned Response = 0;
673 for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
674 unsigned NumRegs = NumPhysRegs[I];
675 if (!NumRegs)
676 continue;
678 const RegisterMappingTracker &RMT = RegisterFiles[I];
679 if (!RMT.NumPhysRegs) {
680 // The register file has an unbounded number of microarchitectural
681 // registers.
682 continue;
685 if (RMT.NumPhysRegs < NumRegs) {
686 // The current register file is too small. This may occur if the number of
687 // microarchitectural registers in register file #0 was changed by the
688 // users via flag -reg-file-size. Alternatively, the scheduling model
689 // specified a too small number of registers for this register file.
690 LLVM_DEBUG(
691 dbgs() << "[PRF] Not enough registers in the register file.\n");
693 // FIXME: Normalize the instruction register count to match the
694 // NumPhysRegs value. This is a highly unusual case, and is not expected
695 // to occur. This normalization is hiding an inconsistency in either the
696 // scheduling model or in the value that the user might have specified
697 // for NumPhysRegs.
698 NumRegs = RMT.NumPhysRegs;
701 if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
702 Response |= (1U << I);
705 return Response;
708 #ifndef NDEBUG
709 void WriteRef::dump() const {
710 dbgs() << "IID=" << getSourceIndex() << ' ';
711 if (isValid())
712 getWriteState()->dump();
713 else
714 dbgs() << "(null)";
717 void RegisterFile::dump() const {
718 for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
719 const RegisterMapping &RM = RegisterMappings[I];
720 const RegisterRenamingInfo &RRI = RM.second;
721 if (ZeroRegisters[I]) {
722 dbgs() << MRI.getName(I) << ", " << I
723 << ", PRF=" << RRI.IndexPlusCost.first
724 << ", Cost=" << RRI.IndexPlusCost.second
725 << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
726 << ",";
727 RM.first.dump();
728 dbgs() << '\n';
732 for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
733 dbgs() << "Register File #" << I;
734 const RegisterMappingTracker &RMT = RegisterFiles[I];
735 dbgs() << "\n TotalMappings: " << RMT.NumPhysRegs
736 << "\n NumUsedMappings: " << RMT.NumUsedPhysRegs << '\n';
739 #endif
741 } // namespace mca
742 } // namespace llvm