• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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