1cc5e6a72SClement Courbet //===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//
2cc5e6a72SClement Courbet //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cc5e6a72SClement Courbet //
7cc5e6a72SClement Courbet //===----------------------------------------------------------------------===//
8cc5e6a72SClement Courbet /// \file
9cc5e6a72SClement Courbet ///
10cc5e6a72SClement Courbet /// This file defines a register mapping file class.  This class is responsible
11cc5e6a72SClement Courbet /// for managing hardware register files and the tracking of data dependencies
12cc5e6a72SClement Courbet /// between registers.
13cc5e6a72SClement Courbet ///
14cc5e6a72SClement Courbet //===----------------------------------------------------------------------===//
15cc5e6a72SClement Courbet 
16cc5e6a72SClement Courbet #include "llvm/MCA/HardwareUnits/RegisterFile.h"
17cc5e6a72SClement Courbet #include "llvm/MCA/Instruction.h"
18cc5e6a72SClement Courbet #include "llvm/Support/Debug.h"
19cc5e6a72SClement Courbet 
20cc5e6a72SClement Courbet #define DEBUG_TYPE "llvm-mca"
21cc5e6a72SClement Courbet 
22cc5e6a72SClement Courbet namespace llvm {
23cc5e6a72SClement Courbet namespace mca {
24cc5e6a72SClement Courbet 
25f5bdc88eSAndrea Di Biagio const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
26f5bdc88eSAndrea Di Biagio 
WriteRef(unsigned SourceIndex,WriteState * WS)27f5bdc88eSAndrea Di Biagio WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
2897a00b7bSAndrea Di Biagio     : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
2997a00b7bSAndrea Di Biagio       Write(WS) {}
30f5bdc88eSAndrea Di Biagio 
commit()31f5bdc88eSAndrea Di Biagio void WriteRef::commit() {
32f5bdc88eSAndrea Di Biagio   assert(Write && Write->isExecuted() && "Cannot commit before write back!");
3350770d8dSAndrea Di Biagio   RegisterID = Write->getRegisterID();
3450770d8dSAndrea Di Biagio   WriteResID = Write->getWriteResourceID();
35f5bdc88eSAndrea Di Biagio   Write = nullptr;
36f5bdc88eSAndrea Di Biagio }
37f5bdc88eSAndrea Di Biagio 
notifyExecuted(unsigned Cycle)38f5bdc88eSAndrea Di Biagio void WriteRef::notifyExecuted(unsigned Cycle) {
39f5bdc88eSAndrea Di Biagio   assert(Write && Write->isExecuted() && "Not executed!");
40f5bdc88eSAndrea Di Biagio   WriteBackCycle = Cycle;
41f5bdc88eSAndrea Di Biagio }
42f5bdc88eSAndrea Di Biagio 
hasKnownWriteBackCycle() const43f5bdc88eSAndrea Di Biagio bool WriteRef::hasKnownWriteBackCycle() const {
44f5bdc88eSAndrea Di Biagio   return isValid() && (!Write || Write->isExecuted());
45f5bdc88eSAndrea Di Biagio }
46f5bdc88eSAndrea Di Biagio 
isWriteZero() const47f5bdc88eSAndrea Di Biagio bool WriteRef::isWriteZero() const {
48f5bdc88eSAndrea Di Biagio   assert(isValid() && "Invalid null WriteState found!");
49f5bdc88eSAndrea Di Biagio   return getWriteState()->isWriteZero();
50f5bdc88eSAndrea Di Biagio }
51f5bdc88eSAndrea Di Biagio 
getWriteResourceID() const52f5bdc88eSAndrea Di Biagio unsigned WriteRef::getWriteResourceID() const {
53f5bdc88eSAndrea Di Biagio   if (Write)
54f5bdc88eSAndrea Di Biagio     return Write->getWriteResourceID();
55f5bdc88eSAndrea Di Biagio   return WriteResID;
56f5bdc88eSAndrea Di Biagio }
57f5bdc88eSAndrea Di Biagio 
getRegisterID() const58f5bdc88eSAndrea Di Biagio MCPhysReg WriteRef::getRegisterID() const {
59f5bdc88eSAndrea Di Biagio   if (Write)
60f5bdc88eSAndrea Di Biagio     return Write->getRegisterID();
61f5bdc88eSAndrea Di Biagio   return RegisterID;
62f5bdc88eSAndrea Di Biagio }
63f5bdc88eSAndrea Di Biagio 
RegisterFile(const MCSchedModel & SM,const MCRegisterInfo & mri,unsigned NumRegs)64cc5e6a72SClement Courbet RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,
65cc5e6a72SClement Courbet                            unsigned NumRegs)
66cc5e6a72SClement Courbet     : MRI(mri),
67cc5e6a72SClement Courbet       RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),
68f5bdc88eSAndrea Di Biagio       ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {
69cc5e6a72SClement Courbet   initialize(SM, NumRegs);
70cc5e6a72SClement Courbet }
71cc5e6a72SClement Courbet 
initialize(const MCSchedModel & SM,unsigned NumRegs)72cc5e6a72SClement Courbet void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
73cc5e6a72SClement Courbet   // Create a default register file that "sees" all the machine registers
74cc5e6a72SClement Courbet   // declared by the target. The number of physical registers in the default
75cc5e6a72SClement Courbet   // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
76cc5e6a72SClement Courbet   // means: this register file has an unbounded number of physical registers.
77cc5e6a72SClement Courbet   RegisterFiles.emplace_back(NumRegs);
78cc5e6a72SClement Courbet   if (!SM.hasExtraProcessorInfo())
79cc5e6a72SClement Courbet     return;
80cc5e6a72SClement Courbet 
81cc5e6a72SClement Courbet   // For each user defined register file, allocate a RegisterMappingTracker
82cc5e6a72SClement Courbet   // object. The size of every register file, as well as the mapping between
83cc5e6a72SClement Courbet   // register files and register classes is specified via tablegen.
84cc5e6a72SClement Courbet   const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
85cc5e6a72SClement Courbet 
86cc5e6a72SClement Courbet   // Skip invalid register file at index 0.
87cc5e6a72SClement Courbet   for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {
88cc5e6a72SClement Courbet     const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
89cc5e6a72SClement Courbet     assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");
90cc5e6a72SClement Courbet 
91cc5e6a72SClement Courbet     // The cost of a register definition is equivalent to the number of
92cc5e6a72SClement Courbet     // physical registers that are allocated at register renaming stage.
93cc5e6a72SClement Courbet     unsigned Length = RF.NumRegisterCostEntries;
94cc5e6a72SClement Courbet     const MCRegisterCostEntry *FirstElt =
95cc5e6a72SClement Courbet         &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
96cc5e6a72SClement Courbet     addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length));
97cc5e6a72SClement Courbet   }
98cc5e6a72SClement Courbet }
99cc5e6a72SClement Courbet 
cycleStart()100cc5e6a72SClement Courbet void RegisterFile::cycleStart() {
101cc5e6a72SClement Courbet   for (RegisterMappingTracker &RMT : RegisterFiles)
102cc5e6a72SClement Courbet     RMT.NumMoveEliminated = 0;
103cc5e6a72SClement Courbet }
104cc5e6a72SClement Courbet 
onInstructionExecuted(Instruction * IS)105f5bdc88eSAndrea Di Biagio void RegisterFile::onInstructionExecuted(Instruction *IS) {
106f5bdc88eSAndrea Di Biagio   assert(IS && IS->isExecuted() && "Unexpected internal state found!");
107f5bdc88eSAndrea Di Biagio   for (WriteState &WS : IS->getDefs()) {
108f5bdc88eSAndrea Di Biagio     if (WS.isEliminated())
109f5bdc88eSAndrea Di Biagio       return;
110f5bdc88eSAndrea Di Biagio 
111f5bdc88eSAndrea Di Biagio     MCPhysReg RegID = WS.getRegisterID();
112dc11d4e6SPatrick Holland 
113dc11d4e6SPatrick Holland     // This allows InstrPostProcess to remove register Defs
114dc11d4e6SPatrick Holland     // by setting their RegisterID to 0.
115dc11d4e6SPatrick Holland     if (!RegID)
116dc11d4e6SPatrick Holland       continue;
117dc11d4e6SPatrick Holland 
118f5bdc88eSAndrea Di Biagio     assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
119f5bdc88eSAndrea Di Biagio            "The number of cycles should be known at this point!");
120f5bdc88eSAndrea Di Biagio     assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
121f5bdc88eSAndrea Di Biagio 
122f5bdc88eSAndrea Di Biagio     MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
123f5bdc88eSAndrea Di Biagio     if (RenameAs && RenameAs != RegID)
124f5bdc88eSAndrea Di Biagio       RegID = RenameAs;
125f5bdc88eSAndrea Di Biagio 
126f5bdc88eSAndrea Di Biagio     WriteRef &WR = RegisterMappings[RegID].first;
127f5bdc88eSAndrea Di Biagio     if (WR.getWriteState() == &WS)
128f5bdc88eSAndrea Di Biagio       WR.notifyExecuted(CurrentCycle);
129f5bdc88eSAndrea Di Biagio 
130f5bdc88eSAndrea Di Biagio     for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
131f5bdc88eSAndrea Di Biagio       WriteRef &OtherWR = RegisterMappings[*I].first;
132f5bdc88eSAndrea Di Biagio       if (OtherWR.getWriteState() == &WS)
133f5bdc88eSAndrea Di Biagio         OtherWR.notifyExecuted(CurrentCycle);
134f5bdc88eSAndrea Di Biagio     }
135f5bdc88eSAndrea Di Biagio 
136f5bdc88eSAndrea Di Biagio     if (!WS.clearsSuperRegisters())
137f5bdc88eSAndrea Di Biagio       continue;
138f5bdc88eSAndrea Di Biagio 
139f5bdc88eSAndrea Di Biagio     for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
140f5bdc88eSAndrea Di Biagio       WriteRef &OtherWR = RegisterMappings[*I].first;
141f5bdc88eSAndrea Di Biagio       if (OtherWR.getWriteState() == &WS)
142f5bdc88eSAndrea Di Biagio         OtherWR.notifyExecuted(CurrentCycle);
143f5bdc88eSAndrea Di Biagio     }
144f5bdc88eSAndrea Di Biagio   }
145f5bdc88eSAndrea Di Biagio }
146f5bdc88eSAndrea Di Biagio 
addRegisterFile(const MCRegisterFileDesc & RF,ArrayRef<MCRegisterCostEntry> Entries)147cc5e6a72SClement Courbet void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,
148cc5e6a72SClement Courbet                                    ArrayRef<MCRegisterCostEntry> Entries) {
149cc5e6a72SClement Courbet   // A default register file is always allocated at index #0. That register file
150cc5e6a72SClement Courbet   // is mainly used to count the total number of mappings created by all
151cc5e6a72SClement Courbet   // register files at runtime. Users can limit the number of available physical
152cc5e6a72SClement Courbet   // registers in register file #0 through the command line flag
153cc5e6a72SClement Courbet   // `-register-file-size`.
154cc5e6a72SClement Courbet   unsigned RegisterFileIndex = RegisterFiles.size();
155cc5e6a72SClement Courbet   RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,
156cc5e6a72SClement Courbet                              RF.AllowZeroMoveEliminationOnly);
157cc5e6a72SClement Courbet 
158cc5e6a72SClement Courbet   // Special case where there is no register class identifier in the set.
159cc5e6a72SClement Courbet   // An empty set of register classes means: this register file contains all
160cc5e6a72SClement Courbet   // the physical registers specified by the target.
161cc5e6a72SClement Courbet   // We optimistically assume that a register can be renamed at the cost of a
162cc5e6a72SClement Courbet   // single physical register. The constructor of RegisterFile ensures that
163cc5e6a72SClement Courbet   // a RegisterMapping exists for each logical register defined by the Target.
164cc5e6a72SClement Courbet   if (Entries.empty())
165cc5e6a72SClement Courbet     return;
166cc5e6a72SClement Courbet 
167cc5e6a72SClement Courbet   // Now update the cost of individual registers.
168cc5e6a72SClement Courbet   for (const MCRegisterCostEntry &RCE : Entries) {
169cc5e6a72SClement Courbet     const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
170cc5e6a72SClement Courbet     for (const MCPhysReg Reg : RC) {
171cc5e6a72SClement Courbet       RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
172cc5e6a72SClement Courbet       IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
173cc5e6a72SClement Courbet       if (IPC.first && IPC.first != RegisterFileIndex) {
174cc5e6a72SClement Courbet         // The only register file that is allowed to overlap is the default
175cc5e6a72SClement Courbet         // register file at index #0. The analysis is inaccurate if register
176cc5e6a72SClement Courbet         // files overlap.
177cc5e6a72SClement Courbet         errs() << "warning: register " << MRI.getName(Reg)
178cc5e6a72SClement Courbet                << " defined in multiple register files.";
179cc5e6a72SClement Courbet       }
180cc5e6a72SClement Courbet       IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
181cc5e6a72SClement Courbet       Entry.RenameAs = Reg;
182cc5e6a72SClement Courbet       Entry.AllowMoveElimination = RCE.AllowMoveElimination;
183cc5e6a72SClement Courbet 
184cc5e6a72SClement Courbet       // Assume the same cost for each sub-register.
185cc5e6a72SClement Courbet       for (MCSubRegIterator I(Reg, &MRI); I.isValid(); ++I) {
186cc5e6a72SClement Courbet         RegisterRenamingInfo &OtherEntry = RegisterMappings[*I].second;
187cc5e6a72SClement Courbet         if (!OtherEntry.IndexPlusCost.first &&
188cc5e6a72SClement Courbet             (!OtherEntry.RenameAs ||
189cc5e6a72SClement Courbet              MRI.isSuperRegister(*I, OtherEntry.RenameAs))) {
190cc5e6a72SClement Courbet           OtherEntry.IndexPlusCost = IPC;
191cc5e6a72SClement Courbet           OtherEntry.RenameAs = Reg;
192cc5e6a72SClement Courbet         }
193cc5e6a72SClement Courbet       }
194cc5e6a72SClement Courbet     }
195cc5e6a72SClement Courbet   }
196cc5e6a72SClement Courbet }
197cc5e6a72SClement Courbet 
allocatePhysRegs(const RegisterRenamingInfo & Entry,MutableArrayRef<unsigned> UsedPhysRegs)198cc5e6a72SClement Courbet void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
199cc5e6a72SClement Courbet                                     MutableArrayRef<unsigned> UsedPhysRegs) {
200cc5e6a72SClement Courbet   unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
201cc5e6a72SClement Courbet   unsigned Cost = Entry.IndexPlusCost.second;
202cc5e6a72SClement Courbet   if (RegisterFileIndex) {
203cc5e6a72SClement Courbet     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
204cc5e6a72SClement Courbet     RMT.NumUsedPhysRegs += Cost;
205cc5e6a72SClement Courbet     UsedPhysRegs[RegisterFileIndex] += Cost;
206cc5e6a72SClement Courbet   }
207cc5e6a72SClement Courbet 
208cc5e6a72SClement Courbet   // Now update the default register mapping tracker.
209cc5e6a72SClement Courbet   RegisterFiles[0].NumUsedPhysRegs += Cost;
210cc5e6a72SClement Courbet   UsedPhysRegs[0] += Cost;
211cc5e6a72SClement Courbet }
212cc5e6a72SClement Courbet 
freePhysRegs(const RegisterRenamingInfo & Entry,MutableArrayRef<unsigned> FreedPhysRegs)213cc5e6a72SClement Courbet void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
214cc5e6a72SClement Courbet                                 MutableArrayRef<unsigned> FreedPhysRegs) {
215cc5e6a72SClement Courbet   unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
216cc5e6a72SClement Courbet   unsigned Cost = Entry.IndexPlusCost.second;
217cc5e6a72SClement Courbet   if (RegisterFileIndex) {
218cc5e6a72SClement Courbet     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
219cc5e6a72SClement Courbet     RMT.NumUsedPhysRegs -= Cost;
220cc5e6a72SClement Courbet     FreedPhysRegs[RegisterFileIndex] += Cost;
221cc5e6a72SClement Courbet   }
222cc5e6a72SClement Courbet 
223cc5e6a72SClement Courbet   // Now update the default register mapping tracker.
224cc5e6a72SClement Courbet   RegisterFiles[0].NumUsedPhysRegs -= Cost;
225cc5e6a72SClement Courbet   FreedPhysRegs[0] += Cost;
226cc5e6a72SClement Courbet }
227cc5e6a72SClement Courbet 
addRegisterWrite(WriteRef Write,MutableArrayRef<unsigned> UsedPhysRegs)228cc5e6a72SClement Courbet void RegisterFile::addRegisterWrite(WriteRef Write,
229cc5e6a72SClement Courbet                                     MutableArrayRef<unsigned> UsedPhysRegs) {
230cc5e6a72SClement Courbet   WriteState &WS = *Write.getWriteState();
231589cb004SAndrea Di Biagio   MCPhysReg RegID = WS.getRegisterID();
232dc11d4e6SPatrick Holland 
233dc11d4e6SPatrick Holland   // This allows InstrPostProcess to remove register Defs
234dc11d4e6SPatrick Holland   // by setting their RegisterID to 0.
235dc11d4e6SPatrick Holland   if (!RegID)
236dc11d4e6SPatrick Holland     return;
237cc5e6a72SClement Courbet 
238cc5e6a72SClement Courbet   LLVM_DEBUG({
23950770d8dSAndrea Di Biagio     dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "
24050770d8dSAndrea Di Biagio            << MRI.getName(RegID) << "]\n";
241cc5e6a72SClement Courbet   });
242cc5e6a72SClement Courbet 
243cc5e6a72SClement Courbet   // If RenameAs is equal to RegID, then RegID is subject to register renaming
244cc5e6a72SClement Courbet   // and false dependencies on RegID are all eliminated.
245cc5e6a72SClement Courbet 
246cc5e6a72SClement Courbet   // If RenameAs references the invalid register, then we optimistically assume
247cc5e6a72SClement Courbet   // that it can be renamed. In the absence of tablegen descriptors for register
248cc5e6a72SClement Courbet   // files, RenameAs is always set to the invalid register ID.  In all other
249cc5e6a72SClement Courbet   // cases, RenameAs must be either equal to RegID, or it must reference a
250cc5e6a72SClement Courbet   // super-register of RegID.
251cc5e6a72SClement Courbet 
252cc5e6a72SClement Courbet   // If RenameAs is a super-register of RegID, then a write to RegID has always
253cc5e6a72SClement Courbet   // a false dependency on RenameAs. The only exception is for when the write
254cc5e6a72SClement Courbet   // implicitly clears the upper portion of the underlying register.
255cc5e6a72SClement Courbet   // If a write clears its super-registers, then it is renamed as `RenameAs`.
256cc5e6a72SClement Courbet   bool IsWriteZero = WS.isWriteZero();
257cc5e6a72SClement Courbet   bool IsEliminated = WS.isEliminated();
258cc5e6a72SClement Courbet   bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
259cc5e6a72SClement Courbet   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
260cc5e6a72SClement Courbet   WS.setPRF(RRI.IndexPlusCost.first);
261cc5e6a72SClement Courbet 
262cc5e6a72SClement Courbet   if (RRI.RenameAs && RRI.RenameAs != RegID) {
263cc5e6a72SClement Courbet     RegID = RRI.RenameAs;
264cc5e6a72SClement Courbet     WriteRef &OtherWrite = RegisterMappings[RegID].first;
265cc5e6a72SClement Courbet 
266cc5e6a72SClement Courbet     if (!WS.clearsSuperRegisters()) {
267cc5e6a72SClement Courbet       // The processor keeps the definition of `RegID` together with register
268cc5e6a72SClement Courbet       // `RenameAs`. Since this partial write is not renamed, no physical
269cc5e6a72SClement Courbet       // register is allocated.
270cc5e6a72SClement Courbet       ShouldAllocatePhysRegs = false;
271cc5e6a72SClement Courbet 
272cc5e6a72SClement Courbet       WriteState *OtherWS = OtherWrite.getWriteState();
273cc5e6a72SClement Courbet       if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
274cc5e6a72SClement Courbet         // This partial write has a false dependency on RenameAs.
275cc5e6a72SClement Courbet         assert(!IsEliminated && "Unexpected partial update!");
2767a950ed5SAndrea Di Biagio         OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);
277cc5e6a72SClement Courbet       }
278cc5e6a72SClement Courbet     }
279cc5e6a72SClement Courbet   }
280cc5e6a72SClement Courbet 
281cc5e6a72SClement Courbet   // Update zero registers.
282589cb004SAndrea Di Biagio   MCPhysReg ZeroRegisterID =
283cc5e6a72SClement Courbet       WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
284099c089dSJay Foad   ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
285cc5e6a72SClement Courbet   for (MCSubRegIterator I(ZeroRegisterID, &MRI); I.isValid(); ++I)
286099c089dSJay Foad     ZeroRegisters.setBitVal(*I, IsWriteZero);
287cc5e6a72SClement Courbet 
2889ceea666SAndrea Di Biagio   // If this move has been eliminated, then method tryEliminateMoveOrSwap should
2899ceea666SAndrea Di Biagio   // have already updated all the register mappings.
290cc5e6a72SClement Courbet   if (!IsEliminated) {
2914a5b1917SAndrea Di Biagio     // Check if this is one of multiple writes performed by this
2924a5b1917SAndrea Di Biagio     // instruction to register RegID.
2934a5b1917SAndrea Di Biagio     const WriteRef &OtherWrite = RegisterMappings[RegID].first;
2944a5b1917SAndrea Di Biagio     const WriteState *OtherWS = OtherWrite.getWriteState();
2954a5b1917SAndrea Di Biagio     if (OtherWS && OtherWrite.getSourceIndex() == Write.getSourceIndex()) {
2964a5b1917SAndrea Di Biagio       if (OtherWS->getLatency() > WS.getLatency()) {
297*1eb75362SAndrea Di Biagio         // Conservatively keep the slowest write on RegID.
298*1eb75362SAndrea Di Biagio         if (ShouldAllocatePhysRegs)
299*1eb75362SAndrea Di Biagio           allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
3004a5b1917SAndrea Di Biagio         return;
3014a5b1917SAndrea Di Biagio       }
3024a5b1917SAndrea Di Biagio     }
3034a5b1917SAndrea Di Biagio 
304cc5e6a72SClement Courbet     // Update the mapping for register RegID including its sub-registers.
305cc5e6a72SClement Courbet     RegisterMappings[RegID].first = Write;
306cc5e6a72SClement Courbet     RegisterMappings[RegID].second.AliasRegID = 0U;
307cc5e6a72SClement Courbet     for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
308cc5e6a72SClement Courbet       RegisterMappings[*I].first = Write;
309cc5e6a72SClement Courbet       RegisterMappings[*I].second.AliasRegID = 0U;
310cc5e6a72SClement Courbet     }
311cc5e6a72SClement Courbet 
312cc5e6a72SClement Courbet     // No physical registers are allocated for instructions that are optimized
313cc5e6a72SClement Courbet     // in hardware. For example, zero-latency data-dependency breaking
314cc5e6a72SClement Courbet     // instructions don't consume physical registers.
315cc5e6a72SClement Courbet     if (ShouldAllocatePhysRegs)
316cc5e6a72SClement Courbet       allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
317cc5e6a72SClement Courbet   }
318cc5e6a72SClement Courbet 
319cc5e6a72SClement Courbet   if (!WS.clearsSuperRegisters())
320cc5e6a72SClement Courbet     return;
321cc5e6a72SClement Courbet 
322cc5e6a72SClement Courbet   for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
323cc5e6a72SClement Courbet     if (!IsEliminated) {
324cc5e6a72SClement Courbet       RegisterMappings[*I].first = Write;
325cc5e6a72SClement Courbet       RegisterMappings[*I].second.AliasRegID = 0U;
326cc5e6a72SClement Courbet     }
327cc5e6a72SClement Courbet 
328099c089dSJay Foad     ZeroRegisters.setBitVal(*I, IsWriteZero);
329cc5e6a72SClement Courbet   }
330cc5e6a72SClement Courbet }
331cc5e6a72SClement Courbet 
removeRegisterWrite(const WriteState & WS,MutableArrayRef<unsigned> FreedPhysRegs)332cc5e6a72SClement Courbet void RegisterFile::removeRegisterWrite(
333cc5e6a72SClement Courbet     const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
334cc5e6a72SClement Courbet   // Early exit if this write was eliminated. A write eliminated at register
335cc5e6a72SClement Courbet   // renaming stage generates an alias, and it is not added to the PRF.
336cc5e6a72SClement Courbet   if (WS.isEliminated())
337cc5e6a72SClement Courbet     return;
338cc5e6a72SClement Courbet 
339589cb004SAndrea Di Biagio   MCPhysReg RegID = WS.getRegisterID();
340cc5e6a72SClement Courbet 
341dc11d4e6SPatrick Holland   // This allows InstrPostProcess to remove register Defs
342dc11d4e6SPatrick Holland   // by setting their RegisterID to 0.
343dc11d4e6SPatrick Holland   if (!RegID)
344dc11d4e6SPatrick Holland     return;
345dc11d4e6SPatrick Holland 
346cc5e6a72SClement Courbet   assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
347cc5e6a72SClement Courbet          "Invalidating a write of unknown cycles!");
348cc5e6a72SClement Courbet   assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
349cc5e6a72SClement Courbet 
350cc5e6a72SClement Courbet   bool ShouldFreePhysRegs = !WS.isWriteZero();
351589cb004SAndrea Di Biagio   MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
352cc5e6a72SClement Courbet   if (RenameAs && RenameAs != RegID) {
353cc5e6a72SClement Courbet     RegID = RenameAs;
354cc5e6a72SClement Courbet 
355cc5e6a72SClement Courbet     if (!WS.clearsSuperRegisters()) {
356cc5e6a72SClement Courbet       // Keep the definition of `RegID` together with register `RenameAs`.
357cc5e6a72SClement Courbet       ShouldFreePhysRegs = false;
358cc5e6a72SClement Courbet     }
359cc5e6a72SClement Courbet   }
360cc5e6a72SClement Courbet 
361cc5e6a72SClement Courbet   if (ShouldFreePhysRegs)
362cc5e6a72SClement Courbet     freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
363cc5e6a72SClement Courbet 
364cc5e6a72SClement Courbet   WriteRef &WR = RegisterMappings[RegID].first;
365cc5e6a72SClement Courbet   if (WR.getWriteState() == &WS)
366f5bdc88eSAndrea Di Biagio     WR.commit();
367cc5e6a72SClement Courbet 
368cc5e6a72SClement Courbet   for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
369cc5e6a72SClement Courbet     WriteRef &OtherWR = RegisterMappings[*I].first;
370cc5e6a72SClement Courbet     if (OtherWR.getWriteState() == &WS)
371f5bdc88eSAndrea Di Biagio       OtherWR.commit();
372cc5e6a72SClement Courbet   }
373cc5e6a72SClement Courbet 
374cc5e6a72SClement Courbet   if (!WS.clearsSuperRegisters())
375cc5e6a72SClement Courbet     return;
376cc5e6a72SClement Courbet 
377cc5e6a72SClement Courbet   for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
378cc5e6a72SClement Courbet     WriteRef &OtherWR = RegisterMappings[*I].first;
379cc5e6a72SClement Courbet     if (OtherWR.getWriteState() == &WS)
380f5bdc88eSAndrea Di Biagio       OtherWR.commit();
381cc5e6a72SClement Courbet   }
382cc5e6a72SClement Courbet }
383cc5e6a72SClement Courbet 
canEliminateMove(const WriteState & WS,const ReadState & RS,unsigned RegisterFileIndex) const3849ceea666SAndrea Di Biagio bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,
3859ceea666SAndrea Di Biagio                                     unsigned RegisterFileIndex) const {
386cc5e6a72SClement Courbet   const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
387cc5e6a72SClement Courbet   const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
3889ceea666SAndrea Di Biagio   const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
389cc5e6a72SClement Courbet 
3909ceea666SAndrea Di Biagio   // From and To must be owned by the PRF at index `RegisterFileIndex`.
391cc5e6a72SClement Courbet   const RegisterRenamingInfo &RRIFrom = RMFrom.second;
3929ceea666SAndrea Di Biagio   if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)
3939ceea666SAndrea Di Biagio     return false;
3949ceea666SAndrea Di Biagio 
395cc5e6a72SClement Courbet   const RegisterRenamingInfo &RRITo = RMTo.second;
3969ceea666SAndrea Di Biagio   if (RRITo.IndexPlusCost.first != RegisterFileIndex)
397cc5e6a72SClement Courbet     return false;
398cc5e6a72SClement Courbet 
3993822ac90SAndrea Di Biagio   // Early exit if the destination register is from a register class that
4003822ac90SAndrea Di Biagio   // doesn't allow move elimination.
4013822ac90SAndrea Di Biagio   if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)
4023822ac90SAndrea Di Biagio     return false;
4033822ac90SAndrea Di Biagio 
404cc5e6a72SClement Courbet   // We only allow move elimination for writes that update a full physical
405cc5e6a72SClement Courbet   // register. On X86, move elimination is possible with 32-bit general purpose
406cc5e6a72SClement Courbet   // registers because writes to those registers are not partial writes.  If a
407cc5e6a72SClement Courbet   // register move is a partial write, then we conservatively assume that move
408cc5e6a72SClement Courbet   // elimination fails, since it would either trigger a partial update, or the
409cc5e6a72SClement Courbet   // issue of a merge opcode.
410cc5e6a72SClement Courbet   //
411cc5e6a72SClement Courbet   // Note that this constraint may be lifted in future.  For example, we could
412cc5e6a72SClement Courbet   // make this model more flexible, and let users customize the set of registers
413cc5e6a72SClement Courbet   // (i.e. register classes) that allow move elimination.
414cc5e6a72SClement Courbet   //
415cc5e6a72SClement Courbet   // For now, we assume that there is a strong correlation between registers
416cc5e6a72SClement Courbet   // that allow move elimination, and how those same registers are renamed in
417cc5e6a72SClement Courbet   // hardware.
4189ceea666SAndrea Di Biagio   if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())
419cc5e6a72SClement Courbet     if (!WS.clearsSuperRegisters())
420cc5e6a72SClement Courbet       return false;
421cc5e6a72SClement Courbet 
422cc5e6a72SClement Courbet   bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];
4239ceea666SAndrea Di Biagio   return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);
4249ceea666SAndrea Di Biagio }
4259ceea666SAndrea Di Biagio 
tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,MutableArrayRef<ReadState> Reads)4269ceea666SAndrea Di Biagio bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
4279ceea666SAndrea Di Biagio                                           MutableArrayRef<ReadState> Reads) {
4289ceea666SAndrea Di Biagio   if (Writes.size() != Reads.size())
429cc5e6a72SClement Courbet     return false;
430cc5e6a72SClement Courbet 
4319ceea666SAndrea Di Biagio   // This logic assumes that writes and reads are contributed by a register move
4329ceea666SAndrea Di Biagio   // or a register swap operation. In particular, it assumes a simple register
4339ceea666SAndrea Di Biagio   // move if there is only one write.  It assumes a swap operation if there are
4349ceea666SAndrea Di Biagio   // exactly two writes.
4359ceea666SAndrea Di Biagio   if (Writes.empty() || Writes.size() > 2)
4369ceea666SAndrea Di Biagio     return false;
4379ceea666SAndrea Di Biagio 
4389ceea666SAndrea Di Biagio   // All registers must be owned by the same PRF.
4399ceea666SAndrea Di Biagio   const RegisterRenamingInfo &RRInfo =
4409ceea666SAndrea Di Biagio       RegisterMappings[Writes[0].getRegisterID()].second;
4419ceea666SAndrea Di Biagio   unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;
4429ceea666SAndrea Di Biagio   RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
4439ceea666SAndrea Di Biagio 
4449ceea666SAndrea Di Biagio   // Early exit if the PRF cannot eliminate more moves/xchg in this cycle.
4459ceea666SAndrea Di Biagio   if (RMT.MaxMoveEliminatedPerCycle &&
4469ceea666SAndrea Di Biagio       (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)
4479ceea666SAndrea Di Biagio     return false;
4489ceea666SAndrea Di Biagio 
4499ceea666SAndrea Di Biagio   for (size_t I = 0, E = Writes.size(); I < E; ++I) {
4509ceea666SAndrea Di Biagio     const ReadState &RS = Reads[I];
4519ceea666SAndrea Di Biagio     const WriteState &WS = Writes[E - (I + 1)];
4529ceea666SAndrea Di Biagio     if (!canEliminateMove(WS, RS, RegisterFileIndex))
4539ceea666SAndrea Di Biagio       return false;
4549ceea666SAndrea Di Biagio   }
4559ceea666SAndrea Di Biagio 
4569ceea666SAndrea Di Biagio   for (size_t I = 0, E = Writes.size(); I < E; ++I) {
4579ceea666SAndrea Di Biagio     ReadState &RS = Reads[I];
4589ceea666SAndrea Di Biagio     WriteState &WS = Writes[E - (I + 1)];
4599ceea666SAndrea Di Biagio 
4609ceea666SAndrea Di Biagio     const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
4619ceea666SAndrea Di Biagio     const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
4629ceea666SAndrea Di Biagio     const RegisterRenamingInfo &RRIFrom = RMFrom.second;
4639ceea666SAndrea Di Biagio     const RegisterRenamingInfo &RRITo = RMTo.second;
4649ceea666SAndrea Di Biagio 
465cc5e6a72SClement Courbet     // Construct an alias.
466c102e2a2SAndrea Di Biagio     MCPhysReg AliasedReg =
467c102e2a2SAndrea Di Biagio         RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();
468c102e2a2SAndrea Di Biagio     MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();
469cc5e6a72SClement Courbet 
470c102e2a2SAndrea Di Biagio     const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;
471cc5e6a72SClement Courbet     if (RMAlias.AliasRegID)
472c102e2a2SAndrea Di Biagio       AliasedReg = RMAlias.AliasRegID;
473cc5e6a72SClement Courbet 
474c102e2a2SAndrea Di Biagio     RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
475c102e2a2SAndrea Di Biagio     for (MCSubRegIterator I(AliasReg, &MRI); I.isValid(); ++I)
476c102e2a2SAndrea Di Biagio       RegisterMappings[*I].second.AliasRegID = AliasedReg;
477cc5e6a72SClement Courbet 
4789ceea666SAndrea Di Biagio     if (ZeroRegisters[RS.getRegisterID()]) {
479cc5e6a72SClement Courbet       WS.setWriteZero();
480cc5e6a72SClement Courbet       RS.setReadZero();
481cc5e6a72SClement Courbet     }
4829ceea666SAndrea Di Biagio 
483cc5e6a72SClement Courbet     WS.setEliminated();
484c102e2a2SAndrea Di Biagio     RMT.NumMoveEliminated++;
4859ceea666SAndrea Di Biagio   }
486cc5e6a72SClement Courbet 
487cc5e6a72SClement Courbet   return true;
488cc5e6a72SClement Courbet }
489cc5e6a72SClement Courbet 
getWriteBackCycle() const490f5bdc88eSAndrea Di Biagio unsigned WriteRef::getWriteBackCycle() const {
491f5bdc88eSAndrea Di Biagio   assert(hasKnownWriteBackCycle() && "Instruction not executed!");
492f5bdc88eSAndrea Di Biagio   assert((!Write || Write->getCyclesLeft() <= 0) &&
493f5bdc88eSAndrea Di Biagio          "Inconsistent state found!");
494f5bdc88eSAndrea Di Biagio   return WriteBackCycle;
495f5bdc88eSAndrea Di Biagio }
496f5bdc88eSAndrea Di Biagio 
getElapsedCyclesFromWriteBack(const WriteRef & WR) const497f5bdc88eSAndrea Di Biagio unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {
498f5bdc88eSAndrea Di Biagio   assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");
499f5bdc88eSAndrea Di Biagio   return CurrentCycle - WR.getWriteBackCycle();
500f5bdc88eSAndrea Di Biagio }
501f5bdc88eSAndrea Di Biagio 
collectWrites(const MCSubtargetInfo & STI,const ReadState & RS,SmallVectorImpl<WriteRef> & Writes,SmallVectorImpl<WriteRef> & CommittedWrites) const502f5bdc88eSAndrea Di Biagio void RegisterFile::collectWrites(
503f5bdc88eSAndrea Di Biagio     const MCSubtargetInfo &STI, const ReadState &RS,
504f5bdc88eSAndrea Di Biagio     SmallVectorImpl<WriteRef> &Writes,
505f5bdc88eSAndrea Di Biagio     SmallVectorImpl<WriteRef> &CommittedWrites) const {
506f5bdc88eSAndrea Di Biagio   const ReadDescriptor &RD = RS.getDescriptor();
507f5bdc88eSAndrea Di Biagio   const MCSchedModel &SM = STI.getSchedModel();
508f5bdc88eSAndrea Di Biagio   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
509589cb004SAndrea Di Biagio   MCPhysReg RegID = RS.getRegisterID();
510cc5e6a72SClement Courbet   assert(RegID && RegID < RegisterMappings.size());
51150770d8dSAndrea Di Biagio   LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "
512cc5e6a72SClement Courbet                     << MRI.getName(RegID) << '\n');
513cc5e6a72SClement Courbet 
514cc5e6a72SClement Courbet   // Check if this is an alias.
515cc5e6a72SClement Courbet   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
516cc5e6a72SClement Courbet   if (RRI.AliasRegID)
517cc5e6a72SClement Courbet     RegID = RRI.AliasRegID;
518cc5e6a72SClement Courbet 
519cc5e6a72SClement Courbet   const WriteRef &WR = RegisterMappings[RegID].first;
520f5bdc88eSAndrea Di Biagio   if (WR.getWriteState()) {
521cc5e6a72SClement Courbet     Writes.push_back(WR);
522f5bdc88eSAndrea Di Biagio   } else if (WR.hasKnownWriteBackCycle()) {
523f5bdc88eSAndrea Di Biagio     unsigned WriteResID = WR.getWriteResourceID();
524f5bdc88eSAndrea Di Biagio     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
525f5bdc88eSAndrea Di Biagio     if (ReadAdvance < 0) {
526f5bdc88eSAndrea Di Biagio       unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
527f5bdc88eSAndrea Di Biagio       if (Elapsed < static_cast<unsigned>(-ReadAdvance))
528f5bdc88eSAndrea Di Biagio         CommittedWrites.push_back(WR);
529f5bdc88eSAndrea Di Biagio     }
530f5bdc88eSAndrea Di Biagio   }
531cc5e6a72SClement Courbet 
532cc5e6a72SClement Courbet   // Handle potential partial register updates.
533cc5e6a72SClement Courbet   for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
534cc5e6a72SClement Courbet     const WriteRef &WR = RegisterMappings[*I].first;
535f5bdc88eSAndrea Di Biagio     if (WR.getWriteState()) {
536cc5e6a72SClement Courbet       Writes.push_back(WR);
537f5bdc88eSAndrea Di Biagio     } else if (WR.hasKnownWriteBackCycle()) {
538f5bdc88eSAndrea Di Biagio       unsigned WriteResID = WR.getWriteResourceID();
539f5bdc88eSAndrea Di Biagio       int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
540f5bdc88eSAndrea Di Biagio       if (ReadAdvance < 0) {
541f5bdc88eSAndrea Di Biagio         unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
542f5bdc88eSAndrea Di Biagio         if (Elapsed < static_cast<unsigned>(-ReadAdvance))
543f5bdc88eSAndrea Di Biagio           CommittedWrites.push_back(WR);
544f5bdc88eSAndrea Di Biagio       }
545f5bdc88eSAndrea Di Biagio     }
546cc5e6a72SClement Courbet   }
547cc5e6a72SClement Courbet 
548cc5e6a72SClement Courbet   // Remove duplicate entries and resize the input vector.
549cc5e6a72SClement Courbet   if (Writes.size() > 1) {
550cc5e6a72SClement Courbet     sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) {
551cc5e6a72SClement Courbet       return Lhs.getWriteState() < Rhs.getWriteState();
552cc5e6a72SClement Courbet     });
553cc5e6a72SClement Courbet     auto It = std::unique(Writes.begin(), Writes.end());
554cc5e6a72SClement Courbet     Writes.resize(std::distance(Writes.begin(), It));
555cc5e6a72SClement Courbet   }
556cc5e6a72SClement Courbet 
557cc5e6a72SClement Courbet   LLVM_DEBUG({
558cc5e6a72SClement Courbet     for (const WriteRef &WR : Writes) {
559cc5e6a72SClement Courbet       const WriteState &WS = *WR.getWriteState();
560cc5e6a72SClement Courbet       dbgs() << "[PRF] Found a dependent use of Register "
561cc5e6a72SClement Courbet              << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"
562cc5e6a72SClement Courbet              << WR.getSourceIndex() << ")\n";
563cc5e6a72SClement Courbet     }
564cc5e6a72SClement Courbet   });
565cc5e6a72SClement Courbet }
566cc5e6a72SClement Courbet 
56750770d8dSAndrea Di Biagio RegisterFile::RAWHazard
checkRAWHazards(const MCSubtargetInfo & STI,const ReadState & RS) const56850770d8dSAndrea Di Biagio RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI,
56950770d8dSAndrea Di Biagio                               const ReadState &RS) const {
57050770d8dSAndrea Di Biagio   RAWHazard Hazard;
57150770d8dSAndrea Di Biagio   SmallVector<WriteRef, 4> Writes;
57250770d8dSAndrea Di Biagio   SmallVector<WriteRef, 4> CommittedWrites;
57350770d8dSAndrea Di Biagio 
57450770d8dSAndrea Di Biagio   const MCSchedModel &SM = STI.getSchedModel();
57550770d8dSAndrea Di Biagio   const ReadDescriptor &RD = RS.getDescriptor();
57650770d8dSAndrea Di Biagio   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
57750770d8dSAndrea Di Biagio 
57850770d8dSAndrea Di Biagio   collectWrites(STI, RS, Writes, CommittedWrites);
57950770d8dSAndrea Di Biagio   for (const WriteRef &WR : Writes) {
58050770d8dSAndrea Di Biagio     const WriteState *WS = WR.getWriteState();
58150770d8dSAndrea Di Biagio     unsigned WriteResID = WS->getWriteResourceID();
58250770d8dSAndrea Di Biagio     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
58350770d8dSAndrea Di Biagio 
58450770d8dSAndrea Di Biagio     if (WS->getCyclesLeft() == UNKNOWN_CYCLES) {
58550770d8dSAndrea Di Biagio       if (Hazard.isValid())
58650770d8dSAndrea Di Biagio         continue;
58750770d8dSAndrea Di Biagio 
58850770d8dSAndrea Di Biagio       Hazard.RegisterID = WR.getRegisterID();
58950770d8dSAndrea Di Biagio       Hazard.CyclesLeft = UNKNOWN_CYCLES;
59050770d8dSAndrea Di Biagio       continue;
59150770d8dSAndrea Di Biagio     }
59250770d8dSAndrea Di Biagio 
59350770d8dSAndrea Di Biagio     int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;
59450770d8dSAndrea Di Biagio     if (CyclesLeft > 0) {
59550770d8dSAndrea Di Biagio       if (Hazard.CyclesLeft < CyclesLeft) {
59650770d8dSAndrea Di Biagio         Hazard.RegisterID = WR.getRegisterID();
59750770d8dSAndrea Di Biagio         Hazard.CyclesLeft = CyclesLeft;
59850770d8dSAndrea Di Biagio       }
59950770d8dSAndrea Di Biagio     }
60050770d8dSAndrea Di Biagio   }
60150770d8dSAndrea Di Biagio   Writes.clear();
60250770d8dSAndrea Di Biagio 
60350770d8dSAndrea Di Biagio   for (const WriteRef &WR : CommittedWrites) {
60450770d8dSAndrea Di Biagio     unsigned WriteResID = WR.getWriteResourceID();
60550770d8dSAndrea Di Biagio     int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
60650770d8dSAndrea Di Biagio     int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR));
60750770d8dSAndrea Di Biagio     int CyclesLeft = NegReadAdvance - Elapsed;
60850770d8dSAndrea Di Biagio     assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");
60950770d8dSAndrea Di Biagio     if (Hazard.CyclesLeft < CyclesLeft) {
61050770d8dSAndrea Di Biagio       Hazard.RegisterID = WR.getRegisterID();
61150770d8dSAndrea Di Biagio       Hazard.CyclesLeft = CyclesLeft;
61250770d8dSAndrea Di Biagio     }
61350770d8dSAndrea Di Biagio   }
61450770d8dSAndrea Di Biagio 
61550770d8dSAndrea Di Biagio   return Hazard;
61650770d8dSAndrea Di Biagio }
61750770d8dSAndrea Di Biagio 
addRegisterRead(ReadState & RS,const MCSubtargetInfo & STI) const618cc5e6a72SClement Courbet void RegisterFile::addRegisterRead(ReadState &RS,
6194bce783eSAndrea Di Biagio                                    const MCSubtargetInfo &STI) const {
620589cb004SAndrea Di Biagio   MCPhysReg RegID = RS.getRegisterID();
621cc5e6a72SClement Courbet   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
622cc5e6a72SClement Courbet   RS.setPRF(RRI.IndexPlusCost.first);
623cc5e6a72SClement Courbet   if (RS.isIndependentFromDef())
624cc5e6a72SClement Courbet     return;
625cc5e6a72SClement Courbet 
626cc5e6a72SClement Courbet   if (ZeroRegisters[RS.getRegisterID()])
627cc5e6a72SClement Courbet     RS.setReadZero();
6284bce783eSAndrea Di Biagio 
6294bce783eSAndrea Di Biagio   SmallVector<WriteRef, 4> DependentWrites;
630f5bdc88eSAndrea Di Biagio   SmallVector<WriteRef, 4> CompletedWrites;
631f5bdc88eSAndrea Di Biagio   collectWrites(STI, RS, DependentWrites, CompletedWrites);
632f5bdc88eSAndrea Di Biagio   RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());
6334bce783eSAndrea Di Biagio 
6344bce783eSAndrea Di Biagio   // We know that this read depends on all the writes in DependentWrites.
6354bce783eSAndrea Di Biagio   // For each write, check if we have ReadAdvance information, and use it
636f5bdc88eSAndrea Di Biagio   // to figure out in how many cycles this read will be available.
6374bce783eSAndrea Di Biagio   const ReadDescriptor &RD = RS.getDescriptor();
6384bce783eSAndrea Di Biagio   const MCSchedModel &SM = STI.getSchedModel();
6394bce783eSAndrea Di Biagio   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
6404bce783eSAndrea Di Biagio   for (WriteRef &WR : DependentWrites) {
641f5bdc88eSAndrea Di Biagio     unsigned WriteResID = WR.getWriteResourceID();
6424bce783eSAndrea Di Biagio     WriteState &WS = *WR.getWriteState();
6434bce783eSAndrea Di Biagio     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
6447a950ed5SAndrea Di Biagio     WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);
6454bce783eSAndrea Di Biagio   }
646f5bdc88eSAndrea Di Biagio 
647f5bdc88eSAndrea Di Biagio   for (WriteRef &WR : CompletedWrites) {
648f5bdc88eSAndrea Di Biagio     unsigned WriteResID = WR.getWriteResourceID();
649f5bdc88eSAndrea Di Biagio     assert(WR.hasKnownWriteBackCycle() && "Invalid write!");
650f5bdc88eSAndrea Di Biagio     assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);
651f5bdc88eSAndrea Di Biagio     unsigned ReadAdvance = static_cast<unsigned>(
652f5bdc88eSAndrea Di Biagio         -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));
653f5bdc88eSAndrea Di Biagio     unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
654f5bdc88eSAndrea Di Biagio     assert(Elapsed < ReadAdvance && "Should not have been added to the set!");
655f5bdc88eSAndrea Di Biagio     RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),
656f5bdc88eSAndrea Di Biagio                        ReadAdvance - Elapsed);
657f5bdc88eSAndrea Di Biagio   }
658cc5e6a72SClement Courbet }
659cc5e6a72SClement Courbet 
isAvailable(ArrayRef<MCPhysReg> Regs) const660589cb004SAndrea Di Biagio unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {
661cc5e6a72SClement Courbet   SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
662cc5e6a72SClement Courbet 
663cc5e6a72SClement Courbet   // Find how many new mappings must be created for each register file.
664589cb004SAndrea Di Biagio   for (const MCPhysReg RegID : Regs) {
665cc5e6a72SClement Courbet     const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
666cc5e6a72SClement Courbet     const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
667cc5e6a72SClement Courbet     if (Entry.first)
668cc5e6a72SClement Courbet       NumPhysRegs[Entry.first] += Entry.second;
669cc5e6a72SClement Courbet     NumPhysRegs[0] += Entry.second;
670cc5e6a72SClement Courbet   }
671cc5e6a72SClement Courbet 
672cc5e6a72SClement Courbet   unsigned Response = 0;
673cc5e6a72SClement Courbet   for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
674cc5e6a72SClement Courbet     unsigned NumRegs = NumPhysRegs[I];
675cc5e6a72SClement Courbet     if (!NumRegs)
676cc5e6a72SClement Courbet       continue;
677cc5e6a72SClement Courbet 
678cc5e6a72SClement Courbet     const RegisterMappingTracker &RMT = RegisterFiles[I];
679cc5e6a72SClement Courbet     if (!RMT.NumPhysRegs) {
680cc5e6a72SClement Courbet       // The register file has an unbounded number of microarchitectural
681cc5e6a72SClement Courbet       // registers.
682cc5e6a72SClement Courbet       continue;
683cc5e6a72SClement Courbet     }
684cc5e6a72SClement Courbet 
685cc5e6a72SClement Courbet     if (RMT.NumPhysRegs < NumRegs) {
686cc5e6a72SClement Courbet       // The current register file is too small. This may occur if the number of
687cc5e6a72SClement Courbet       // microarchitectural registers in register file #0 was changed by the
688cc5e6a72SClement Courbet       // users via flag -reg-file-size. Alternatively, the scheduling model
689cc5e6a72SClement Courbet       // specified a too small number of registers for this register file.
69050770d8dSAndrea Di Biagio       LLVM_DEBUG(
69150770d8dSAndrea Di Biagio           dbgs() << "[PRF] Not enough registers in the register file.\n");
692cc5e6a72SClement Courbet 
693cc5e6a72SClement Courbet       // FIXME: Normalize the instruction register count to match the
694cc5e6a72SClement Courbet       // NumPhysRegs value.  This is a highly unusual case, and is not expected
695cc5e6a72SClement Courbet       // to occur.  This normalization is hiding an inconsistency in either the
696cc5e6a72SClement Courbet       // scheduling model or in the value that the user might have specified
697cc5e6a72SClement Courbet       // for NumPhysRegs.
698cc5e6a72SClement Courbet       NumRegs = RMT.NumPhysRegs;
699cc5e6a72SClement Courbet     }
700cc5e6a72SClement Courbet 
701cc5e6a72SClement Courbet     if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
702cc5e6a72SClement Courbet       Response |= (1U << I);
703cc5e6a72SClement Courbet   }
704cc5e6a72SClement Courbet 
705cc5e6a72SClement Courbet   return Response;
706cc5e6a72SClement Courbet }
707cc5e6a72SClement Courbet 
708cc5e6a72SClement Courbet #ifndef NDEBUG
dump() const709f5bdc88eSAndrea Di Biagio void WriteRef::dump() const {
710f5bdc88eSAndrea Di Biagio   dbgs() << "IID=" << getSourceIndex() << ' ';
711f5bdc88eSAndrea Di Biagio   if (isValid())
712f5bdc88eSAndrea Di Biagio     getWriteState()->dump();
713f5bdc88eSAndrea Di Biagio   else
714f5bdc88eSAndrea Di Biagio     dbgs() << "(null)";
715f5bdc88eSAndrea Di Biagio }
716f5bdc88eSAndrea Di Biagio 
dump() const717cc5e6a72SClement Courbet void RegisterFile::dump() const {
718cc5e6a72SClement Courbet   for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
719cc5e6a72SClement Courbet     const RegisterMapping &RM = RegisterMappings[I];
720cc5e6a72SClement Courbet     const RegisterRenamingInfo &RRI = RM.second;
721cc5e6a72SClement Courbet     if (ZeroRegisters[I]) {
722cc5e6a72SClement Courbet       dbgs() << MRI.getName(I) << ", " << I
723cc5e6a72SClement Courbet              << ", PRF=" << RRI.IndexPlusCost.first
724cc5e6a72SClement Courbet              << ", Cost=" << RRI.IndexPlusCost.second
725cc5e6a72SClement Courbet              << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
726cc5e6a72SClement Courbet              << ",";
727cc5e6a72SClement Courbet       RM.first.dump();
728cc5e6a72SClement Courbet       dbgs() << '\n';
729cc5e6a72SClement Courbet     }
730cc5e6a72SClement Courbet   }
731cc5e6a72SClement Courbet 
732cc5e6a72SClement Courbet   for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
733cc5e6a72SClement Courbet     dbgs() << "Register File #" << I;
734cc5e6a72SClement Courbet     const RegisterMappingTracker &RMT = RegisterFiles[I];
735cc5e6a72SClement Courbet     dbgs() << "\n  TotalMappings:        " << RMT.NumPhysRegs
736cc5e6a72SClement Courbet            << "\n  NumUsedMappings:      " << RMT.NumUsedPhysRegs << '\n';
737cc5e6a72SClement Courbet   }
738cc5e6a72SClement Courbet }
739cc5e6a72SClement Courbet #endif
740cc5e6a72SClement Courbet 
741cc5e6a72SClement Courbet } // namespace mca
742cc5e6a72SClement Courbet } // namespace llvm
743