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