|
|
|||
File indexing completed on 2026-05-10 08:44:16
0001 //===--------------------- RegisterFile.h -----------------------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 /// \file 0009 /// 0010 /// This file defines a register mapping file class. This class is responsible 0011 /// for managing hardware register files and the tracking of data dependencies 0012 /// between registers. 0013 /// 0014 //===----------------------------------------------------------------------===// 0015 0016 #ifndef LLVM_MCA_HARDWAREUNITS_REGISTERFILE_H 0017 #define LLVM_MCA_HARDWAREUNITS_REGISTERFILE_H 0018 0019 #include "llvm/ADT/APInt.h" 0020 #include "llvm/ADT/SmallVector.h" 0021 #include "llvm/MC/MCRegisterInfo.h" 0022 #include "llvm/MC/MCSchedule.h" 0023 #include "llvm/MC/MCSubtargetInfo.h" 0024 #include "llvm/MCA/HardwareUnits/HardwareUnit.h" 0025 0026 namespace llvm { 0027 namespace mca { 0028 0029 class ReadState; 0030 class WriteState; 0031 class Instruction; 0032 0033 /// A reference to a register write. 0034 /// 0035 /// This class is mainly used by the register file to describe register 0036 /// mappings. It correlates a register write to the source index of the 0037 /// defining instruction. 0038 class WriteRef { 0039 unsigned IID; 0040 unsigned WriteBackCycle; 0041 unsigned WriteResID; 0042 MCPhysReg RegisterID; 0043 WriteState *Write; 0044 0045 static const unsigned INVALID_IID; 0046 0047 public: 0048 WriteRef() 0049 : IID(INVALID_IID), WriteBackCycle(), WriteResID(), RegisterID(), 0050 Write() {} 0051 WriteRef(unsigned SourceIndex, WriteState *WS); 0052 0053 unsigned getSourceIndex() const { return IID; } 0054 unsigned getWriteBackCycle() const; 0055 0056 const WriteState *getWriteState() const { return Write; } 0057 WriteState *getWriteState() { return Write; } 0058 unsigned getWriteResourceID() const; 0059 MCPhysReg getRegisterID() const; 0060 0061 void commit(); 0062 void notifyExecuted(unsigned Cycle); 0063 0064 bool hasKnownWriteBackCycle() const; 0065 bool isWriteZero() const; 0066 bool isValid() const { return getSourceIndex() != INVALID_IID; } 0067 0068 /// Returns true if this register write has been executed, and the new 0069 /// register value is therefore available to users. 0070 bool isAvailable() const { return hasKnownWriteBackCycle(); } 0071 0072 bool operator==(const WriteRef &Other) const { 0073 return Write && Other.Write && Write == Other.Write; 0074 } 0075 0076 #ifndef NDEBUG 0077 void dump() const; 0078 #endif 0079 }; 0080 0081 /// Manages hardware register files, and tracks register definitions for 0082 /// register renaming purposes. 0083 class RegisterFile : public HardwareUnit { 0084 const MCRegisterInfo &MRI; 0085 0086 // class RegisterMappingTracker is a physical register file (PRF) descriptor. 0087 // There is one RegisterMappingTracker for every PRF definition in the 0088 // scheduling model. 0089 // 0090 // An instance of RegisterMappingTracker tracks the number of physical 0091 // registers available for renaming. It also tracks the number of register 0092 // moves eliminated per cycle. 0093 struct RegisterMappingTracker { 0094 // The total number of physical registers that are available in this 0095 // register file for register renaming purpouses. A value of zero for this 0096 // field means: this register file has an unbounded number of physical 0097 // registers. 0098 const unsigned NumPhysRegs; 0099 // Number of physical registers that are currently in use. 0100 unsigned NumUsedPhysRegs; 0101 0102 // Maximum number of register moves that can be eliminated by this PRF every 0103 // cycle. A value of zero means that there is no limit in the number of 0104 // moves which can be eliminated every cycle. 0105 const unsigned MaxMoveEliminatedPerCycle; 0106 0107 // Number of register moves eliminated during this cycle. 0108 // 0109 // This value is increased by one every time a register move is eliminated. 0110 // Every new cycle, this value is reset to zero. 0111 // A move can be eliminated only if MaxMoveEliminatedPerCycle is zero, or if 0112 // NumMoveEliminated is less than MaxMoveEliminatedPerCycle. 0113 unsigned NumMoveEliminated; 0114 0115 // If set, move elimination is restricted to zero-register moves only. 0116 bool AllowZeroMoveEliminationOnly; 0117 0118 RegisterMappingTracker(unsigned NumPhysRegisters, 0119 unsigned MaxMoveEliminated = 0U, 0120 bool AllowZeroMoveElimOnly = false) 0121 : NumPhysRegs(NumPhysRegisters), NumUsedPhysRegs(0), 0122 MaxMoveEliminatedPerCycle(MaxMoveEliminated), NumMoveEliminated(0U), 0123 AllowZeroMoveEliminationOnly(AllowZeroMoveElimOnly) {} 0124 }; 0125 0126 // A vector of register file descriptors. This set always contains at least 0127 // one entry. Entry at index #0 is reserved. That entry describes a register 0128 // file with an unbounded number of physical registers that "sees" all the 0129 // hardware registers declared by the target (i.e. all the register 0130 // definitions in the target specific `XYZRegisterInfo.td` - where `XYZ` is 0131 // the target name). 0132 // 0133 // Users can limit the number of physical registers that are available in 0134 // register file #0 specifying command line flag `-register-file-size=<uint>`. 0135 SmallVector<RegisterMappingTracker, 4> RegisterFiles; 0136 0137 // This type is used to propagate information about the owner of a register, 0138 // and the cost of allocating it in the PRF. Register cost is defined as the 0139 // number of physical registers consumed by the PRF to allocate a user 0140 // register. 0141 // 0142 // For example: on X86 BtVer2, a YMM register consumes 2 128-bit physical 0143 // registers. So, the cost of allocating a YMM register in BtVer2 is 2. 0144 using IndexPlusCostPairTy = std::pair<unsigned, unsigned>; 0145 0146 // Struct RegisterRenamingInfo is used to map logical registers to register 0147 // files. 0148 // 0149 // There is a RegisterRenamingInfo object for every logical register defined 0150 // by the target. RegisteRenamingInfo objects are stored into vector 0151 // `RegisterMappings`, and MCPhysReg IDs can be used to reference 0152 // elements in that vector. 0153 // 0154 // Each RegisterRenamingInfo is owned by a PRF, and field `IndexPlusCost` 0155 // specifies both the owning PRF, as well as the number of physical registers 0156 // consumed at register renaming stage. 0157 // 0158 // Field `AllowMoveElimination` is set for registers that are used as 0159 // destination by optimizable register moves. 0160 // 0161 // Field `AliasRegID` is set by writes from register moves that have been 0162 // eliminated at register renaming stage. A move eliminated at register 0163 // renaming stage is effectively bypassed, and its write aliases the source 0164 // register definition. 0165 struct RegisterRenamingInfo { 0166 IndexPlusCostPairTy IndexPlusCost; 0167 MCPhysReg RenameAs; 0168 MCPhysReg AliasRegID; 0169 bool AllowMoveElimination; 0170 RegisterRenamingInfo() 0171 : IndexPlusCost(std::make_pair(0U, 1U)), RenameAs(0U), AliasRegID(0U), 0172 AllowMoveElimination(false) {} 0173 }; 0174 0175 // RegisterMapping objects are mainly used to track physical register 0176 // definitions and resolve data dependencies. 0177 // 0178 // Every register declared by the Target is associated with an instance of 0179 // RegisterMapping. RegisterMapping objects keep track of writes to a logical 0180 // register. That information is used by class RegisterFile to resolve data 0181 // dependencies, and correctly set latencies for register uses. 0182 // 0183 // This implementation does not allow overlapping register files. The only 0184 // register file that is allowed to overlap with other register files is 0185 // register file #0. If we exclude register #0, every register is "owned" by 0186 // at most one register file. 0187 using RegisterMapping = std::pair<WriteRef, RegisterRenamingInfo>; 0188 0189 // There is one entry per each register defined by the target. 0190 std::vector<RegisterMapping> RegisterMappings; 0191 0192 // Used to track zero registers. There is one bit for each register defined by 0193 // the target. Bits are set for registers that are known to be zero. 0194 APInt ZeroRegisters; 0195 0196 unsigned CurrentCycle; 0197 0198 // This method creates a new register file descriptor. 0199 // The new register file owns all of the registers declared by register 0200 // classes in the 'RegisterClasses' set. 0201 // 0202 // Processor models allow the definition of RegisterFile(s) via tablegen. For 0203 // example, this is a tablegen definition for a x86 register file for 0204 // XMM[0-15] and YMM[0-15], that allows up to 60 renames (each rename costs 1 0205 // physical register). 0206 // 0207 // def FPRegisterFile : RegisterFile<60, [VR128RegClass, VR256RegClass]> 0208 // 0209 // Here FPRegisterFile contains all the registers defined by register class 0210 // VR128RegClass and VR256RegClass. FPRegisterFile implements 60 0211 // registers which can be used for register renaming purpose. 0212 void addRegisterFile(const MCRegisterFileDesc &RF, 0213 ArrayRef<MCRegisterCostEntry> Entries); 0214 0215 // Consumes physical registers in each register file specified by the 0216 // `IndexPlusCostPairTy`. This method is called from `addRegisterMapping()`. 0217 void allocatePhysRegs(const RegisterRenamingInfo &Entry, 0218 MutableArrayRef<unsigned> UsedPhysRegs); 0219 0220 // Releases previously allocated physical registers from the register file(s). 0221 // This method is called from `invalidateRegisterMapping()`. 0222 void freePhysRegs(const RegisterRenamingInfo &Entry, 0223 MutableArrayRef<unsigned> FreedPhysRegs); 0224 0225 // Create an instance of RegisterMappingTracker for every register file 0226 // specified by the processor model. 0227 // If no register file is specified, then this method creates a default 0228 // register file with an unbounded number of physical registers. 0229 void initialize(const MCSchedModel &SM, unsigned NumRegs); 0230 0231 public: 0232 RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri, 0233 unsigned NumRegs = 0); 0234 0235 // Collects writes that are in a RAW dependency with RS. 0236 void collectWrites(const MCSubtargetInfo &STI, const ReadState &RS, 0237 SmallVectorImpl<WriteRef> &Writes, 0238 SmallVectorImpl<WriteRef> &CommittedWrites) const; 0239 struct RAWHazard { 0240 MCPhysReg RegisterID = 0; 0241 int CyclesLeft = 0; 0242 0243 RAWHazard() = default; 0244 bool isValid() const { return RegisterID; } 0245 bool hasUnknownCycles() const { return CyclesLeft < 0; } 0246 }; 0247 0248 RAWHazard checkRAWHazards(const MCSubtargetInfo &STI, 0249 const ReadState &RS) const; 0250 0251 // This method updates the register mappings inserting a new register 0252 // definition. This method is also responsible for updating the number of 0253 // allocated physical registers in each register file modified by the write. 0254 // No physical regiser is allocated if this write is from a zero-idiom. 0255 void addRegisterWrite(WriteRef Write, MutableArrayRef<unsigned> UsedPhysRegs); 0256 0257 // Collect writes that are in a data dependency with RS, and update RS 0258 // internal state. 0259 void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const; 0260 0261 // Removes write \param WS from the register mappings. 0262 // Physical registers may be released to reflect this update. 0263 // No registers are released if this write is from a zero-idiom. 0264 void removeRegisterWrite(const WriteState &WS, 0265 MutableArrayRef<unsigned> FreedPhysRegs); 0266 0267 // Returns true if the PRF at index `PRFIndex` can eliminate a move from RS to 0268 // WS. 0269 bool canEliminateMove(const WriteState &WS, const ReadState &RS, 0270 unsigned PRFIndex) const; 0271 0272 // Returns true if this instruction can be fully eliminated at register 0273 // renaming stage. On success, this method updates the internal state of each 0274 // WriteState by setting flag `WS.isEliminated`, and by propagating the zero 0275 // flag for known zero registers. It internally uses `canEliminateMove` to 0276 // determine if a read/write pair can be eliminated. By default, it assumes a 0277 // register swap if there is more than one register definition. 0278 bool tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes, 0279 MutableArrayRef<ReadState> Reads); 0280 0281 // Checks if there are enough physical registers in the register files. 0282 // Returns a "response mask" where each bit represents the response from a 0283 // different register file. A mask of all zeroes means that all register 0284 // files are available. Otherwise, the mask can be used to identify which 0285 // register file was busy. This sematic allows us to classify dispatch 0286 // stalls caused by the lack of register file resources. 0287 // 0288 // Current implementation can simulate up to 32 register files (including the 0289 // special register file at index #0). 0290 unsigned isAvailable(ArrayRef<MCPhysReg> Regs) const; 0291 0292 // Returns the number of PRFs implemented by this processor. 0293 unsigned getNumRegisterFiles() const { return RegisterFiles.size(); } 0294 0295 unsigned getElapsedCyclesFromWriteBack(const WriteRef &WR) const; 0296 0297 void onInstructionExecuted(Instruction *IS); 0298 0299 // Notify each PRF that a new cycle just started. 0300 void cycleStart(); 0301 0302 void cycleEnd() { ++CurrentCycle; } 0303 0304 #ifndef NDEBUG 0305 void dump() const; 0306 #endif 0307 }; 0308 0309 } // namespace mca 0310 } // namespace llvm 0311 0312 #endif // LLVM_MCA_HARDWAREUNITS_REGISTERFILE_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|