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_REGISTER_FILE_H 17 #define LLVM_MCA_REGISTER_FILE_H 18 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" 26 27 namespace llvm { 28 namespace mca { 29 30 class ReadState; 31 class WriteState; 32 class WriteRef; 33 34 /// Manages hardware register files, and tracks register definitions for 35 /// register renaming purposes. 36 class RegisterFile : public HardwareUnit { 37 const MCRegisterInfo &MRI; 38 39 // class RegisterMappingTracker is a physical register file (PRF) descriptor. 40 // There is one RegisterMappingTracker for every PRF definition in the 41 // scheduling model. 42 // 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 50 // registers. 51 const unsigned NumPhysRegs; 52 // Number of physical registers that are currently in use. 53 unsigned NumUsedPhysRegs; 54 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; 59 60 // Number of register moves eliminated during this cycle. 61 // 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; 67 68 // If set, move elimination is restricted to zero-register moves only. 69 bool AllowZeroMoveEliminationOnly; 70 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) {} 77 }; 78 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 84 // the target name). 85 // 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; 89 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 93 // register. 94 // 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>; 98 99 // Struct RegisterRenamingInfo is used to map logical registers to register 100 // files. 101 // 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. 106 // 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. 110 // 111 // Field `AllowMoveElimination` is set for registers that are used as 112 // destination by optimizable register moves. 113 // 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; 120 MCPhysReg RenameAs; 121 MCPhysReg AliasRegID; 122 bool AllowMoveElimination; 123 RegisterRenamingInfo() 124 : IndexPlusCost(std::make_pair(0U, 1U)), RenameAs(0U), AliasRegID(0U), 125 AllowMoveElimination(false) {} 126 }; 127 128 // RegisterMapping objects are mainly used to track physical register 129 // definitions and resolve data dependencies. 130 // 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. 135 // 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>; 141 142 // There is one entry per each register defined by the target. 143 std::vector<RegisterMapping> RegisterMappings; 144 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. 147 APInt ZeroRegisters; 148 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. 152 // 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). 157 // 158 // def FPRegisterFile : RegisterFile<60, [VR128RegClass, VR256RegClass]> 159 // 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); 165 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); 170 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); 175 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; 180 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); 186 187 public: 188 RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri, 189 unsigned NumRegs = 0); 190 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); 196 197 // Collect writes that are in a data dependency with RS, and update RS 198 // internal state. 199 void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const; 200 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); 206 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); 213 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. 220 // 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; 224 225 // Returns the number of PRFs implemented by this processor. 226 unsigned getNumRegisterFiles() const { return RegisterFiles.size(); } 227 228 // Notify each PRF that a new cycle just started. 229 void cycleStart(); 230 231 #ifndef NDEBUG 232 void dump() const; 233 #endif 234 }; 235 236 } // namespace mca 237 } // namespace llvm 238 239 #endif // LLVM_MCA_REGISTER_FILE_H 240