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 //===----------------------------------------------------------------------===//
15 
16 #include "llvm/MCA/HardwareUnits/RegisterFile.h"
17 #include "llvm/MCA/Instruction.h"
18 #include "llvm/Support/Debug.h"
19 
20 #define DEBUG_TYPE "llvm-mca"
21 
22 namespace llvm {
23 namespace mca {
24 
25 const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
26 
27 WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
28     : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
29       Write(WS) {}
30 
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;
36 }
37 
38 void WriteRef::notifyExecuted(unsigned Cycle) {
39   assert(Write && Write->isExecuted() && "Not executed!");
40   WriteBackCycle = Cycle;
41 }
42 
43 bool WriteRef::hasKnownWriteBackCycle() const {
44   return isValid() && (!Write || Write->isExecuted());
45 }
46 
47 bool WriteRef::isWriteZero() const {
48   assert(isValid() && "Invalid null WriteState found!");
49   return getWriteState()->isWriteZero();
50 }
51 
52 unsigned WriteRef::getWriteResourceID() const {
53   if (Write)
54     return Write->getWriteResourceID();
55   return WriteResID;
56 }
57 
58 MCPhysReg WriteRef::getRegisterID() const {
59   if (Write)
60     return Write->getRegisterID();
61   return RegisterID;
62 }
63 
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);
70 }
71 
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;
80 
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();
85 
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!");
90 
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));
97   }
98 }
99 
100 void RegisterFile::cycleStart() {
101   for (RegisterMappingTracker &RMT : RegisterFiles)
102     RMT.NumMoveEliminated = 0;
103 }
104 
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;
110 
111     MCPhysReg RegID = WS.getRegisterID();
112     assert(RegID != 0 && "A write of an invalid register?");
113     assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
114            "The number of cycles should be known at this point!");
115     assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
116 
117     MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
118     if (RenameAs && RenameAs != RegID)
119       RegID = RenameAs;
120 
121     WriteRef &WR = RegisterMappings[RegID].first;
122     if (WR.getWriteState() == &WS)
123       WR.notifyExecuted(CurrentCycle);
124 
125     for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
126       WriteRef &OtherWR = RegisterMappings[*I].first;
127       if (OtherWR.getWriteState() == &WS)
128         OtherWR.notifyExecuted(CurrentCycle);
129     }
130 
131     if (!WS.clearsSuperRegisters())
132       continue;
133 
134     for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
135       WriteRef &OtherWR = RegisterMappings[*I].first;
136       if (OtherWR.getWriteState() == &WS)
137         OtherWR.notifyExecuted(CurrentCycle);
138     }
139   }
140 }
141 
142 void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,
143                                    ArrayRef<MCRegisterCostEntry> Entries) {
144   // A default register file is always allocated at index #0. That register file
145   // is mainly used to count the total number of mappings created by all
146   // register files at runtime. Users can limit the number of available physical
147   // registers in register file #0 through the command line flag
148   // `-register-file-size`.
149   unsigned RegisterFileIndex = RegisterFiles.size();
150   RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,
151                              RF.AllowZeroMoveEliminationOnly);
152 
153   // Special case where there is no register class identifier in the set.
154   // An empty set of register classes means: this register file contains all
155   // the physical registers specified by the target.
156   // We optimistically assume that a register can be renamed at the cost of a
157   // single physical register. The constructor of RegisterFile ensures that
158   // a RegisterMapping exists for each logical register defined by the Target.
159   if (Entries.empty())
160     return;
161 
162   // Now update the cost of individual registers.
163   for (const MCRegisterCostEntry &RCE : Entries) {
164     const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
165     for (const MCPhysReg Reg : RC) {
166       RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
167       IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
168       if (IPC.first && IPC.first != RegisterFileIndex) {
169         // The only register file that is allowed to overlap is the default
170         // register file at index #0. The analysis is inaccurate if register
171         // files overlap.
172         errs() << "warning: register " << MRI.getName(Reg)
173                << " defined in multiple register files.";
174       }
175       IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
176       Entry.RenameAs = Reg;
177       Entry.AllowMoveElimination = RCE.AllowMoveElimination;
178 
179       // Assume the same cost for each sub-register.
180       for (MCSubRegIterator I(Reg, &MRI); I.isValid(); ++I) {
181         RegisterRenamingInfo &OtherEntry = RegisterMappings[*I].second;
182         if (!OtherEntry.IndexPlusCost.first &&
183             (!OtherEntry.RenameAs ||
184              MRI.isSuperRegister(*I, OtherEntry.RenameAs))) {
185           OtherEntry.IndexPlusCost = IPC;
186           OtherEntry.RenameAs = Reg;
187         }
188       }
189     }
190   }
191 }
192 
193 void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
194                                     MutableArrayRef<unsigned> UsedPhysRegs) {
195   unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
196   unsigned Cost = Entry.IndexPlusCost.second;
197   if (RegisterFileIndex) {
198     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
199     RMT.NumUsedPhysRegs += Cost;
200     UsedPhysRegs[RegisterFileIndex] += Cost;
201   }
202 
203   // Now update the default register mapping tracker.
204   RegisterFiles[0].NumUsedPhysRegs += Cost;
205   UsedPhysRegs[0] += Cost;
206 }
207 
208 void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
209                                 MutableArrayRef<unsigned> FreedPhysRegs) {
210   unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
211   unsigned Cost = Entry.IndexPlusCost.second;
212   if (RegisterFileIndex) {
213     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
214     RMT.NumUsedPhysRegs -= Cost;
215     FreedPhysRegs[RegisterFileIndex] += Cost;
216   }
217 
218   // Now update the default register mapping tracker.
219   RegisterFiles[0].NumUsedPhysRegs -= Cost;
220   FreedPhysRegs[0] += Cost;
221 }
222 
223 void RegisterFile::addRegisterWrite(WriteRef Write,
224                                     MutableArrayRef<unsigned> UsedPhysRegs) {
225   WriteState &WS = *Write.getWriteState();
226   MCPhysReg RegID = WS.getRegisterID();
227   assert(RegID && "Adding an invalid register definition?");
228 
229   LLVM_DEBUG({
230     dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "
231            << MRI.getName(RegID) << "]\n";
232   });
233 
234   // If RenameAs is equal to RegID, then RegID is subject to register renaming
235   // and false dependencies on RegID are all eliminated.
236 
237   // If RenameAs references the invalid register, then we optimistically assume
238   // that it can be renamed. In the absence of tablegen descriptors for register
239   // files, RenameAs is always set to the invalid register ID.  In all other
240   // cases, RenameAs must be either equal to RegID, or it must reference a
241   // super-register of RegID.
242 
243   // If RenameAs is a super-register of RegID, then a write to RegID has always
244   // a false dependency on RenameAs. The only exception is for when the write
245   // implicitly clears the upper portion of the underlying register.
246   // If a write clears its super-registers, then it is renamed as `RenameAs`.
247   bool IsWriteZero = WS.isWriteZero();
248   bool IsEliminated = WS.isEliminated();
249   bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
250   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
251   WS.setPRF(RRI.IndexPlusCost.first);
252 
253   if (RRI.RenameAs && RRI.RenameAs != RegID) {
254     RegID = RRI.RenameAs;
255     WriteRef &OtherWrite = RegisterMappings[RegID].first;
256 
257     if (!WS.clearsSuperRegisters()) {
258       // The processor keeps the definition of `RegID` together with register
259       // `RenameAs`. Since this partial write is not renamed, no physical
260       // register is allocated.
261       ShouldAllocatePhysRegs = false;
262 
263       WriteState *OtherWS = OtherWrite.getWriteState();
264       if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
265         // This partial write has a false dependency on RenameAs.
266         assert(!IsEliminated && "Unexpected partial update!");
267         OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);
268       }
269     }
270   }
271 
272   // Update zero registers.
273   MCPhysReg ZeroRegisterID =
274       WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
275   ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
276   for (MCSubRegIterator I(ZeroRegisterID, &MRI); I.isValid(); ++I)
277     ZeroRegisters.setBitVal(*I, IsWriteZero);
278 
279   // If this move has been eliminated, then method tryEliminateMoveOrSwap should
280   // have already updated all the register mappings.
281   if (!IsEliminated) {
282     // Update the mapping for register RegID including its sub-registers.
283     RegisterMappings[RegID].first = Write;
284     RegisterMappings[RegID].second.AliasRegID = 0U;
285     for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
286       RegisterMappings[*I].first = Write;
287       RegisterMappings[*I].second.AliasRegID = 0U;
288     }
289 
290     // No physical registers are allocated for instructions that are optimized
291     // in hardware. For example, zero-latency data-dependency breaking
292     // instructions don't consume physical registers.
293     if (ShouldAllocatePhysRegs)
294       allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
295   }
296 
297   if (!WS.clearsSuperRegisters())
298     return;
299 
300   for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
301     if (!IsEliminated) {
302       RegisterMappings[*I].first = Write;
303       RegisterMappings[*I].second.AliasRegID = 0U;
304     }
305 
306     ZeroRegisters.setBitVal(*I, IsWriteZero);
307   }
308 }
309 
310 void RegisterFile::removeRegisterWrite(
311     const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
312   // Early exit if this write was eliminated. A write eliminated at register
313   // renaming stage generates an alias, and it is not added to the PRF.
314   if (WS.isEliminated())
315     return;
316 
317   MCPhysReg RegID = WS.getRegisterID();
318 
319   assert(RegID != 0 && "Invalidating an already invalid register?");
320   assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
321          "Invalidating a write of unknown cycles!");
322   assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
323 
324   bool ShouldFreePhysRegs = !WS.isWriteZero();
325   MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
326   if (RenameAs && RenameAs != RegID) {
327     RegID = RenameAs;
328 
329     if (!WS.clearsSuperRegisters()) {
330       // Keep the definition of `RegID` together with register `RenameAs`.
331       ShouldFreePhysRegs = false;
332     }
333   }
334 
335   if (ShouldFreePhysRegs)
336     freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
337 
338   WriteRef &WR = RegisterMappings[RegID].first;
339   if (WR.getWriteState() == &WS)
340     WR.commit();
341 
342   for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
343     WriteRef &OtherWR = RegisterMappings[*I].first;
344     if (OtherWR.getWriteState() == &WS)
345       OtherWR.commit();
346   }
347 
348   if (!WS.clearsSuperRegisters())
349     return;
350 
351   for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
352     WriteRef &OtherWR = RegisterMappings[*I].first;
353     if (OtherWR.getWriteState() == &WS)
354       OtherWR.commit();
355   }
356 }
357 
358 bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,
359                                     unsigned RegisterFileIndex) const {
360   const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
361   const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
362   const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
363 
364   // From and To must be owned by the PRF at index `RegisterFileIndex`.
365   const RegisterRenamingInfo &RRIFrom = RMFrom.second;
366   if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)
367     return false;
368 
369   const RegisterRenamingInfo &RRITo = RMTo.second;
370   if (RRITo.IndexPlusCost.first != RegisterFileIndex)
371     return false;
372 
373   // Early exit if the destination register is from a register class that
374   // doesn't allow move elimination.
375   if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)
376     return false;
377 
378   // We only allow move elimination for writes that update a full physical
379   // register. On X86, move elimination is possible with 32-bit general purpose
380   // registers because writes to those registers are not partial writes.  If a
381   // register move is a partial write, then we conservatively assume that move
382   // elimination fails, since it would either trigger a partial update, or the
383   // issue of a merge opcode.
384   //
385   // Note that this constraint may be lifted in future.  For example, we could
386   // make this model more flexible, and let users customize the set of registers
387   // (i.e. register classes) that allow move elimination.
388   //
389   // For now, we assume that there is a strong correlation between registers
390   // that allow move elimination, and how those same registers are renamed in
391   // hardware.
392   if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())
393     if (!WS.clearsSuperRegisters())
394       return false;
395 
396   bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];
397   return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);
398 }
399 
400 bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
401                                           MutableArrayRef<ReadState> Reads) {
402   if (Writes.size() != Reads.size())
403     return false;
404 
405   // This logic assumes that writes and reads are contributed by a register move
406   // or a register swap operation. In particular, it assumes a simple register
407   // move if there is only one write.  It assumes a swap operation if there are
408   // exactly two writes.
409   if (Writes.empty() || Writes.size() > 2)
410     return false;
411 
412   // All registers must be owned by the same PRF.
413   const RegisterRenamingInfo &RRInfo =
414       RegisterMappings[Writes[0].getRegisterID()].second;
415   unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;
416   RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
417 
418   // Early exit if the PRF cannot eliminate more moves/xchg in this cycle.
419   if (RMT.MaxMoveEliminatedPerCycle &&
420       (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)
421     return false;
422 
423   for (size_t I = 0, E = Writes.size(); I < E; ++I) {
424     const ReadState &RS = Reads[I];
425     const WriteState &WS = Writes[E - (I + 1)];
426     if (!canEliminateMove(WS, RS, RegisterFileIndex))
427       return false;
428   }
429 
430   for (size_t I = 0, E = Writes.size(); I < E; ++I) {
431     ReadState &RS = Reads[I];
432     WriteState &WS = Writes[E - (I + 1)];
433 
434     const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
435     const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
436     const RegisterRenamingInfo &RRIFrom = RMFrom.second;
437     const RegisterRenamingInfo &RRITo = RMTo.second;
438 
439     // Construct an alias.
440     MCPhysReg AliasedReg =
441         RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();
442     MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();
443 
444     const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;
445     if (RMAlias.AliasRegID)
446       AliasedReg = RMAlias.AliasRegID;
447 
448     RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
449     for (MCSubRegIterator I(AliasReg, &MRI); I.isValid(); ++I)
450       RegisterMappings[*I].second.AliasRegID = AliasedReg;
451 
452     if (ZeroRegisters[RS.getRegisterID()]) {
453       WS.setWriteZero();
454       RS.setReadZero();
455     }
456 
457     WS.setEliminated();
458     RMT.NumMoveEliminated++;
459   }
460 
461   return true;
462 }
463 
464 unsigned WriteRef::getWriteBackCycle() const {
465   assert(hasKnownWriteBackCycle() && "Instruction not executed!");
466   assert((!Write || Write->getCyclesLeft() <= 0) &&
467          "Inconsistent state found!");
468   return WriteBackCycle;
469 }
470 
471 unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {
472   assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");
473   return CurrentCycle - WR.getWriteBackCycle();
474 }
475 
476 void RegisterFile::collectWrites(
477     const MCSubtargetInfo &STI, const ReadState &RS,
478     SmallVectorImpl<WriteRef> &Writes,
479     SmallVectorImpl<WriteRef> &CommittedWrites) const {
480   const ReadDescriptor &RD = RS.getDescriptor();
481   const MCSchedModel &SM = STI.getSchedModel();
482   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
483   MCPhysReg RegID = RS.getRegisterID();
484   assert(RegID && RegID < RegisterMappings.size());
485   LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "
486                     << MRI.getName(RegID) << '\n');
487 
488   // Check if this is an alias.
489   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
490   if (RRI.AliasRegID)
491     RegID = RRI.AliasRegID;
492 
493   const WriteRef &WR = RegisterMappings[RegID].first;
494   if (WR.getWriteState()) {
495     Writes.push_back(WR);
496   } else if (WR.hasKnownWriteBackCycle()) {
497     unsigned WriteResID = WR.getWriteResourceID();
498     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
499     if (ReadAdvance < 0) {
500       unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
501       if (Elapsed < static_cast<unsigned>(-ReadAdvance))
502         CommittedWrites.push_back(WR);
503     }
504   }
505 
506   // Handle potential partial register updates.
507   for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
508     const WriteRef &WR = RegisterMappings[*I].first;
509     if (WR.getWriteState()) {
510       Writes.push_back(WR);
511     } else if (WR.hasKnownWriteBackCycle()) {
512       unsigned WriteResID = WR.getWriteResourceID();
513       int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
514       if (ReadAdvance < 0) {
515         unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
516         if (Elapsed < static_cast<unsigned>(-ReadAdvance))
517           CommittedWrites.push_back(WR);
518       }
519     }
520   }
521 
522   // Remove duplicate entries and resize the input vector.
523   if (Writes.size() > 1) {
524     sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) {
525       return Lhs.getWriteState() < Rhs.getWriteState();
526     });
527     auto It = std::unique(Writes.begin(), Writes.end());
528     Writes.resize(std::distance(Writes.begin(), It));
529   }
530 
531   LLVM_DEBUG({
532     for (const WriteRef &WR : Writes) {
533       const WriteState &WS = *WR.getWriteState();
534       dbgs() << "[PRF] Found a dependent use of Register "
535              << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"
536              << WR.getSourceIndex() << ")\n";
537     }
538   });
539 }
540 
541 RegisterFile::RAWHazard
542 RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI,
543                               const ReadState &RS) const {
544   RAWHazard Hazard;
545   SmallVector<WriteRef, 4> Writes;
546   SmallVector<WriteRef, 4> CommittedWrites;
547 
548   const MCSchedModel &SM = STI.getSchedModel();
549   const ReadDescriptor &RD = RS.getDescriptor();
550   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
551 
552   collectWrites(STI, RS, Writes, CommittedWrites);
553   for (const WriteRef &WR : Writes) {
554     const WriteState *WS = WR.getWriteState();
555     unsigned WriteResID = WS->getWriteResourceID();
556     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
557 
558     if (WS->getCyclesLeft() == UNKNOWN_CYCLES) {
559       if (Hazard.isValid())
560         continue;
561 
562       Hazard.RegisterID = WR.getRegisterID();
563       Hazard.CyclesLeft = UNKNOWN_CYCLES;
564       continue;
565     }
566 
567     int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;
568     if (CyclesLeft > 0) {
569       if (Hazard.CyclesLeft < CyclesLeft) {
570         Hazard.RegisterID = WR.getRegisterID();
571         Hazard.CyclesLeft = CyclesLeft;
572       }
573     }
574   }
575   Writes.clear();
576 
577   for (const WriteRef &WR : CommittedWrites) {
578     unsigned WriteResID = WR.getWriteResourceID();
579     int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
580     int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR));
581     int CyclesLeft = NegReadAdvance - Elapsed;
582     assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");
583     if (Hazard.CyclesLeft < CyclesLeft) {
584       Hazard.RegisterID = WR.getRegisterID();
585       Hazard.CyclesLeft = CyclesLeft;
586     }
587   }
588 
589   return Hazard;
590 }
591 
592 void RegisterFile::addRegisterRead(ReadState &RS,
593                                    const MCSubtargetInfo &STI) const {
594   MCPhysReg RegID = RS.getRegisterID();
595   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
596   RS.setPRF(RRI.IndexPlusCost.first);
597   if (RS.isIndependentFromDef())
598     return;
599 
600   if (ZeroRegisters[RS.getRegisterID()])
601     RS.setReadZero();
602 
603   SmallVector<WriteRef, 4> DependentWrites;
604   SmallVector<WriteRef, 4> CompletedWrites;
605   collectWrites(STI, RS, DependentWrites, CompletedWrites);
606   RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());
607 
608   // We know that this read depends on all the writes in DependentWrites.
609   // For each write, check if we have ReadAdvance information, and use it
610   // to figure out in how many cycles this read will be available.
611   const ReadDescriptor &RD = RS.getDescriptor();
612   const MCSchedModel &SM = STI.getSchedModel();
613   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
614   for (WriteRef &WR : DependentWrites) {
615     unsigned WriteResID = WR.getWriteResourceID();
616     WriteState &WS = *WR.getWriteState();
617     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
618     WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);
619   }
620 
621   for (WriteRef &WR : CompletedWrites) {
622     unsigned WriteResID = WR.getWriteResourceID();
623     assert(WR.hasKnownWriteBackCycle() && "Invalid write!");
624     assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);
625     unsigned ReadAdvance = static_cast<unsigned>(
626         -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));
627     unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
628     assert(Elapsed < ReadAdvance && "Should not have been added to the set!");
629     RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),
630                        ReadAdvance - Elapsed);
631   }
632 }
633 
634 unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {
635   SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
636 
637   // Find how many new mappings must be created for each register file.
638   for (const MCPhysReg RegID : Regs) {
639     const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
640     const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
641     if (Entry.first)
642       NumPhysRegs[Entry.first] += Entry.second;
643     NumPhysRegs[0] += Entry.second;
644   }
645 
646   unsigned Response = 0;
647   for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
648     unsigned NumRegs = NumPhysRegs[I];
649     if (!NumRegs)
650       continue;
651 
652     const RegisterMappingTracker &RMT = RegisterFiles[I];
653     if (!RMT.NumPhysRegs) {
654       // The register file has an unbounded number of microarchitectural
655       // registers.
656       continue;
657     }
658 
659     if (RMT.NumPhysRegs < NumRegs) {
660       // The current register file is too small. This may occur if the number of
661       // microarchitectural registers in register file #0 was changed by the
662       // users via flag -reg-file-size. Alternatively, the scheduling model
663       // specified a too small number of registers for this register file.
664       LLVM_DEBUG(
665           dbgs() << "[PRF] Not enough registers in the register file.\n");
666 
667       // FIXME: Normalize the instruction register count to match the
668       // NumPhysRegs value.  This is a highly unusual case, and is not expected
669       // to occur.  This normalization is hiding an inconsistency in either the
670       // scheduling model or in the value that the user might have specified
671       // for NumPhysRegs.
672       NumRegs = RMT.NumPhysRegs;
673     }
674 
675     if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
676       Response |= (1U << I);
677   }
678 
679   return Response;
680 }
681 
682 #ifndef NDEBUG
683 void WriteRef::dump() const {
684   dbgs() << "IID=" << getSourceIndex() << ' ';
685   if (isValid())
686     getWriteState()->dump();
687   else
688     dbgs() << "(null)";
689 }
690 
691 void RegisterFile::dump() const {
692   for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
693     const RegisterMapping &RM = RegisterMappings[I];
694     const RegisterRenamingInfo &RRI = RM.second;
695     if (ZeroRegisters[I]) {
696       dbgs() << MRI.getName(I) << ", " << I
697              << ", PRF=" << RRI.IndexPlusCost.first
698              << ", Cost=" << RRI.IndexPlusCost.second
699              << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
700              << ",";
701       RM.first.dump();
702       dbgs() << '\n';
703     }
704   }
705 
706   for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
707     dbgs() << "Register File #" << I;
708     const RegisterMappingTracker &RMT = RegisterFiles[I];
709     dbgs() << "\n  TotalMappings:        " << RMT.NumPhysRegs
710            << "\n  NumUsedMappings:      " << RMT.NumUsedPhysRegs << '\n';
711   }
712 }
713 #endif
714 
715 } // namespace mca
716 } // namespace llvm
717