1 //===--------------------- RegisterFile.h -----------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_MCA_REGISTER_FILE_H
17 #define LLVM_MCA_REGISTER_FILE_H
19 #include "llvm/ADT/APInt.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSchedule.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 #include "llvm/MCA/HardwareUnits/HardwareUnit.h"
25 #include "llvm/Support/Error.h"
34 /// Manages hardware register files, and tracks register definitions for
35 /// register renaming purposes.
36 class RegisterFile
: public HardwareUnit
{
37 const MCRegisterInfo
&MRI
;
39 // class RegisterMappingTracker is a physical register file (PRF) descriptor.
40 // There is one RegisterMappingTracker for every PRF definition in the
43 // An instance of RegisterMappingTracker tracks the number of physical
44 // registers available for renaming. It also tracks the number of register
45 // moves eliminated per cycle.
46 struct RegisterMappingTracker
{
47 // The total number of physical registers that are available in this
48 // register file for register renaming purpouses. A value of zero for this
49 // field means: this register file has an unbounded number of physical
51 const unsigned NumPhysRegs
;
52 // Number of physical registers that are currently in use.
53 unsigned NumUsedPhysRegs
;
55 // Maximum number of register moves that can be eliminated by this PRF every
56 // cycle. A value of zero means that there is no limit in the number of
57 // moves which can be eliminated every cycle.
58 const unsigned MaxMoveEliminatedPerCycle
;
60 // Number of register moves eliminated during this cycle.
62 // This value is increased by one every time a register move is eliminated.
63 // Every new cycle, this value is reset to zero.
64 // A move can be eliminated only if MaxMoveEliminatedPerCycle is zero, or if
65 // NumMoveEliminated is less than MaxMoveEliminatedPerCycle.
66 unsigned NumMoveEliminated
;
68 // If set, move elimination is restricted to zero-register moves only.
69 bool AllowZeroMoveEliminationOnly
;
71 RegisterMappingTracker(unsigned NumPhysRegisters
,
72 unsigned MaxMoveEliminated
= 0U,
73 bool AllowZeroMoveElimOnly
= false)
74 : NumPhysRegs(NumPhysRegisters
), NumUsedPhysRegs(0),
75 MaxMoveEliminatedPerCycle(MaxMoveEliminated
), NumMoveEliminated(0U),
76 AllowZeroMoveEliminationOnly(AllowZeroMoveElimOnly
) {}
79 // A vector of register file descriptors. This set always contains at least
80 // one entry. Entry at index #0 is reserved. That entry describes a register
81 // file with an unbounded number of physical registers that "sees" all the
82 // hardware registers declared by the target (i.e. all the register
83 // definitions in the target specific `XYZRegisterInfo.td` - where `XYZ` is
86 // Users can limit the number of physical registers that are available in
87 // regsiter file #0 specifying command line flag `-register-file-size=<uint>`.
88 SmallVector
<RegisterMappingTracker
, 4> RegisterFiles
;
90 // This type is used to propagate information about the owner of a register,
91 // and the cost of allocating it in the PRF. Register cost is defined as the
92 // number of physical registers consumed by the PRF to allocate a user
95 // For example: on X86 BtVer2, a YMM register consumes 2 128-bit physical
96 // registers. So, the cost of allocating a YMM register in BtVer2 is 2.
97 using IndexPlusCostPairTy
= std::pair
<unsigned, unsigned>;
99 // Struct RegisterRenamingInfo is used to map logical registers to register
102 // There is a RegisterRenamingInfo object for every logical register defined
103 // by the target. RegisteRenamingInfo objects are stored into vector
104 // `RegisterMappings`, and MCPhysReg IDs can be used to reference
105 // elements in that vector.
107 // Each RegisterRenamingInfo is owned by a PRF, and field `IndexPlusCost`
108 // specifies both the owning PRF, as well as the number of physical registers
109 // consumed at register renaming stage.
111 // Field `AllowMoveElimination` is set for registers that are used as
112 // destination by optimizable register moves.
114 // Field `AliasRegID` is set by writes from register moves that have been
115 // eliminated at register renaming stage. A move eliminated at register
116 // renaming stage is effectively bypassed, and its write aliases the source
117 // register definition.
118 struct RegisterRenamingInfo
{
119 IndexPlusCostPairTy IndexPlusCost
;
121 MCPhysReg AliasRegID
;
122 bool AllowMoveElimination
;
123 RegisterRenamingInfo()
124 : IndexPlusCost(std::make_pair(0U, 1U)), RenameAs(0U), AliasRegID(0U),
125 AllowMoveElimination(false) {}
128 // RegisterMapping objects are mainly used to track physical register
129 // definitions and resolve data dependencies.
131 // Every register declared by the Target is associated with an instance of
132 // RegisterMapping. RegisterMapping objects keep track of writes to a logical
133 // register. That information is used by class RegisterFile to resolve data
134 // dependencies, and correctly set latencies for register uses.
136 // This implementation does not allow overlapping register files. The only
137 // register file that is allowed to overlap with other register files is
138 // register file #0. If we exclude register #0, every register is "owned" by
139 // at most one register file.
140 using RegisterMapping
= std::pair
<WriteRef
, RegisterRenamingInfo
>;
142 // There is one entry per each register defined by the target.
143 std::vector
<RegisterMapping
> RegisterMappings
;
145 // Used to track zero registers. There is one bit for each register defined by
146 // the target. Bits are set for registers that are known to be zero.
149 // This method creates a new register file descriptor.
150 // The new register file owns all of the registers declared by register
151 // classes in the 'RegisterClasses' set.
153 // Processor models allow the definition of RegisterFile(s) via tablegen. For
154 // example, this is a tablegen definition for a x86 register file for
155 // XMM[0-15] and YMM[0-15], that allows up to 60 renames (each rename costs 1
156 // physical register).
158 // def FPRegisterFile : RegisterFile<60, [VR128RegClass, VR256RegClass]>
160 // Here FPRegisterFile contains all the registers defined by register class
161 // VR128RegClass and VR256RegClass. FPRegisterFile implements 60
162 // registers which can be used for register renaming purpose.
163 void addRegisterFile(const MCRegisterFileDesc
&RF
,
164 ArrayRef
<MCRegisterCostEntry
> Entries
);
166 // Consumes physical registers in each register file specified by the
167 // `IndexPlusCostPairTy`. This method is called from `addRegisterMapping()`.
168 void allocatePhysRegs(const RegisterRenamingInfo
&Entry
,
169 MutableArrayRef
<unsigned> UsedPhysRegs
);
171 // Releases previously allocated physical registers from the register file(s).
172 // This method is called from `invalidateRegisterMapping()`.
173 void freePhysRegs(const RegisterRenamingInfo
&Entry
,
174 MutableArrayRef
<unsigned> FreedPhysRegs
);
176 // Collects writes that are in a RAW dependency with RS.
177 // This method is called from `addRegisterRead()`.
178 void collectWrites(const ReadState
&RS
,
179 SmallVectorImpl
<WriteRef
> &Writes
) const;
181 // Create an instance of RegisterMappingTracker for every register file
182 // specified by the processor model.
183 // If no register file is specified, then this method creates a default
184 // register file with an unbounded number of physical registers.
185 void initialize(const MCSchedModel
&SM
, unsigned NumRegs
);
188 RegisterFile(const MCSchedModel
&SM
, const MCRegisterInfo
&mri
,
189 unsigned NumRegs
= 0);
191 // This method updates the register mappings inserting a new register
192 // definition. This method is also responsible for updating the number of
193 // allocated physical registers in each register file modified by the write.
194 // No physical regiser is allocated if this write is from a zero-idiom.
195 void addRegisterWrite(WriteRef Write
, MutableArrayRef
<unsigned> UsedPhysRegs
);
197 // Collect writes that are in a data dependency with RS, and update RS
199 void addRegisterRead(ReadState
&RS
, const MCSubtargetInfo
&STI
) const;
201 // Removes write \param WS from the register mappings.
202 // Physical registers may be released to reflect this update.
203 // No registers are released if this write is from a zero-idiom.
204 void removeRegisterWrite(const WriteState
&WS
,
205 MutableArrayRef
<unsigned> FreedPhysRegs
);
207 // Returns true if a move from RS to WS can be eliminated.
208 // On success, it updates WriteState by setting flag `WS.isEliminated`.
209 // If RS is a read from a zero register, and WS is eliminated, then
210 // `WS.WritesZero` is also set, so that method addRegisterWrite() would not
211 // reserve a physical register for it.
212 bool tryEliminateMove(WriteState
&WS
, ReadState
&RS
);
214 // Checks if there are enough physical registers in the register files.
215 // Returns a "response mask" where each bit represents the response from a
216 // different register file. A mask of all zeroes means that all register
217 // files are available. Otherwise, the mask can be used to identify which
218 // register file was busy. This sematic allows us to classify dispatch
219 // stalls caused by the lack of register file resources.
221 // Current implementation can simulate up to 32 register files (including the
222 // special register file at index #0).
223 unsigned isAvailable(ArrayRef
<MCPhysReg
> Regs
) const;
225 // Returns the number of PRFs implemented by this processor.
226 unsigned getNumRegisterFiles() const { return RegisterFiles
.size(); }
228 // Notify each PRF that a new cycle just started.
239 #endif // LLVM_MCA_REGISTER_FILE_H