Che-Liang Chiou | 3278c42 | 2010-11-08 03:00:52 +0000 | [diff] [blame] | 1 | //===- PTXMachineFuctionInfo.h - PTX machine function info -------*- 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 | // |
| 10 | // This file declares PTX-specific per-machine-function information. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef PTX_MACHINE_FUNCTION_INFO_H |
| 15 | #define PTX_MACHINE_FUNCTION_INFO_H |
| 16 | |
| 17 | #include "PTX.h" |
Justin Holewinski | 27f08fc | 2011-09-23 14:18:22 +0000 | [diff] [blame] | 18 | #include "PTXParamManager.h" |
Justin Holewinski | 297984d | 2011-09-22 16:45:40 +0000 | [diff] [blame] | 19 | #include "PTXRegisterInfo.h" |
| 20 | #include "llvm/ADT/DenseMap.h" |
Justin Holewinski | e0aef2d | 2011-06-16 17:50:00 +0000 | [diff] [blame] | 21 | #include "llvm/ADT/DenseSet.h" |
Justin Holewinski | 297984d | 2011-09-22 16:45:40 +0000 | [diff] [blame] | 22 | #include "llvm/ADT/StringExtras.h" |
Che-Liang Chiou | 3278c42 | 2010-11-08 03:00:52 +0000 | [diff] [blame] | 23 | #include "llvm/CodeGen/MachineFunction.h" |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 24 | #include "llvm/Support/Debug.h" |
| 25 | #include "llvm/Support/raw_ostream.h" |
Che-Liang Chiou | 3278c42 | 2010-11-08 03:00:52 +0000 | [diff] [blame] | 26 | |
| 27 | namespace llvm { |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 28 | |
Che-Liang Chiou | 3278c42 | 2010-11-08 03:00:52 +0000 | [diff] [blame] | 29 | /// PTXMachineFunctionInfo - This class is derived from MachineFunction and |
| 30 | /// contains private PTX target-specific information for each MachineFunction. |
| 31 | /// |
| 32 | class PTXMachineFunctionInfo : public MachineFunctionInfo { |
| 33 | private: |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 34 | bool IsKernel; |
| 35 | DenseSet<unsigned> RegArgs; |
| 36 | DenseSet<unsigned> RegRets; |
Che-Liang Chiou | 3278c42 | 2010-11-08 03:00:52 +0000 | [diff] [blame] | 37 | |
Justin Holewinski | f47dfba | 2011-09-27 18:12:55 +0000 | [diff] [blame] | 38 | typedef DenseMap<int, std::string> FrameMap; |
Justin Holewinski | 297984d | 2011-09-22 16:45:40 +0000 | [diff] [blame] | 39 | |
Justin Holewinski | f47dfba | 2011-09-27 18:12:55 +0000 | [diff] [blame] | 40 | FrameMap FrameSymbols; |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 41 | |
Justin Holewinski | 4c7ffb6 | 2011-12-06 17:39:48 +0000 | [diff] [blame^] | 42 | struct RegisterInfo { |
| 43 | unsigned Reg; |
| 44 | unsigned Type; |
| 45 | unsigned Space; |
| 46 | unsigned Offset; |
| 47 | unsigned Encoded; |
| 48 | }; |
| 49 | |
| 50 | typedef DenseMap<unsigned, RegisterInfo> RegisterInfoMap; |
| 51 | |
| 52 | RegisterInfoMap RegInfo; |
| 53 | |
Justin Holewinski | 27f08fc | 2011-09-23 14:18:22 +0000 | [diff] [blame] | 54 | PTXParamManager ParamManager; |
| 55 | |
Che-Liang Chiou | 3278c42 | 2010-11-08 03:00:52 +0000 | [diff] [blame] | 56 | public: |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 57 | typedef DenseSet<unsigned>::const_iterator reg_iterator; |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 58 | |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 59 | PTXMachineFunctionInfo(MachineFunction &MF) |
| 60 | : IsKernel(false) { |
Justin Holewinski | 4c7ffb6 | 2011-12-06 17:39:48 +0000 | [diff] [blame^] | 61 | } |
Che-Liang Chiou | 3278c42 | 2010-11-08 03:00:52 +0000 | [diff] [blame] | 62 | |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 63 | /// getParamManager - Returns the PTXParamManager instance for this function. |
Justin Holewinski | 27f08fc | 2011-09-23 14:18:22 +0000 | [diff] [blame] | 64 | PTXParamManager& getParamManager() { return ParamManager; } |
| 65 | const PTXParamManager& getParamManager() const { return ParamManager; } |
| 66 | |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 67 | /// setKernel/isKernel - Gets/sets a flag that indicates if this function is |
| 68 | /// a PTX kernel function. |
| 69 | void setKernel(bool _IsKernel=true) { IsKernel = _IsKernel; } |
| 70 | bool isKernel() const { return IsKernel; } |
Che-Liang Chiou | 3278c42 | 2010-11-08 03:00:52 +0000 | [diff] [blame] | 71 | |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 72 | /// argreg_begin/argreg_end - Returns iterators to the set of registers |
| 73 | /// containing function arguments. |
| 74 | reg_iterator argreg_begin() const { return RegArgs.begin(); } |
| 75 | reg_iterator argreg_end() const { return RegArgs.end(); } |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 76 | |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 77 | /// retreg_begin/retreg_end - Returns iterators to the set of registers |
| 78 | /// containing the function return values. |
| 79 | reg_iterator retreg_begin() const { return RegRets.begin(); } |
| 80 | reg_iterator retreg_end() const { return RegRets.end(); } |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 81 | |
Justin Holewinski | 4c7ffb6 | 2011-12-06 17:39:48 +0000 | [diff] [blame^] | 82 | /// addRegister - Adds a virtual register to the set of all used registers |
| 83 | void addRegister(unsigned Reg, unsigned RegType, unsigned RegSpace) { |
| 84 | if (!RegInfo.count(Reg)) { |
| 85 | RegisterInfo Info; |
| 86 | Info.Reg = Reg; |
| 87 | Info.Type = RegType; |
| 88 | Info.Space = RegSpace; |
| 89 | |
| 90 | // Determine register offset |
| 91 | Info.Offset = 0; |
| 92 | for(RegisterInfoMap::const_iterator i = RegInfo.begin(), |
| 93 | e = RegInfo.end(); i != e; ++i) { |
| 94 | const RegisterInfo& RI = i->second; |
| 95 | if (RI.Space == RegSpace) |
| 96 | if (RI.Space != PTXRegisterSpace::Reg || RI.Type == Info.Type) |
| 97 | Info.Offset++; |
| 98 | } |
| 99 | |
| 100 | // Encode the register data into a single register number |
| 101 | Info.Encoded = (Info.Offset << 6) | (Info.Type << 3) | Info.Space; |
| 102 | |
| 103 | RegInfo[Reg] = Info; |
| 104 | |
| 105 | if (RegSpace == PTXRegisterSpace::Argument) |
| 106 | RegArgs.insert(Reg); |
| 107 | else if (RegSpace == PTXRegisterSpace::Return) |
| 108 | RegRets.insert(Reg); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | /// countRegisters - Returns the number of registers of the given type and |
| 113 | /// space. |
| 114 | unsigned countRegisters(unsigned RegType, unsigned RegSpace) const { |
| 115 | unsigned Count = 0; |
| 116 | for(RegisterInfoMap::const_iterator i = RegInfo.begin(), e = RegInfo.end(); |
| 117 | i != e; ++i) { |
| 118 | const RegisterInfo& RI = i->second; |
| 119 | if (RI.Type == RegType && RI.Space == RegSpace) |
| 120 | Count++; |
| 121 | } |
| 122 | return Count; |
| 123 | } |
| 124 | |
| 125 | /// getEncodedRegister - Returns the encoded value of the register. |
| 126 | unsigned getEncodedRegister(unsigned Reg) const { |
| 127 | return RegInfo.lookup(Reg).Encoded; |
| 128 | } |
| 129 | |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 130 | /// addRetReg - Adds a register to the set of return-value registers. |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 131 | void addRetReg(unsigned Reg) { |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 132 | if (!RegRets.count(Reg)) { |
| 133 | RegRets.insert(Reg); |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 134 | } |
| 135 | } |
Justin Holewinski | 297984d | 2011-09-22 16:45:40 +0000 | [diff] [blame] | 136 | |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 137 | /// addArgReg - Adds a register to the set of function argument registers. |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 138 | void addArgReg(unsigned Reg) { |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 139 | RegArgs.insert(Reg); |
Justin Holewinski | 297984d | 2011-09-22 16:45:40 +0000 | [diff] [blame] | 140 | } |
| 141 | |
Justin Holewinski | dc0baf9 | 2011-09-23 17:15:53 +0000 | [diff] [blame] | 142 | /// getRegisterName - Returns the name of the specified virtual register. This |
| 143 | /// name is used during PTX emission. |
Justin Holewinski | 4c7ffb6 | 2011-12-06 17:39:48 +0000 | [diff] [blame^] | 144 | std::string getRegisterName(unsigned Reg) const { |
| 145 | if (RegInfo.count(Reg)) { |
| 146 | const RegisterInfo& RI = RegInfo.lookup(Reg); |
| 147 | std::string Name; |
| 148 | raw_string_ostream NameStr(Name); |
| 149 | decodeRegisterName(NameStr, RI.Encoded); |
| 150 | NameStr.flush(); |
| 151 | return Name; |
| 152 | } |
Justin Holewinski | 5422a0f | 2011-09-22 16:45:46 +0000 | [diff] [blame] | 153 | else if (Reg == PTX::NoRegister) |
| 154 | return "%noreg"; |
Justin Holewinski | 297984d | 2011-09-22 16:45:40 +0000 | [diff] [blame] | 155 | else |
| 156 | llvm_unreachable("Register not in register name map"); |
| 157 | } |
| 158 | |
Justin Holewinski | 4c7ffb6 | 2011-12-06 17:39:48 +0000 | [diff] [blame^] | 159 | /// getEncodedRegisterName - Returns the name of the encoded register. |
| 160 | std::string getEncodedRegisterName(unsigned EncodedReg) const { |
| 161 | std::string Name; |
| 162 | raw_string_ostream NameStr(Name); |
| 163 | decodeRegisterName(NameStr, EncodedReg); |
| 164 | NameStr.flush(); |
| 165 | return Name; |
| 166 | } |
| 167 | |
| 168 | /// getRegisterType - Returns the type of the specified virtual register. |
| 169 | unsigned getRegisterType(unsigned Reg) const { |
| 170 | if (RegInfo.count(Reg)) |
| 171 | return RegInfo.lookup(Reg).Type; |
| 172 | else |
| 173 | llvm_unreachable("Unknown register"); |
Justin Holewinski | 297984d | 2011-09-22 16:45:40 +0000 | [diff] [blame] | 174 | } |
| 175 | |
Justin Holewinski | e37a83f | 2011-12-06 17:39:46 +0000 | [diff] [blame] | 176 | /// getOffsetForRegister - Returns the offset of the virtual register |
Justin Holewinski | 4c7ffb6 | 2011-12-06 17:39:48 +0000 | [diff] [blame^] | 177 | unsigned getOffsetForRegister(unsigned Reg) const { |
| 178 | if (RegInfo.count(Reg)) |
| 179 | return RegInfo.lookup(Reg).Offset; |
| 180 | else |
| 181 | return 0; |
Justin Holewinski | e37a83f | 2011-12-06 17:39:46 +0000 | [diff] [blame] | 182 | } |
| 183 | |
Justin Holewinski | f47dfba | 2011-09-27 18:12:55 +0000 | [diff] [blame] | 184 | /// getFrameSymbol - Returns the symbol name for the given FrameIndex. |
| 185 | const char* getFrameSymbol(int FrameIndex) { |
| 186 | if (FrameSymbols.count(FrameIndex)) { |
| 187 | return FrameSymbols.lookup(FrameIndex).c_str(); |
| 188 | } else { |
Justin Holewinski | e37a83f | 2011-12-06 17:39:46 +0000 | [diff] [blame] | 189 | std::string Name = "__local"; |
| 190 | Name += utostr(FrameIndex); |
Justin Holewinski | f47dfba | 2011-09-27 18:12:55 +0000 | [diff] [blame] | 191 | // The whole point of caching this name is to ensure the pointer we pass |
| 192 | // to any getExternalSymbol() calls will remain valid for the lifetime of |
| 193 | // the back-end instance. This is to work around an issue in SelectionDAG |
| 194 | // where symbol names are expected to be life-long strings. |
Justin Holewinski | e37a83f | 2011-12-06 17:39:46 +0000 | [diff] [blame] | 195 | FrameSymbols[FrameIndex] = Name; |
Justin Holewinski | f47dfba | 2011-09-27 18:12:55 +0000 | [diff] [blame] | 196 | return FrameSymbols[FrameIndex].c_str(); |
| 197 | } |
| 198 | } |
Che-Liang Chiou | 3278c42 | 2010-11-08 03:00:52 +0000 | [diff] [blame] | 199 | }; // class PTXMachineFunctionInfo |
| 200 | } // namespace llvm |
| 201 | |
| 202 | #endif // PTX_MACHINE_FUNCTION_INFO_H |