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