LLVM 20.0.0git
RegisterFile.h
Go to the documentation of this file.
1//===--------------------- RegisterFile.h -----------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
10/// This file defines a register mapping file class. This class is responsible
11/// for managing hardware register files and the tracking of data dependencies
12/// between registers.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_MCA_HARDWAREUNITS_REGISTERFILE_H
17#define LLVM_MCA_HARDWAREUNITS_REGISTERFILE_H
18
19#include "llvm/ADT/APInt.h"
22#include "llvm/MC/MCSchedule.h"
25
26namespace llvm {
27namespace mca {
28
29class ReadState;
30class WriteState;
31class Instruction;
32
33/// A reference to a register write.
34///
35/// This class is mainly used by the register file to describe register
36/// mappings. It correlates a register write to the source index of the
37/// defining instruction.
38class WriteRef {
39 unsigned IID;
40 unsigned WriteBackCycle;
41 unsigned WriteResID;
42 MCPhysReg RegisterID;
43 WriteState *Write;
44
45 static const unsigned INVALID_IID;
46
47public:
49 : IID(INVALID_IID), WriteBackCycle(), WriteResID(), RegisterID(),
50 Write() {}
51 WriteRef(unsigned SourceIndex, WriteState *WS);
52
53 unsigned getSourceIndex() const { return IID; }
54 unsigned getWriteBackCycle() const;
55
56 const WriteState *getWriteState() const { return Write; }
58 unsigned getWriteResourceID() const;
60
61 void commit();
62 void notifyExecuted(unsigned Cycle);
63
64 bool hasKnownWriteBackCycle() const;
65 bool isWriteZero() const;
66 bool isValid() const { return getSourceIndex() != INVALID_IID; }
67
68 /// Returns true if this register write has been executed, and the new
69 /// register value is therefore available to users.
70 bool isAvailable() const { return hasKnownWriteBackCycle(); }
71
72 bool operator==(const WriteRef &Other) const {
73 return Write && Other.Write && Write == Other.Write;
74 }
75
76#ifndef NDEBUG
77 void dump() const;
78#endif
79};
80
81/// Manages hardware register files, and tracks register definitions for
82/// register renaming purposes.
83class RegisterFile : public HardwareUnit {
84 const MCRegisterInfo &MRI;
85
86 // class RegisterMappingTracker is a physical register file (PRF) descriptor.
87 // There is one RegisterMappingTracker for every PRF definition in the
88 // scheduling model.
89 //
90 // An instance of RegisterMappingTracker tracks the number of physical
91 // registers available for renaming. It also tracks the number of register
92 // moves eliminated per cycle.
93 struct RegisterMappingTracker {
94 // The total number of physical registers that are available in this
95 // register file for register renaming purpouses. A value of zero for this
96 // field means: this register file has an unbounded number of physical
97 // registers.
98 const unsigned NumPhysRegs;
99 // Number of physical registers that are currently in use.
100 unsigned NumUsedPhysRegs;
101
102 // Maximum number of register moves that can be eliminated by this PRF every
103 // cycle. A value of zero means that there is no limit in the number of
104 // moves which can be eliminated every cycle.
105 const unsigned MaxMoveEliminatedPerCycle;
106
107 // Number of register moves eliminated during this cycle.
108 //
109 // This value is increased by one every time a register move is eliminated.
110 // Every new cycle, this value is reset to zero.
111 // A move can be eliminated only if MaxMoveEliminatedPerCycle is zero, or if
112 // NumMoveEliminated is less than MaxMoveEliminatedPerCycle.
113 unsigned NumMoveEliminated;
114
115 // If set, move elimination is restricted to zero-register moves only.
116 bool AllowZeroMoveEliminationOnly;
117
118 RegisterMappingTracker(unsigned NumPhysRegisters,
119 unsigned MaxMoveEliminated = 0U,
120 bool AllowZeroMoveElimOnly = false)
121 : NumPhysRegs(NumPhysRegisters), NumUsedPhysRegs(0),
122 MaxMoveEliminatedPerCycle(MaxMoveEliminated), NumMoveEliminated(0U),
123 AllowZeroMoveEliminationOnly(AllowZeroMoveElimOnly) {}
124 };
125
126 // A vector of register file descriptors. This set always contains at least
127 // one entry. Entry at index #0 is reserved. That entry describes a register
128 // file with an unbounded number of physical registers that "sees" all the
129 // hardware registers declared by the target (i.e. all the register
130 // definitions in the target specific `XYZRegisterInfo.td` - where `XYZ` is
131 // the target name).
132 //
133 // Users can limit the number of physical registers that are available in
134 // register file #0 specifying command line flag `-register-file-size=<uint>`.
136
137 // This type is used to propagate information about the owner of a register,
138 // and the cost of allocating it in the PRF. Register cost is defined as the
139 // number of physical registers consumed by the PRF to allocate a user
140 // register.
141 //
142 // For example: on X86 BtVer2, a YMM register consumes 2 128-bit physical
143 // registers. So, the cost of allocating a YMM register in BtVer2 is 2.
144 using IndexPlusCostPairTy = std::pair<unsigned, unsigned>;
145
146 // Struct RegisterRenamingInfo is used to map logical registers to register
147 // files.
148 //
149 // There is a RegisterRenamingInfo object for every logical register defined
150 // by the target. RegisteRenamingInfo objects are stored into vector
151 // `RegisterMappings`, and MCPhysReg IDs can be used to reference
152 // elements in that vector.
153 //
154 // Each RegisterRenamingInfo is owned by a PRF, and field `IndexPlusCost`
155 // specifies both the owning PRF, as well as the number of physical registers
156 // consumed at register renaming stage.
157 //
158 // Field `AllowMoveElimination` is set for registers that are used as
159 // destination by optimizable register moves.
160 //
161 // Field `AliasRegID` is set by writes from register moves that have been
162 // eliminated at register renaming stage. A move eliminated at register
163 // renaming stage is effectively bypassed, and its write aliases the source
164 // register definition.
165 struct RegisterRenamingInfo {
166 IndexPlusCostPairTy IndexPlusCost;
167 MCPhysReg RenameAs;
168 MCPhysReg AliasRegID;
169 bool AllowMoveElimination;
170 RegisterRenamingInfo()
171 : IndexPlusCost(std::make_pair(0U, 1U)), RenameAs(0U), AliasRegID(0U),
172 AllowMoveElimination(false) {}
173 };
174
175 // RegisterMapping objects are mainly used to track physical register
176 // definitions and resolve data dependencies.
177 //
178 // Every register declared by the Target is associated with an instance of
179 // RegisterMapping. RegisterMapping objects keep track of writes to a logical
180 // register. That information is used by class RegisterFile to resolve data
181 // dependencies, and correctly set latencies for register uses.
182 //
183 // This implementation does not allow overlapping register files. The only
184 // register file that is allowed to overlap with other register files is
185 // register file #0. If we exclude register #0, every register is "owned" by
186 // at most one register file.
187 using RegisterMapping = std::pair<WriteRef, RegisterRenamingInfo>;
188
189 // There is one entry per each register defined by the target.
190 std::vector<RegisterMapping> RegisterMappings;
191
192 // Used to track zero registers. There is one bit for each register defined by
193 // the target. Bits are set for registers that are known to be zero.
194 APInt ZeroRegisters;
195
196 unsigned CurrentCycle;
197
198 // This method creates a new register file descriptor.
199 // The new register file owns all of the registers declared by register
200 // classes in the 'RegisterClasses' set.
201 //
202 // Processor models allow the definition of RegisterFile(s) via tablegen. For
203 // example, this is a tablegen definition for a x86 register file for
204 // XMM[0-15] and YMM[0-15], that allows up to 60 renames (each rename costs 1
205 // physical register).
206 //
207 // def FPRegisterFile : RegisterFile<60, [VR128RegClass, VR256RegClass]>
208 //
209 // Here FPRegisterFile contains all the registers defined by register class
210 // VR128RegClass and VR256RegClass. FPRegisterFile implements 60
211 // registers which can be used for register renaming purpose.
212 void addRegisterFile(const MCRegisterFileDesc &RF,
214
215 // Consumes physical registers in each register file specified by the
216 // `IndexPlusCostPairTy`. This method is called from `addRegisterMapping()`.
217 void allocatePhysRegs(const RegisterRenamingInfo &Entry,
218 MutableArrayRef<unsigned> UsedPhysRegs);
219
220 // Releases previously allocated physical registers from the register file(s).
221 // This method is called from `invalidateRegisterMapping()`.
222 void freePhysRegs(const RegisterRenamingInfo &Entry,
223 MutableArrayRef<unsigned> FreedPhysRegs);
224
225 // Create an instance of RegisterMappingTracker for every register file
226 // specified by the processor model.
227 // If no register file is specified, then this method creates a default
228 // register file with an unbounded number of physical registers.
229 void initialize(const MCSchedModel &SM, unsigned NumRegs);
230
231public:
232 RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,
233 unsigned NumRegs = 0);
234
235 // Collects writes that are in a RAW dependency with RS.
236 void collectWrites(const MCSubtargetInfo &STI, const ReadState &RS,
238 SmallVectorImpl<WriteRef> &CommittedWrites) const;
239 struct RAWHazard {
241 int CyclesLeft = 0;
242
243 RAWHazard() = default;
244 bool isValid() const { return RegisterID; }
245 bool hasUnknownCycles() const { return CyclesLeft < 0; }
246 };
247
248 RAWHazard checkRAWHazards(const MCSubtargetInfo &STI,
249 const ReadState &RS) const;
250
251 // This method updates the register mappings inserting a new register
252 // definition. This method is also responsible for updating the number of
253 // allocated physical registers in each register file modified by the write.
254 // No physical regiser is allocated if this write is from a zero-idiom.
256
257 // Collect writes that are in a data dependency with RS, and update RS
258 // internal state.
259 void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const;
260
261 // Removes write \param WS from the register mappings.
262 // Physical registers may be released to reflect this update.
263 // No registers are released if this write is from a zero-idiom.
264 void removeRegisterWrite(const WriteState &WS,
265 MutableArrayRef<unsigned> FreedPhysRegs);
266
267 // Returns true if the PRF at index `PRFIndex` can eliminate a move from RS to
268 // WS.
269 bool canEliminateMove(const WriteState &WS, const ReadState &RS,
270 unsigned PRFIndex) const;
271
272 // Returns true if this instruction can be fully eliminated at register
273 // renaming stage. On success, this method updates the internal state of each
274 // WriteState by setting flag `WS.isEliminated`, and by propagating the zero
275 // flag for known zero registers. It internally uses `canEliminateMove` to
276 // determine if a read/write pair can be eliminated. By default, it assumes a
277 // register swap if there is more than one register definition.
280
281 // Checks if there are enough physical registers in the register files.
282 // Returns a "response mask" where each bit represents the response from a
283 // different register file. A mask of all zeroes means that all register
284 // files are available. Otherwise, the mask can be used to identify which
285 // register file was busy. This sematic allows us to classify dispatch
286 // stalls caused by the lack of register file resources.
287 //
288 // Current implementation can simulate up to 32 register files (including the
289 // special register file at index #0).
290 unsigned isAvailable(ArrayRef<MCPhysReg> Regs) const;
291
292 // Returns the number of PRFs implemented by this processor.
293 unsigned getNumRegisterFiles() const { return RegisterFiles.size(); }
294
295 unsigned getElapsedCyclesFromWriteBack(const WriteRef &WR) const;
296
298
299 // Notify each PRF that a new cycle just started.
300 void cycleStart();
301
302 void cycleEnd() { ++CurrentCycle; }
303
304#ifndef NDEBUG
305 void dump() const;
306#endif
307};
308
309} // namespace mca
310} // namespace llvm
311
312#endif // LLVM_MCA_HARDWAREUNITS_REGISTERFILE_H
This file implements a class to represent arbitrary precision integral constant values and operations...
SmallVector< uint32_t, 0 > Writes
Definition: ELF_riscv.cpp:497
This file defines a base class for describing a simulated hardware unit.
This file defines the SmallVector class.
Class for arbitrary precision integers.
Definition: APInt.h:77
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
A possibly irreducible generalization of a Loop.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:307
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
An instruction propagated through the simulated instruction pipeline.
Definition: Instruction.h:600
Tracks register operand latency in cycles.
Definition: Instruction.h:326
Manages hardware register files, and tracks register definitions for register renaming purposes.
Definition: RegisterFile.h:83
void collectWrites(const MCSubtargetInfo &STI, const ReadState &RS, SmallVectorImpl< WriteRef > &Writes, SmallVectorImpl< WriteRef > &CommittedWrites) const
unsigned getElapsedCyclesFromWriteBack(const WriteRef &WR) const
void addRegisterWrite(WriteRef Write, MutableArrayRef< unsigned > UsedPhysRegs)
unsigned isAvailable(ArrayRef< MCPhysReg > Regs) const
unsigned getNumRegisterFiles() const
Definition: RegisterFile.h:293
RAWHazard checkRAWHazards(const MCSubtargetInfo &STI, const ReadState &RS) const
void removeRegisterWrite(const WriteState &WS, MutableArrayRef< unsigned > FreedPhysRegs)
bool tryEliminateMoveOrSwap(MutableArrayRef< WriteState > Writes, MutableArrayRef< ReadState > Reads)
void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const
bool canEliminateMove(const WriteState &WS, const ReadState &RS, unsigned PRFIndex) const
void onInstructionExecuted(Instruction *IS)
A reference to a register write.
Definition: RegisterFile.h:38
bool isAvailable() const
Returns true if this register write has been executed, and the new register value is therefore availa...
Definition: RegisterFile.h:70
unsigned getSourceIndex() const
Definition: RegisterFile.h:53
unsigned getWriteResourceID() const
void notifyExecuted(unsigned Cycle)
bool isWriteZero() const
bool operator==(const WriteRef &Other) const
Definition: RegisterFile.h:72
const WriteState * getWriteState() const
Definition: RegisterFile.h:56
MCPhysReg getRegisterID() const
bool isValid() const
Definition: RegisterFile.h:66
WriteState * getWriteState()
Definition: RegisterFile.h:57
unsigned getWriteBackCycle() const
bool hasKnownWriteBackCycle() const
Tracks uses of a register definition (e.g.
Definition: Instruction.h:197
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Write
Definition: CodeGenData.h:103
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition: MCRegister.h:21
@ Other
Any other memory.
A register file descriptor.
Definition: MCSchedule.h:166
Machine model for scheduling, bundling, and heuristics.
Definition: MCSchedule.h:253