LLVM 22.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; }
57 WriteState *getWriteState() { 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...
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:78
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
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:303
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction propagated through the simulated instruction pipeline.
Tracks register operand latency in cycles.
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
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)
RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri, unsigned NumRegs=0)
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.
bool isAvailable() const
Returns true if this register write has been executed, and the new register value is therefore availa...
unsigned getSourceIndex() const
unsigned getWriteResourceID() const
void notifyExecuted(unsigned Cycle)
bool isWriteZero() const
bool operator==(const WriteRef &Other) const
const WriteState * getWriteState() const
MCPhysReg getRegisterID() const
bool isValid() const
WriteState * getWriteState()
unsigned getWriteBackCycle() const
bool hasKnownWriteBackCycle() const
Tracks uses of a register definition (e.g.
This is an optimization pass for GlobalISel generic memory operations.
CycleInfo::CycleT Cycle
Definition CycleInfo.h:24
@ Other
Any other memory.
Definition ModRef.h:68
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
A register file descriptor.
Definition MCSchedule.h:171
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:258