1 //===--------------------- RegisterFile.h -----------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// 11 /// This file defines a register mapping file class. This class is responsible 12 /// for managing hardware register files and the tracking of data dependencies 13 /// between registers. 14 /// 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H 18 #define LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H 19 20 #include "HardwareUnit.h" 21 #include "llvm/ADT/SmallVector.h" 22 #include "llvm/MC/MCRegisterInfo.h" 23 #include "llvm/MC/MCSchedule.h" 24 25 namespace mca { 26 27 class ReadState; 28 class WriteState; 29 class WriteRef; 30 31 /// Manages hardware register files, and tracks register definitions for 32 /// register renaming purposes. 33 class RegisterFile : public HardwareUnit { 34 const llvm::MCRegisterInfo &MRI; 35 36 // Each register file is associated with an instance of 37 // RegisterMappingTracker. 38 // A RegisterMappingTracker keeps track of the number of physical registers 39 // which have been dynamically allocated by the simulator. 40 struct RegisterMappingTracker { 41 // The total number of physical registers that are available in this 42 // register file for register renaming purpouses. A value of zero for this 43 // field means: this register file has an unbounded number of physical 44 // registers. 45 const unsigned NumPhysRegs; 46 // Number of physical registers that are currently in use. 47 unsigned NumUsedPhysRegs; 48 RegisterMappingTrackerRegisterMappingTracker49 RegisterMappingTracker(unsigned NumPhysRegisters) 50 : NumPhysRegs(NumPhysRegisters), NumUsedPhysRegs(0) {} 51 }; 52 53 // A vector of register file descriptors. This set always contains at least 54 // one entry. Entry at index #0 is reserved. That entry describes a register 55 // file with an unbounded number of physical registers that "sees" all the 56 // hardware registers declared by the target (i.e. all the register 57 // definitions in the target specific `XYZRegisterInfo.td` - where `XYZ` is 58 // the target name). 59 // 60 // Users can limit the number of physical registers that are available in 61 // regsiter file #0 specifying command line flag `-register-file-size=<uint>`. 62 llvm::SmallVector<RegisterMappingTracker, 4> RegisterFiles; 63 64 // This type is used to propagate information about the owner of a register, 65 // and the cost of allocating it in the PRF. Register cost is defined as the 66 // number of physical registers consumed by the PRF to allocate a user 67 // register. 68 // 69 // For example: on X86 BtVer2, a YMM register consumes 2 128-bit physical 70 // registers. So, the cost of allocating a YMM register in BtVer2 is 2. 71 using IndexPlusCostPairTy = std::pair<unsigned, unsigned>; 72 73 // Struct RegisterRenamingInfo maps registers to register files. 74 // There is a RegisterRenamingInfo object for every register defined by 75 // the target. RegisteRenamingInfo objects are stored into vector 76 // RegisterMappings, and register IDs can be used to reference them. 77 struct RegisterRenamingInfo { 78 IndexPlusCostPairTy IndexPlusCost; 79 llvm::MCPhysReg RenameAs; 80 }; 81 82 // RegisterMapping objects are mainly used to track physical register 83 // definitions. There is a RegisterMapping for every register defined by the 84 // Target. For each register, a RegisterMapping pair contains a descriptor of 85 // the last register write (in the form of a WriteRef object), as well as a 86 // RegisterRenamingInfo to quickly identify owning register files. 87 // 88 // This implementation does not allow overlapping register files. The only 89 // register file that is allowed to overlap with other register files is 90 // register file #0. If we exclude register #0, every register is "owned" by 91 // at most one register file. 92 using RegisterMapping = std::pair<WriteRef, RegisterRenamingInfo>; 93 94 // This map contains one entry for each register defined by the target. 95 std::vector<RegisterMapping> RegisterMappings; 96 97 // This method creates a new register file descriptor. 98 // The new register file owns all of the registers declared by register 99 // classes in the 'RegisterClasses' set. 100 // 101 // Processor models allow the definition of RegisterFile(s) via tablegen. For 102 // example, this is a tablegen definition for a x86 register file for 103 // XMM[0-15] and YMM[0-15], that allows up to 60 renames (each rename costs 1 104 // physical register). 105 // 106 // def FPRegisterFile : RegisterFile<60, [VR128RegClass, VR256RegClass]> 107 // 108 // Here FPRegisterFile contains all the registers defined by register class 109 // VR128RegClass and VR256RegClass. FPRegisterFile implements 60 110 // registers which can be used for register renaming purpose. 111 void 112 addRegisterFile(llvm::ArrayRef<llvm::MCRegisterCostEntry> RegisterClasses, 113 unsigned NumPhysRegs); 114 115 // Consumes physical registers in each register file specified by the 116 // `IndexPlusCostPairTy`. This method is called from `addRegisterMapping()`. 117 void allocatePhysRegs(const RegisterRenamingInfo &Entry, 118 llvm::MutableArrayRef<unsigned> UsedPhysRegs); 119 120 // Releases previously allocated physical registers from the register file(s). 121 // This method is called from `invalidateRegisterMapping()`. 122 void freePhysRegs(const RegisterRenamingInfo &Entry, 123 llvm::MutableArrayRef<unsigned> FreedPhysRegs); 124 125 // Create an instance of RegisterMappingTracker for every register file 126 // specified by the processor model. 127 // If no register file is specified, then this method creates a default 128 // register file with an unbounded number of physical registers. 129 void initialize(const llvm::MCSchedModel &SM, unsigned NumRegs); 130 131 public: 132 RegisterFile(const llvm::MCSchedModel &SM, const llvm::MCRegisterInfo &mri, 133 unsigned NumRegs = 0); 134 135 // This method updates the register mappings inserting a new register 136 // definition. This method is also responsible for updating the number of 137 // allocated physical registers in each register file modified by the write. 138 // No physical regiser is allocated when flag ShouldAllocatePhysRegs is set. 139 void addRegisterWrite(WriteRef Write, 140 llvm::MutableArrayRef<unsigned> UsedPhysRegs, 141 bool ShouldAllocatePhysRegs = true); 142 143 // Removes write \param WS from the register mappings. 144 // Physical registers may be released to reflect this update. 145 void removeRegisterWrite(const WriteState &WS, 146 llvm::MutableArrayRef<unsigned> FreedPhysRegs, 147 bool ShouldFreePhysRegs = true); 148 149 // Checks if there are enough physical registers in the register files. 150 // Returns a "response mask" where each bit represents the response from a 151 // different register file. A mask of all zeroes means that all register 152 // files are available. Otherwise, the mask can be used to identify which 153 // register file was busy. This sematic allows us to classify dispatch 154 // stalls caused by the lack of register file resources. 155 // 156 // Current implementation can simulate up to 32 register files (including the 157 // special register file at index #0). 158 unsigned isAvailable(llvm::ArrayRef<unsigned> Regs) const; 159 void collectWrites(llvm::SmallVectorImpl<WriteRef> &Writes, 160 unsigned RegID) const; 161 void updateOnRead(ReadState &RS, unsigned RegID); 162 getNumRegisterFiles()163 unsigned getNumRegisterFiles() const { return RegisterFiles.size(); } 164 165 #ifndef NDEBUG 166 void dump() const; 167 #endif 168 }; 169 170 } // namespace mca 171 172 #endif // LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H 173