xref: /freebsd-src/contrib/llvm-project/llvm/lib/MCA/HardwareUnits/RegisterFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This file defines a register mapping file class.  This class is responsible
110b57cec5SDimitry Andric /// for managing hardware register files and the tracking of data dependencies
120b57cec5SDimitry Andric /// between registers.
130b57cec5SDimitry Andric ///
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/MCA/HardwareUnits/RegisterFile.h"
170b57cec5SDimitry Andric #include "llvm/MCA/Instruction.h"
180b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #define DEBUG_TYPE "llvm-mca"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace llvm {
230b57cec5SDimitry Andric namespace mca {
240b57cec5SDimitry Andric 
25fe6060f1SDimitry Andric const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
26fe6060f1SDimitry Andric 
27fe6060f1SDimitry Andric WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
28fe6060f1SDimitry Andric     : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
29fe6060f1SDimitry Andric       Write(WS) {}
30fe6060f1SDimitry Andric 
31fe6060f1SDimitry Andric void WriteRef::commit() {
32fe6060f1SDimitry Andric   assert(Write && Write->isExecuted() && "Cannot commit before write back!");
33fe6060f1SDimitry Andric   RegisterID = Write->getRegisterID();
34fe6060f1SDimitry Andric   WriteResID = Write->getWriteResourceID();
35fe6060f1SDimitry Andric   Write = nullptr;
36fe6060f1SDimitry Andric }
37fe6060f1SDimitry Andric 
38fe6060f1SDimitry Andric void WriteRef::notifyExecuted(unsigned Cycle) {
39fe6060f1SDimitry Andric   assert(Write && Write->isExecuted() && "Not executed!");
40fe6060f1SDimitry Andric   WriteBackCycle = Cycle;
41fe6060f1SDimitry Andric }
42fe6060f1SDimitry Andric 
43fe6060f1SDimitry Andric bool WriteRef::hasKnownWriteBackCycle() const {
44fe6060f1SDimitry Andric   return isValid() && (!Write || Write->isExecuted());
45fe6060f1SDimitry Andric }
46fe6060f1SDimitry Andric 
47fe6060f1SDimitry Andric bool WriteRef::isWriteZero() const {
48fe6060f1SDimitry Andric   assert(isValid() && "Invalid null WriteState found!");
49fe6060f1SDimitry Andric   return getWriteState()->isWriteZero();
50fe6060f1SDimitry Andric }
51fe6060f1SDimitry Andric 
52fe6060f1SDimitry Andric unsigned WriteRef::getWriteResourceID() const {
53fe6060f1SDimitry Andric   if (Write)
54fe6060f1SDimitry Andric     return Write->getWriteResourceID();
55fe6060f1SDimitry Andric   return WriteResID;
56fe6060f1SDimitry Andric }
57fe6060f1SDimitry Andric 
58fe6060f1SDimitry Andric MCPhysReg WriteRef::getRegisterID() const {
59fe6060f1SDimitry Andric   if (Write)
60fe6060f1SDimitry Andric     return Write->getRegisterID();
61fe6060f1SDimitry Andric   return RegisterID;
62fe6060f1SDimitry Andric }
63fe6060f1SDimitry Andric 
640b57cec5SDimitry Andric RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,
650b57cec5SDimitry Andric                            unsigned NumRegs)
660b57cec5SDimitry Andric     : MRI(mri),
670b57cec5SDimitry Andric       RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),
68fe6060f1SDimitry Andric       ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {
690b57cec5SDimitry Andric   initialize(SM, NumRegs);
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
730b57cec5SDimitry Andric   // Create a default register file that "sees" all the machine registers
740b57cec5SDimitry Andric   // declared by the target. The number of physical registers in the default
750b57cec5SDimitry Andric   // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
760b57cec5SDimitry Andric   // means: this register file has an unbounded number of physical registers.
770b57cec5SDimitry Andric   RegisterFiles.emplace_back(NumRegs);
780b57cec5SDimitry Andric   if (!SM.hasExtraProcessorInfo())
790b57cec5SDimitry Andric     return;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   // For each user defined register file, allocate a RegisterMappingTracker
820b57cec5SDimitry Andric   // object. The size of every register file, as well as the mapping between
830b57cec5SDimitry Andric   // register files and register classes is specified via tablegen.
840b57cec5SDimitry Andric   const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   // Skip invalid register file at index 0.
870b57cec5SDimitry Andric   for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {
880b57cec5SDimitry Andric     const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
890b57cec5SDimitry Andric     assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric     // The cost of a register definition is equivalent to the number of
920b57cec5SDimitry Andric     // physical registers that are allocated at register renaming stage.
930b57cec5SDimitry Andric     unsigned Length = RF.NumRegisterCostEntries;
940b57cec5SDimitry Andric     const MCRegisterCostEntry *FirstElt =
950b57cec5SDimitry Andric         &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
960b57cec5SDimitry Andric     addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length));
970b57cec5SDimitry Andric   }
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric void RegisterFile::cycleStart() {
1010b57cec5SDimitry Andric   for (RegisterMappingTracker &RMT : RegisterFiles)
1020b57cec5SDimitry Andric     RMT.NumMoveEliminated = 0;
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
105fe6060f1SDimitry Andric void RegisterFile::onInstructionExecuted(Instruction *IS) {
106fe6060f1SDimitry Andric   assert(IS && IS->isExecuted() && "Unexpected internal state found!");
107fe6060f1SDimitry Andric   for (WriteState &WS : IS->getDefs()) {
108fe6060f1SDimitry Andric     if (WS.isEliminated())
109fe6060f1SDimitry Andric       return;
110fe6060f1SDimitry Andric 
111fe6060f1SDimitry Andric     MCPhysReg RegID = WS.getRegisterID();
112fe6060f1SDimitry Andric 
113fe6060f1SDimitry Andric     // This allows InstrPostProcess to remove register Defs
114fe6060f1SDimitry Andric     // by setting their RegisterID to 0.
115fe6060f1SDimitry Andric     if (!RegID)
116fe6060f1SDimitry Andric       continue;
117fe6060f1SDimitry Andric 
118fe6060f1SDimitry Andric     assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
119fe6060f1SDimitry Andric            "The number of cycles should be known at this point!");
120fe6060f1SDimitry Andric     assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
121fe6060f1SDimitry Andric 
122fe6060f1SDimitry Andric     MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
123fe6060f1SDimitry Andric     if (RenameAs && RenameAs != RegID)
124fe6060f1SDimitry Andric       RegID = RenameAs;
125fe6060f1SDimitry Andric 
126fe6060f1SDimitry Andric     WriteRef &WR = RegisterMappings[RegID].first;
127fe6060f1SDimitry Andric     if (WR.getWriteState() == &WS)
128fe6060f1SDimitry Andric       WR.notifyExecuted(CurrentCycle);
129fe6060f1SDimitry Andric 
13006c3fb27SDimitry Andric     for (MCPhysReg I : MRI.subregs(RegID)) {
13106c3fb27SDimitry Andric       WriteRef &OtherWR = RegisterMappings[I].first;
132fe6060f1SDimitry Andric       if (OtherWR.getWriteState() == &WS)
133fe6060f1SDimitry Andric         OtherWR.notifyExecuted(CurrentCycle);
134fe6060f1SDimitry Andric     }
135fe6060f1SDimitry Andric 
136fe6060f1SDimitry Andric     if (!WS.clearsSuperRegisters())
137fe6060f1SDimitry Andric       continue;
138fe6060f1SDimitry Andric 
13906c3fb27SDimitry Andric     for (MCPhysReg I : MRI.superregs(RegID)) {
14006c3fb27SDimitry Andric       WriteRef &OtherWR = RegisterMappings[I].first;
141fe6060f1SDimitry Andric       if (OtherWR.getWriteState() == &WS)
142fe6060f1SDimitry Andric         OtherWR.notifyExecuted(CurrentCycle);
143fe6060f1SDimitry Andric     }
144fe6060f1SDimitry Andric   }
145fe6060f1SDimitry Andric }
146fe6060f1SDimitry Andric 
1470b57cec5SDimitry Andric void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,
1480b57cec5SDimitry Andric                                    ArrayRef<MCRegisterCostEntry> Entries) {
1490b57cec5SDimitry Andric   // A default register file is always allocated at index #0. That register file
1500b57cec5SDimitry Andric   // is mainly used to count the total number of mappings created by all
1510b57cec5SDimitry Andric   // register files at runtime. Users can limit the number of available physical
1520b57cec5SDimitry Andric   // registers in register file #0 through the command line flag
1530b57cec5SDimitry Andric   // `-register-file-size`.
1540b57cec5SDimitry Andric   unsigned RegisterFileIndex = RegisterFiles.size();
1550b57cec5SDimitry Andric   RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,
1560b57cec5SDimitry Andric                              RF.AllowZeroMoveEliminationOnly);
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   // Special case where there is no register class identifier in the set.
1590b57cec5SDimitry Andric   // An empty set of register classes means: this register file contains all
1600b57cec5SDimitry Andric   // the physical registers specified by the target.
1610b57cec5SDimitry Andric   // We optimistically assume that a register can be renamed at the cost of a
1620b57cec5SDimitry Andric   // single physical register. The constructor of RegisterFile ensures that
1630b57cec5SDimitry Andric   // a RegisterMapping exists for each logical register defined by the Target.
1640b57cec5SDimitry Andric   if (Entries.empty())
1650b57cec5SDimitry Andric     return;
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   // Now update the cost of individual registers.
1680b57cec5SDimitry Andric   for (const MCRegisterCostEntry &RCE : Entries) {
1690b57cec5SDimitry Andric     const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
1700b57cec5SDimitry Andric     for (const MCPhysReg Reg : RC) {
1710b57cec5SDimitry Andric       RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
1720b57cec5SDimitry Andric       IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
1730b57cec5SDimitry Andric       if (IPC.first && IPC.first != RegisterFileIndex) {
1740b57cec5SDimitry Andric         // The only register file that is allowed to overlap is the default
1750b57cec5SDimitry Andric         // register file at index #0. The analysis is inaccurate if register
1760b57cec5SDimitry Andric         // files overlap.
1770b57cec5SDimitry Andric         errs() << "warning: register " << MRI.getName(Reg)
1780b57cec5SDimitry Andric                << " defined in multiple register files.";
1790b57cec5SDimitry Andric       }
1800b57cec5SDimitry Andric       IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
1810b57cec5SDimitry Andric       Entry.RenameAs = Reg;
1820b57cec5SDimitry Andric       Entry.AllowMoveElimination = RCE.AllowMoveElimination;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric       // Assume the same cost for each sub-register.
18506c3fb27SDimitry Andric       for (MCPhysReg I : MRI.subregs(Reg)) {
18606c3fb27SDimitry Andric         RegisterRenamingInfo &OtherEntry = RegisterMappings[I].second;
1870b57cec5SDimitry Andric         if (!OtherEntry.IndexPlusCost.first &&
1880b57cec5SDimitry Andric             (!OtherEntry.RenameAs ||
18906c3fb27SDimitry Andric              MRI.isSuperRegister(I, OtherEntry.RenameAs))) {
1900b57cec5SDimitry Andric           OtherEntry.IndexPlusCost = IPC;
1910b57cec5SDimitry Andric           OtherEntry.RenameAs = Reg;
1920b57cec5SDimitry Andric         }
1930b57cec5SDimitry Andric       }
1940b57cec5SDimitry Andric     }
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
1990b57cec5SDimitry Andric                                     MutableArrayRef<unsigned> UsedPhysRegs) {
2000b57cec5SDimitry Andric   unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
2010b57cec5SDimitry Andric   unsigned Cost = Entry.IndexPlusCost.second;
2020b57cec5SDimitry Andric   if (RegisterFileIndex) {
2030b57cec5SDimitry Andric     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
2040b57cec5SDimitry Andric     RMT.NumUsedPhysRegs += Cost;
2050b57cec5SDimitry Andric     UsedPhysRegs[RegisterFileIndex] += Cost;
2060b57cec5SDimitry Andric   }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   // Now update the default register mapping tracker.
2090b57cec5SDimitry Andric   RegisterFiles[0].NumUsedPhysRegs += Cost;
2100b57cec5SDimitry Andric   UsedPhysRegs[0] += Cost;
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
2140b57cec5SDimitry Andric                                 MutableArrayRef<unsigned> FreedPhysRegs) {
2150b57cec5SDimitry Andric   unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
2160b57cec5SDimitry Andric   unsigned Cost = Entry.IndexPlusCost.second;
2170b57cec5SDimitry Andric   if (RegisterFileIndex) {
2180b57cec5SDimitry Andric     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
2190b57cec5SDimitry Andric     RMT.NumUsedPhysRegs -= Cost;
2200b57cec5SDimitry Andric     FreedPhysRegs[RegisterFileIndex] += Cost;
2210b57cec5SDimitry Andric   }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   // Now update the default register mapping tracker.
2240b57cec5SDimitry Andric   RegisterFiles[0].NumUsedPhysRegs -= Cost;
2250b57cec5SDimitry Andric   FreedPhysRegs[0] += Cost;
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric void RegisterFile::addRegisterWrite(WriteRef Write,
2290b57cec5SDimitry Andric                                     MutableArrayRef<unsigned> UsedPhysRegs) {
2300b57cec5SDimitry Andric   WriteState &WS = *Write.getWriteState();
2318bcb0991SDimitry Andric   MCPhysReg RegID = WS.getRegisterID();
232fe6060f1SDimitry Andric 
233fe6060f1SDimitry Andric   // This allows InstrPostProcess to remove register Defs
234fe6060f1SDimitry Andric   // by setting their RegisterID to 0.
235fe6060f1SDimitry Andric   if (!RegID)
236fe6060f1SDimitry Andric     return;
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   LLVM_DEBUG({
239fe6060f1SDimitry Andric     dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "
240fe6060f1SDimitry Andric            << MRI.getName(RegID) << "]\n";
2410b57cec5SDimitry Andric   });
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   // If RenameAs is equal to RegID, then RegID is subject to register renaming
2440b57cec5SDimitry Andric   // and false dependencies on RegID are all eliminated.
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   // If RenameAs references the invalid register, then we optimistically assume
2470b57cec5SDimitry Andric   // that it can be renamed. In the absence of tablegen descriptors for register
2480b57cec5SDimitry Andric   // files, RenameAs is always set to the invalid register ID.  In all other
2490b57cec5SDimitry Andric   // cases, RenameAs must be either equal to RegID, or it must reference a
2500b57cec5SDimitry Andric   // super-register of RegID.
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   // If RenameAs is a super-register of RegID, then a write to RegID has always
2530b57cec5SDimitry Andric   // a false dependency on RenameAs. The only exception is for when the write
2540b57cec5SDimitry Andric   // implicitly clears the upper portion of the underlying register.
2550b57cec5SDimitry Andric   // If a write clears its super-registers, then it is renamed as `RenameAs`.
2560b57cec5SDimitry Andric   bool IsWriteZero = WS.isWriteZero();
2570b57cec5SDimitry Andric   bool IsEliminated = WS.isEliminated();
2580b57cec5SDimitry Andric   bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
2590b57cec5SDimitry Andric   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
2600b57cec5SDimitry Andric   WS.setPRF(RRI.IndexPlusCost.first);
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   if (RRI.RenameAs && RRI.RenameAs != RegID) {
2630b57cec5SDimitry Andric     RegID = RRI.RenameAs;
2640b57cec5SDimitry Andric     WriteRef &OtherWrite = RegisterMappings[RegID].first;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric     if (!WS.clearsSuperRegisters()) {
2670b57cec5SDimitry Andric       // The processor keeps the definition of `RegID` together with register
2680b57cec5SDimitry Andric       // `RenameAs`. Since this partial write is not renamed, no physical
2690b57cec5SDimitry Andric       // register is allocated.
2700b57cec5SDimitry Andric       ShouldAllocatePhysRegs = false;
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric       WriteState *OtherWS = OtherWrite.getWriteState();
2730b57cec5SDimitry Andric       if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
2740b57cec5SDimitry Andric         // This partial write has a false dependency on RenameAs.
2750b57cec5SDimitry Andric         assert(!IsEliminated && "Unexpected partial update!");
2760b57cec5SDimitry Andric         OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);
2770b57cec5SDimitry Andric       }
2780b57cec5SDimitry Andric     }
2790b57cec5SDimitry Andric   }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   // Update zero registers.
2828bcb0991SDimitry Andric   MCPhysReg ZeroRegisterID =
2830b57cec5SDimitry Andric       WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
284e8d8bef9SDimitry Andric   ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
28506c3fb27SDimitry Andric   for (MCPhysReg I : MRI.subregs(ZeroRegisterID))
28606c3fb27SDimitry Andric     ZeroRegisters.setBitVal(I, IsWriteZero);
2870b57cec5SDimitry Andric 
288fe6060f1SDimitry Andric   // If this move has been eliminated, then method tryEliminateMoveOrSwap should
289fe6060f1SDimitry Andric   // have already updated all the register mappings.
2900b57cec5SDimitry Andric   if (!IsEliminated) {
291349cc55cSDimitry Andric     // Check if this is one of multiple writes performed by this
292349cc55cSDimitry Andric     // instruction to register RegID.
293349cc55cSDimitry Andric     const WriteRef &OtherWrite = RegisterMappings[RegID].first;
294349cc55cSDimitry Andric     const WriteState *OtherWS = OtherWrite.getWriteState();
295349cc55cSDimitry Andric     if (OtherWS && OtherWrite.getSourceIndex() == Write.getSourceIndex()) {
296349cc55cSDimitry Andric       if (OtherWS->getLatency() > WS.getLatency()) {
297349cc55cSDimitry Andric         // Conservatively keep the slowest write on RegID.
298349cc55cSDimitry Andric         if (ShouldAllocatePhysRegs)
299349cc55cSDimitry Andric           allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
300349cc55cSDimitry Andric         return;
301349cc55cSDimitry Andric       }
302349cc55cSDimitry Andric     }
303349cc55cSDimitry Andric 
3040b57cec5SDimitry Andric     // Update the mapping for register RegID including its sub-registers.
3050b57cec5SDimitry Andric     RegisterMappings[RegID].first = Write;
3060b57cec5SDimitry Andric     RegisterMappings[RegID].second.AliasRegID = 0U;
30706c3fb27SDimitry Andric     for (MCPhysReg I : MRI.subregs(RegID)) {
30806c3fb27SDimitry Andric       RegisterMappings[I].first = Write;
30906c3fb27SDimitry Andric       RegisterMappings[I].second.AliasRegID = 0U;
3100b57cec5SDimitry Andric     }
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric     // No physical registers are allocated for instructions that are optimized
3130b57cec5SDimitry Andric     // in hardware. For example, zero-latency data-dependency breaking
3140b57cec5SDimitry Andric     // instructions don't consume physical registers.
3150b57cec5SDimitry Andric     if (ShouldAllocatePhysRegs)
3160b57cec5SDimitry Andric       allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   if (!WS.clearsSuperRegisters())
3200b57cec5SDimitry Andric     return;
3210b57cec5SDimitry Andric 
32206c3fb27SDimitry Andric   for (MCPhysReg I : MRI.superregs(RegID)) {
3230b57cec5SDimitry Andric     if (!IsEliminated) {
32406c3fb27SDimitry Andric       RegisterMappings[I].first = Write;
32506c3fb27SDimitry Andric       RegisterMappings[I].second.AliasRegID = 0U;
3260b57cec5SDimitry Andric     }
3270b57cec5SDimitry Andric 
32806c3fb27SDimitry Andric     ZeroRegisters.setBitVal(I, IsWriteZero);
3290b57cec5SDimitry Andric   }
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric void RegisterFile::removeRegisterWrite(
3330b57cec5SDimitry Andric     const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
3340b57cec5SDimitry Andric   // Early exit if this write was eliminated. A write eliminated at register
3350b57cec5SDimitry Andric   // renaming stage generates an alias, and it is not added to the PRF.
3360b57cec5SDimitry Andric   if (WS.isEliminated())
3370b57cec5SDimitry Andric     return;
3380b57cec5SDimitry Andric 
3398bcb0991SDimitry Andric   MCPhysReg RegID = WS.getRegisterID();
3400b57cec5SDimitry Andric 
341fe6060f1SDimitry Andric   // This allows InstrPostProcess to remove register Defs
342fe6060f1SDimitry Andric   // by setting their RegisterID to 0.
343fe6060f1SDimitry Andric   if (!RegID)
344fe6060f1SDimitry Andric     return;
345fe6060f1SDimitry Andric 
3460b57cec5SDimitry Andric   assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
3470b57cec5SDimitry Andric          "Invalidating a write of unknown cycles!");
3480b57cec5SDimitry Andric   assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   bool ShouldFreePhysRegs = !WS.isWriteZero();
3518bcb0991SDimitry Andric   MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
3520b57cec5SDimitry Andric   if (RenameAs && RenameAs != RegID) {
3530b57cec5SDimitry Andric     RegID = RenameAs;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric     if (!WS.clearsSuperRegisters()) {
3560b57cec5SDimitry Andric       // Keep the definition of `RegID` together with register `RenameAs`.
3570b57cec5SDimitry Andric       ShouldFreePhysRegs = false;
3580b57cec5SDimitry Andric     }
3590b57cec5SDimitry Andric   }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   if (ShouldFreePhysRegs)
3620b57cec5SDimitry Andric     freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   WriteRef &WR = RegisterMappings[RegID].first;
3650b57cec5SDimitry Andric   if (WR.getWriteState() == &WS)
366fe6060f1SDimitry Andric     WR.commit();
3670b57cec5SDimitry Andric 
36806c3fb27SDimitry Andric   for (MCPhysReg I : MRI.subregs(RegID)) {
36906c3fb27SDimitry Andric     WriteRef &OtherWR = RegisterMappings[I].first;
3700b57cec5SDimitry Andric     if (OtherWR.getWriteState() == &WS)
371fe6060f1SDimitry Andric       OtherWR.commit();
3720b57cec5SDimitry Andric   }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   if (!WS.clearsSuperRegisters())
3750b57cec5SDimitry Andric     return;
3760b57cec5SDimitry Andric 
37706c3fb27SDimitry Andric   for (MCPhysReg I : MRI.superregs(RegID)) {
37806c3fb27SDimitry Andric     WriteRef &OtherWR = RegisterMappings[I].first;
3790b57cec5SDimitry Andric     if (OtherWR.getWriteState() == &WS)
380fe6060f1SDimitry Andric       OtherWR.commit();
3810b57cec5SDimitry Andric   }
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric 
384fe6060f1SDimitry Andric bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,
385fe6060f1SDimitry Andric                                     unsigned RegisterFileIndex) const {
3860b57cec5SDimitry Andric   const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
3870b57cec5SDimitry Andric   const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
388fe6060f1SDimitry Andric   const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
3890b57cec5SDimitry Andric 
390fe6060f1SDimitry Andric   // From and To must be owned by the PRF at index `RegisterFileIndex`.
3910b57cec5SDimitry Andric   const RegisterRenamingInfo &RRIFrom = RMFrom.second;
392fe6060f1SDimitry Andric   if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)
393fe6060f1SDimitry Andric     return false;
394fe6060f1SDimitry Andric 
3950b57cec5SDimitry Andric   const RegisterRenamingInfo &RRITo = RMTo.second;
396fe6060f1SDimitry Andric   if (RRITo.IndexPlusCost.first != RegisterFileIndex)
397fe6060f1SDimitry Andric     return false;
398fe6060f1SDimitry Andric 
399fe6060f1SDimitry Andric   // Early exit if the destination register is from a register class that
400fe6060f1SDimitry Andric   // doesn't allow move elimination.
401fe6060f1SDimitry Andric   if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)
4020b57cec5SDimitry Andric     return false;
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   // We only allow move elimination for writes that update a full physical
4050b57cec5SDimitry Andric   // register. On X86, move elimination is possible with 32-bit general purpose
4060b57cec5SDimitry Andric   // registers because writes to those registers are not partial writes.  If a
4070b57cec5SDimitry Andric   // register move is a partial write, then we conservatively assume that move
4080b57cec5SDimitry Andric   // elimination fails, since it would either trigger a partial update, or the
4090b57cec5SDimitry Andric   // issue of a merge opcode.
4100b57cec5SDimitry Andric   //
4110b57cec5SDimitry Andric   // Note that this constraint may be lifted in future.  For example, we could
4120b57cec5SDimitry Andric   // make this model more flexible, and let users customize the set of registers
4130b57cec5SDimitry Andric   // (i.e. register classes) that allow move elimination.
4140b57cec5SDimitry Andric   //
4150b57cec5SDimitry Andric   // For now, we assume that there is a strong correlation between registers
4160b57cec5SDimitry Andric   // that allow move elimination, and how those same registers are renamed in
4170b57cec5SDimitry Andric   // hardware.
418fe6060f1SDimitry Andric   if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())
4190b57cec5SDimitry Andric     if (!WS.clearsSuperRegisters())
4200b57cec5SDimitry Andric       return false;
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];
423fe6060f1SDimitry Andric   return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);
424fe6060f1SDimitry Andric }
425fe6060f1SDimitry Andric 
426fe6060f1SDimitry Andric bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
427fe6060f1SDimitry Andric                                           MutableArrayRef<ReadState> Reads) {
428fe6060f1SDimitry Andric   if (Writes.size() != Reads.size())
4290b57cec5SDimitry Andric     return false;
4300b57cec5SDimitry Andric 
431fe6060f1SDimitry Andric   // This logic assumes that writes and reads are contributed by a register move
432fe6060f1SDimitry Andric   // or a register swap operation. In particular, it assumes a simple register
433fe6060f1SDimitry Andric   // move if there is only one write.  It assumes a swap operation if there are
434fe6060f1SDimitry Andric   // exactly two writes.
435fe6060f1SDimitry Andric   if (Writes.empty() || Writes.size() > 2)
436fe6060f1SDimitry Andric     return false;
437fe6060f1SDimitry Andric 
438fe6060f1SDimitry Andric   // All registers must be owned by the same PRF.
439fe6060f1SDimitry Andric   const RegisterRenamingInfo &RRInfo =
440fe6060f1SDimitry Andric       RegisterMappings[Writes[0].getRegisterID()].second;
441fe6060f1SDimitry Andric   unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;
442fe6060f1SDimitry Andric   RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
443fe6060f1SDimitry Andric 
444fe6060f1SDimitry Andric   // Early exit if the PRF cannot eliminate more moves/xchg in this cycle.
445fe6060f1SDimitry Andric   if (RMT.MaxMoveEliminatedPerCycle &&
446fe6060f1SDimitry Andric       (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)
447fe6060f1SDimitry Andric     return false;
448fe6060f1SDimitry Andric 
449fe6060f1SDimitry Andric   for (size_t I = 0, E = Writes.size(); I < E; ++I) {
450fe6060f1SDimitry Andric     const ReadState &RS = Reads[I];
451fe6060f1SDimitry Andric     const WriteState &WS = Writes[E - (I + 1)];
452fe6060f1SDimitry Andric     if (!canEliminateMove(WS, RS, RegisterFileIndex))
453fe6060f1SDimitry Andric       return false;
454fe6060f1SDimitry Andric   }
455fe6060f1SDimitry Andric 
456fe6060f1SDimitry Andric   for (size_t I = 0, E = Writes.size(); I < E; ++I) {
457fe6060f1SDimitry Andric     ReadState &RS = Reads[I];
458fe6060f1SDimitry Andric     WriteState &WS = Writes[E - (I + 1)];
459fe6060f1SDimitry Andric 
460fe6060f1SDimitry Andric     const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
461fe6060f1SDimitry Andric     const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
462fe6060f1SDimitry Andric     const RegisterRenamingInfo &RRIFrom = RMFrom.second;
463fe6060f1SDimitry Andric     const RegisterRenamingInfo &RRITo = RMTo.second;
464fe6060f1SDimitry Andric 
4650b57cec5SDimitry Andric     // Construct an alias.
4660b57cec5SDimitry Andric     MCPhysReg AliasedReg =
4670b57cec5SDimitry Andric         RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();
4680b57cec5SDimitry Andric     MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric     const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;
4710b57cec5SDimitry Andric     if (RMAlias.AliasRegID)
4720b57cec5SDimitry Andric       AliasedReg = RMAlias.AliasRegID;
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric     RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
47506c3fb27SDimitry Andric     for (MCPhysReg I : MRI.subregs(AliasReg))
47606c3fb27SDimitry Andric       RegisterMappings[I].second.AliasRegID = AliasedReg;
4770b57cec5SDimitry Andric 
478fe6060f1SDimitry Andric     if (ZeroRegisters[RS.getRegisterID()]) {
4790b57cec5SDimitry Andric       WS.setWriteZero();
4800b57cec5SDimitry Andric       RS.setReadZero();
4810b57cec5SDimitry Andric     }
482fe6060f1SDimitry Andric 
4830b57cec5SDimitry Andric     WS.setEliminated();
4840b57cec5SDimitry Andric     RMT.NumMoveEliminated++;
485fe6060f1SDimitry Andric   }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric   return true;
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric 
490fe6060f1SDimitry Andric unsigned WriteRef::getWriteBackCycle() const {
491fe6060f1SDimitry Andric   assert(hasKnownWriteBackCycle() && "Instruction not executed!");
492fe6060f1SDimitry Andric   assert((!Write || Write->getCyclesLeft() <= 0) &&
493fe6060f1SDimitry Andric          "Inconsistent state found!");
494fe6060f1SDimitry Andric   return WriteBackCycle;
495fe6060f1SDimitry Andric }
496fe6060f1SDimitry Andric 
497fe6060f1SDimitry Andric unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {
498fe6060f1SDimitry Andric   assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");
499fe6060f1SDimitry Andric   return CurrentCycle - WR.getWriteBackCycle();
500fe6060f1SDimitry Andric }
501fe6060f1SDimitry Andric 
502fe6060f1SDimitry Andric void RegisterFile::collectWrites(
503fe6060f1SDimitry Andric     const MCSubtargetInfo &STI, const ReadState &RS,
504fe6060f1SDimitry Andric     SmallVectorImpl<WriteRef> &Writes,
505fe6060f1SDimitry Andric     SmallVectorImpl<WriteRef> &CommittedWrites) const {
506fe6060f1SDimitry Andric   const ReadDescriptor &RD = RS.getDescriptor();
507fe6060f1SDimitry Andric   const MCSchedModel &SM = STI.getSchedModel();
508fe6060f1SDimitry Andric   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
5098bcb0991SDimitry Andric   MCPhysReg RegID = RS.getRegisterID();
5100b57cec5SDimitry Andric   assert(RegID && RegID < RegisterMappings.size());
511fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "
5120b57cec5SDimitry Andric                     << MRI.getName(RegID) << '\n');
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric   // Check if this is an alias.
5150b57cec5SDimitry Andric   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
5160b57cec5SDimitry Andric   if (RRI.AliasRegID)
5170b57cec5SDimitry Andric     RegID = RRI.AliasRegID;
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric   const WriteRef &WR = RegisterMappings[RegID].first;
520fe6060f1SDimitry Andric   if (WR.getWriteState()) {
5210b57cec5SDimitry Andric     Writes.push_back(WR);
522fe6060f1SDimitry Andric   } else if (WR.hasKnownWriteBackCycle()) {
523fe6060f1SDimitry Andric     unsigned WriteResID = WR.getWriteResourceID();
524fe6060f1SDimitry Andric     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
525fe6060f1SDimitry Andric     if (ReadAdvance < 0) {
526fe6060f1SDimitry Andric       unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
527fe6060f1SDimitry Andric       if (Elapsed < static_cast<unsigned>(-ReadAdvance))
528fe6060f1SDimitry Andric         CommittedWrites.push_back(WR);
529fe6060f1SDimitry Andric     }
530fe6060f1SDimitry Andric   }
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   // Handle potential partial register updates.
53306c3fb27SDimitry Andric   for (MCPhysReg I : MRI.subregs(RegID)) {
53406c3fb27SDimitry Andric     const WriteRef &WR = RegisterMappings[I].first;
535fe6060f1SDimitry Andric     if (WR.getWriteState()) {
5360b57cec5SDimitry Andric       Writes.push_back(WR);
537fe6060f1SDimitry Andric     } else if (WR.hasKnownWriteBackCycle()) {
538fe6060f1SDimitry Andric       unsigned WriteResID = WR.getWriteResourceID();
539fe6060f1SDimitry Andric       int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
540fe6060f1SDimitry Andric       if (ReadAdvance < 0) {
541fe6060f1SDimitry Andric         unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
542fe6060f1SDimitry Andric         if (Elapsed < static_cast<unsigned>(-ReadAdvance))
543fe6060f1SDimitry Andric           CommittedWrites.push_back(WR);
544fe6060f1SDimitry Andric       }
545fe6060f1SDimitry Andric     }
5460b57cec5SDimitry Andric   }
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric   // Remove duplicate entries and resize the input vector.
5490b57cec5SDimitry Andric   if (Writes.size() > 1) {
5500b57cec5SDimitry Andric     sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) {
5510b57cec5SDimitry Andric       return Lhs.getWriteState() < Rhs.getWriteState();
5520b57cec5SDimitry Andric     });
553*0fca6ea1SDimitry Andric     auto It = llvm::unique(Writes);
5540b57cec5SDimitry Andric     Writes.resize(std::distance(Writes.begin(), It));
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   LLVM_DEBUG({
5580b57cec5SDimitry Andric     for (const WriteRef &WR : Writes) {
5590b57cec5SDimitry Andric       const WriteState &WS = *WR.getWriteState();
5600b57cec5SDimitry Andric       dbgs() << "[PRF] Found a dependent use of Register "
5610b57cec5SDimitry Andric              << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"
5620b57cec5SDimitry Andric              << WR.getSourceIndex() << ")\n";
5630b57cec5SDimitry Andric     }
5640b57cec5SDimitry Andric   });
5650b57cec5SDimitry Andric }
5660b57cec5SDimitry Andric 
567fe6060f1SDimitry Andric RegisterFile::RAWHazard
568fe6060f1SDimitry Andric RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI,
569fe6060f1SDimitry Andric                               const ReadState &RS) const {
570fe6060f1SDimitry Andric   RAWHazard Hazard;
571fe6060f1SDimitry Andric   SmallVector<WriteRef, 4> Writes;
572fe6060f1SDimitry Andric   SmallVector<WriteRef, 4> CommittedWrites;
573fe6060f1SDimitry Andric 
574fe6060f1SDimitry Andric   const MCSchedModel &SM = STI.getSchedModel();
575fe6060f1SDimitry Andric   const ReadDescriptor &RD = RS.getDescriptor();
576fe6060f1SDimitry Andric   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
577fe6060f1SDimitry Andric 
578fe6060f1SDimitry Andric   collectWrites(STI, RS, Writes, CommittedWrites);
579fe6060f1SDimitry Andric   for (const WriteRef &WR : Writes) {
580fe6060f1SDimitry Andric     const WriteState *WS = WR.getWriteState();
581fe6060f1SDimitry Andric     unsigned WriteResID = WS->getWriteResourceID();
582fe6060f1SDimitry Andric     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
583fe6060f1SDimitry Andric 
584fe6060f1SDimitry Andric     if (WS->getCyclesLeft() == UNKNOWN_CYCLES) {
585fe6060f1SDimitry Andric       if (Hazard.isValid())
586fe6060f1SDimitry Andric         continue;
587fe6060f1SDimitry Andric 
588fe6060f1SDimitry Andric       Hazard.RegisterID = WR.getRegisterID();
589fe6060f1SDimitry Andric       Hazard.CyclesLeft = UNKNOWN_CYCLES;
590fe6060f1SDimitry Andric       continue;
591fe6060f1SDimitry Andric     }
592fe6060f1SDimitry Andric 
593fe6060f1SDimitry Andric     int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;
594fe6060f1SDimitry Andric     if (CyclesLeft > 0) {
595fe6060f1SDimitry Andric       if (Hazard.CyclesLeft < CyclesLeft) {
596fe6060f1SDimitry Andric         Hazard.RegisterID = WR.getRegisterID();
597fe6060f1SDimitry Andric         Hazard.CyclesLeft = CyclesLeft;
598fe6060f1SDimitry Andric       }
599fe6060f1SDimitry Andric     }
600fe6060f1SDimitry Andric   }
601fe6060f1SDimitry Andric   Writes.clear();
602fe6060f1SDimitry Andric 
603fe6060f1SDimitry Andric   for (const WriteRef &WR : CommittedWrites) {
604fe6060f1SDimitry Andric     unsigned WriteResID = WR.getWriteResourceID();
605fe6060f1SDimitry Andric     int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
606fe6060f1SDimitry Andric     int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR));
607fe6060f1SDimitry Andric     int CyclesLeft = NegReadAdvance - Elapsed;
608fe6060f1SDimitry Andric     assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");
609fe6060f1SDimitry Andric     if (Hazard.CyclesLeft < CyclesLeft) {
610fe6060f1SDimitry Andric       Hazard.RegisterID = WR.getRegisterID();
611fe6060f1SDimitry Andric       Hazard.CyclesLeft = CyclesLeft;
612fe6060f1SDimitry Andric     }
613fe6060f1SDimitry Andric   }
614fe6060f1SDimitry Andric 
615fe6060f1SDimitry Andric   return Hazard;
616fe6060f1SDimitry Andric }
617fe6060f1SDimitry Andric 
6180b57cec5SDimitry Andric void RegisterFile::addRegisterRead(ReadState &RS,
6190b57cec5SDimitry Andric                                    const MCSubtargetInfo &STI) const {
6208bcb0991SDimitry Andric   MCPhysReg RegID = RS.getRegisterID();
6210b57cec5SDimitry Andric   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
6220b57cec5SDimitry Andric   RS.setPRF(RRI.IndexPlusCost.first);
6230b57cec5SDimitry Andric   if (RS.isIndependentFromDef())
6240b57cec5SDimitry Andric     return;
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   if (ZeroRegisters[RS.getRegisterID()])
6270b57cec5SDimitry Andric     RS.setReadZero();
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric   SmallVector<WriteRef, 4> DependentWrites;
630fe6060f1SDimitry Andric   SmallVector<WriteRef, 4> CompletedWrites;
631fe6060f1SDimitry Andric   collectWrites(STI, RS, DependentWrites, CompletedWrites);
632fe6060f1SDimitry Andric   RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   // We know that this read depends on all the writes in DependentWrites.
6350b57cec5SDimitry Andric   // For each write, check if we have ReadAdvance information, and use it
636fe6060f1SDimitry Andric   // to figure out in how many cycles this read will be available.
6370b57cec5SDimitry Andric   const ReadDescriptor &RD = RS.getDescriptor();
6380b57cec5SDimitry Andric   const MCSchedModel &SM = STI.getSchedModel();
6390b57cec5SDimitry Andric   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
6400b57cec5SDimitry Andric   for (WriteRef &WR : DependentWrites) {
641fe6060f1SDimitry Andric     unsigned WriteResID = WR.getWriteResourceID();
6420b57cec5SDimitry Andric     WriteState &WS = *WR.getWriteState();
6430b57cec5SDimitry Andric     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
6440b57cec5SDimitry Andric     WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);
6450b57cec5SDimitry Andric   }
646fe6060f1SDimitry Andric 
647fe6060f1SDimitry Andric   for (WriteRef &WR : CompletedWrites) {
648fe6060f1SDimitry Andric     unsigned WriteResID = WR.getWriteResourceID();
649fe6060f1SDimitry Andric     assert(WR.hasKnownWriteBackCycle() && "Invalid write!");
650fe6060f1SDimitry Andric     assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);
651fe6060f1SDimitry Andric     unsigned ReadAdvance = static_cast<unsigned>(
652fe6060f1SDimitry Andric         -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));
653fe6060f1SDimitry Andric     unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
654fe6060f1SDimitry Andric     assert(Elapsed < ReadAdvance && "Should not have been added to the set!");
655fe6060f1SDimitry Andric     RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),
656fe6060f1SDimitry Andric                        ReadAdvance - Elapsed);
657fe6060f1SDimitry Andric   }
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
6608bcb0991SDimitry Andric unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {
6610b57cec5SDimitry Andric   SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   // Find how many new mappings must be created for each register file.
6648bcb0991SDimitry Andric   for (const MCPhysReg RegID : Regs) {
6650b57cec5SDimitry Andric     const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
6660b57cec5SDimitry Andric     const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
6670b57cec5SDimitry Andric     if (Entry.first)
6680b57cec5SDimitry Andric       NumPhysRegs[Entry.first] += Entry.second;
6690b57cec5SDimitry Andric     NumPhysRegs[0] += Entry.second;
6700b57cec5SDimitry Andric   }
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   unsigned Response = 0;
6730b57cec5SDimitry Andric   for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
6740b57cec5SDimitry Andric     unsigned NumRegs = NumPhysRegs[I];
6750b57cec5SDimitry Andric     if (!NumRegs)
6760b57cec5SDimitry Andric       continue;
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric     const RegisterMappingTracker &RMT = RegisterFiles[I];
6790b57cec5SDimitry Andric     if (!RMT.NumPhysRegs) {
6800b57cec5SDimitry Andric       // The register file has an unbounded number of microarchitectural
6810b57cec5SDimitry Andric       // registers.
6820b57cec5SDimitry Andric       continue;
6830b57cec5SDimitry Andric     }
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric     if (RMT.NumPhysRegs < NumRegs) {
6860b57cec5SDimitry Andric       // The current register file is too small. This may occur if the number of
6870b57cec5SDimitry Andric       // microarchitectural registers in register file #0 was changed by the
6880b57cec5SDimitry Andric       // users via flag -reg-file-size. Alternatively, the scheduling model
6890b57cec5SDimitry Andric       // specified a too small number of registers for this register file.
690fe6060f1SDimitry Andric       LLVM_DEBUG(
691fe6060f1SDimitry Andric           dbgs() << "[PRF] Not enough registers in the register file.\n");
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric       // FIXME: Normalize the instruction register count to match the
6940b57cec5SDimitry Andric       // NumPhysRegs value.  This is a highly unusual case, and is not expected
6950b57cec5SDimitry Andric       // to occur.  This normalization is hiding an inconsistency in either the
6960b57cec5SDimitry Andric       // scheduling model or in the value that the user might have specified
6970b57cec5SDimitry Andric       // for NumPhysRegs.
6980b57cec5SDimitry Andric       NumRegs = RMT.NumPhysRegs;
6990b57cec5SDimitry Andric     }
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric     if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
7020b57cec5SDimitry Andric       Response |= (1U << I);
7030b57cec5SDimitry Andric   }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   return Response;
7060b57cec5SDimitry Andric }
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric #ifndef NDEBUG
709fe6060f1SDimitry Andric void WriteRef::dump() const {
710fe6060f1SDimitry Andric   dbgs() << "IID=" << getSourceIndex() << ' ';
711fe6060f1SDimitry Andric   if (isValid())
712fe6060f1SDimitry Andric     getWriteState()->dump();
713fe6060f1SDimitry Andric   else
714fe6060f1SDimitry Andric     dbgs() << "(null)";
715fe6060f1SDimitry Andric }
716fe6060f1SDimitry Andric 
7170b57cec5SDimitry Andric void RegisterFile::dump() const {
7180b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
7190b57cec5SDimitry Andric     const RegisterMapping &RM = RegisterMappings[I];
7200b57cec5SDimitry Andric     const RegisterRenamingInfo &RRI = RM.second;
7210b57cec5SDimitry Andric     if (ZeroRegisters[I]) {
7220b57cec5SDimitry Andric       dbgs() << MRI.getName(I) << ", " << I
7230b57cec5SDimitry Andric              << ", PRF=" << RRI.IndexPlusCost.first
7240b57cec5SDimitry Andric              << ", Cost=" << RRI.IndexPlusCost.second
7250b57cec5SDimitry Andric              << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
7260b57cec5SDimitry Andric              << ",";
7270b57cec5SDimitry Andric       RM.first.dump();
7280b57cec5SDimitry Andric       dbgs() << '\n';
7290b57cec5SDimitry Andric     }
7300b57cec5SDimitry Andric   }
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric   for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
7330b57cec5SDimitry Andric     dbgs() << "Register File #" << I;
7340b57cec5SDimitry Andric     const RegisterMappingTracker &RMT = RegisterFiles[I];
7350b57cec5SDimitry Andric     dbgs() << "\n  TotalMappings:        " << RMT.NumPhysRegs
7360b57cec5SDimitry Andric            << "\n  NumUsedMappings:      " << RMT.NumUsedPhysRegs << '\n';
7370b57cec5SDimitry Andric   }
7380b57cec5SDimitry Andric }
7390b57cec5SDimitry Andric #endif
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric } // namespace mca
7420b57cec5SDimitry Andric } // namespace llvm
743