1 //===--- AMDGPU.h - Declare AMDGPU target feature support -------*- 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 AMDGPU TargetInfo objects. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H 15 #define LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H 16 17 #include "clang/Basic/TargetInfo.h" 18 #include "clang/Basic/TargetOptions.h" 19 #include "llvm/ADT/StringSet.h" 20 #include "llvm/ADT/Triple.h" 21 #include "llvm/Support/Compiler.h" 22 23 namespace clang { 24 namespace targets { 25 26 class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { 27 28 static const Builtin::Info BuiltinInfo[]; 29 static const char *const GCCRegNames[]; 30 31 struct LLVM_LIBRARY_VISIBILITY AddrSpace { 32 unsigned Generic, Global, Local, Constant, Private; 33 AddrSpace(bool IsGenericZero_ = false) { 34 if (IsGenericZero_) { 35 Generic = 0; 36 Global = 1; 37 Local = 3; 38 Constant = 2; 39 Private = 5; 40 } else { 41 Generic = 4; 42 Global = 1; 43 Local = 3; 44 Constant = 2; 45 Private = 0; 46 } 47 } 48 }; 49 50 /// \brief The GPU profiles supported by the AMDGPU target. 51 enum GPUKind { 52 GK_NONE, 53 GK_R600, 54 GK_R600_DOUBLE_OPS, 55 GK_R700, 56 GK_R700_DOUBLE_OPS, 57 GK_EVERGREEN, 58 GK_EVERGREEN_DOUBLE_OPS, 59 GK_NORTHERN_ISLANDS, 60 GK_CAYMAN, 61 GK_GFX6, 62 GK_GFX7, 63 GK_GFX8, 64 GK_GFX9 65 }; 66 67 struct GPUInfo { 68 llvm::StringLiteral Name; 69 llvm::StringLiteral CanonicalName; 70 AMDGPUTargetInfo::GPUKind Kind; 71 }; 72 73 GPUInfo GPU; 74 75 static constexpr GPUInfo InvalidGPU = {{""}, {""}, GK_NONE}; 76 static constexpr GPUInfo R600Names[26] = { 77 {{"r600"}, {"r600"}, GK_R600}, 78 {{"rv630"}, {"r600"}, GK_R600}, 79 {{"rv635"}, {"r600"}, GK_R600}, 80 {{"r630"}, {"r630"}, GK_R600}, 81 {{"rs780"}, {"rs880"}, GK_R600}, 82 {{"rs880"}, {"rs880"}, GK_R600}, 83 {{"rv610"}, {"rs880"}, GK_R600}, 84 {{"rv620"}, {"rs880"}, GK_R600}, 85 {{"rv670"}, {"rv670"}, GK_R600_DOUBLE_OPS}, 86 {{"rv710"}, {"rv710"}, GK_R700}, 87 {{"rv730"}, {"rv730"}, GK_R700}, 88 {{"rv740"}, {"rv770"}, GK_R700_DOUBLE_OPS}, 89 {{"rv770"}, {"rv770"}, GK_R700_DOUBLE_OPS}, 90 {{"cedar"}, {"cedar"}, GK_EVERGREEN}, 91 {{"palm"}, {"cedar"}, GK_EVERGREEN}, 92 {{"cypress"}, {"cypress"}, GK_EVERGREEN_DOUBLE_OPS}, 93 {{"hemlock"}, {"cypress"}, GK_EVERGREEN_DOUBLE_OPS}, 94 {{"juniper"}, {"juniper"}, GK_EVERGREEN}, 95 {{"redwood"}, {"redwood"}, GK_EVERGREEN}, 96 {{"sumo"}, {"sumo"}, GK_EVERGREEN}, 97 {{"sumo2"}, {"sumo"}, GK_EVERGREEN}, 98 {{"barts"}, {"barts"}, GK_NORTHERN_ISLANDS}, 99 {{"caicos"}, {"caicos"}, GK_NORTHERN_ISLANDS}, 100 {{"turks"}, {"turks"}, GK_NORTHERN_ISLANDS}, 101 {{"aruba"}, {"cayman"}, GK_CAYMAN}, 102 {{"cayman"}, {"cayman"}, GK_CAYMAN}, 103 }; 104 static constexpr GPUInfo AMDGCNNames[30] = { 105 {{"gfx600"}, {"gfx600"}, GK_GFX6}, 106 {{"tahiti"}, {"gfx600"}, GK_GFX6}, 107 {{"gfx601"}, {"gfx601"}, GK_GFX6}, 108 {{"hainan"}, {"gfx601"}, GK_GFX6}, 109 {{"oland"}, {"gfx601"}, GK_GFX6}, 110 {{"pitcairn"}, {"gfx601"}, GK_GFX6}, 111 {{"verde"}, {"gfx601"}, GK_GFX6}, 112 {{"gfx700"}, {"gfx700"}, GK_GFX7}, 113 {{"kaveri"}, {"gfx700"}, GK_GFX7}, 114 {{"gfx701"}, {"gfx701"}, GK_GFX7}, 115 {{"hawaii"}, {"gfx701"}, GK_GFX7}, 116 {{"gfx702"}, {"gfx702"}, GK_GFX7}, 117 {{"gfx703"}, {"gfx703"}, GK_GFX7}, 118 {{"kabini"}, {"gfx703"}, GK_GFX7}, 119 {{"mullins"}, {"gfx703"}, GK_GFX7}, 120 {{"gfx704"}, {"gfx704"}, GK_GFX7}, 121 {{"bonaire"}, {"gfx704"}, GK_GFX7}, 122 {{"gfx801"}, {"gfx801"}, GK_GFX8}, 123 {{"carrizo"}, {"gfx801"}, GK_GFX8}, 124 {{"gfx802"}, {"gfx802"}, GK_GFX8}, 125 {{"iceland"}, {"gfx802"}, GK_GFX8}, 126 {{"tonga"}, {"gfx802"}, GK_GFX8}, 127 {{"gfx803"}, {"gfx803"}, GK_GFX8}, 128 {{"fiji"}, {"gfx803"}, GK_GFX8}, 129 {{"polaris10"}, {"gfx803"}, GK_GFX8}, 130 {{"polaris11"}, {"gfx803"}, GK_GFX8}, 131 {{"gfx810"}, {"gfx810"}, GK_GFX8}, 132 {{"stoney"}, {"gfx810"}, GK_GFX8}, 133 {{"gfx900"}, {"gfx900"}, GK_GFX9}, 134 {{"gfx902"}, {"gfx902"}, GK_GFX9}, 135 }; 136 137 bool hasFP64 : 1; 138 bool hasFMAF : 1; 139 bool hasLDEXPF : 1; 140 const AddrSpace AS; 141 142 static bool hasFullSpeedFMAF32(StringRef GPUName) { 143 return parseAMDGCNName(GPUName).Kind >= GK_GFX9; 144 } 145 146 static bool isAMDGCN(const llvm::Triple &TT) { 147 return TT.getArch() == llvm::Triple::amdgcn; 148 } 149 150 static bool isGenericZero(const llvm::Triple &TT) { return true; } 151 152 public: 153 AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); 154 155 void setAddressSpaceMap(bool DefaultIsPrivate); 156 157 void adjust(LangOptions &Opts) override; 158 159 uint64_t getPointerWidthV(unsigned AddrSpace) const override { 160 if (GPU.Kind <= GK_CAYMAN) 161 return 32; 162 163 if (AddrSpace == AS.Private || AddrSpace == AS.Local) { 164 return 32; 165 } 166 return 64; 167 } 168 169 uint64_t getPointerAlignV(unsigned AddrSpace) const override { 170 return getPointerWidthV(AddrSpace); 171 } 172 173 uint64_t getMaxPointerWidth() const override { 174 return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32; 175 } 176 177 const char *getClobbers() const override { return ""; } 178 179 ArrayRef<const char *> getGCCRegNames() const override; 180 181 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 182 return None; 183 } 184 185 /// Accepted register names: (n, m is unsigned integer, n < m) 186 /// v 187 /// s 188 /// {vn}, {v[n]} 189 /// {sn}, {s[n]} 190 /// {S} , where S is a special register name 191 ////{v[n:m]} 192 /// {s[n:m]} 193 bool validateAsmConstraint(const char *&Name, 194 TargetInfo::ConstraintInfo &Info) const override { 195 static const ::llvm::StringSet<> SpecialRegs({ 196 "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma", 197 "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo", 198 "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi", 199 }); 200 201 StringRef S(Name); 202 bool HasLeftParen = false; 203 if (S.front() == '{') { 204 HasLeftParen = true; 205 S = S.drop_front(); 206 } 207 if (S.empty()) 208 return false; 209 if (S.front() != 'v' && S.front() != 's') { 210 if (!HasLeftParen) 211 return false; 212 auto E = S.find('}'); 213 if (!SpecialRegs.count(S.substr(0, E))) 214 return false; 215 S = S.drop_front(E + 1); 216 if (!S.empty()) 217 return false; 218 // Found {S} where S is a special register. 219 Info.setAllowsRegister(); 220 Name = S.data() - 1; 221 return true; 222 } 223 S = S.drop_front(); 224 if (!HasLeftParen) { 225 if (!S.empty()) 226 return false; 227 // Found s or v. 228 Info.setAllowsRegister(); 229 Name = S.data() - 1; 230 return true; 231 } 232 bool HasLeftBracket = false; 233 if (!S.empty() && S.front() == '[') { 234 HasLeftBracket = true; 235 S = S.drop_front(); 236 } 237 unsigned long long N; 238 if (S.empty() || consumeUnsignedInteger(S, 10, N)) 239 return false; 240 if (!S.empty() && S.front() == ':') { 241 if (!HasLeftBracket) 242 return false; 243 S = S.drop_front(); 244 unsigned long long M; 245 if (consumeUnsignedInteger(S, 10, M) || N >= M) 246 return false; 247 } 248 if (HasLeftBracket) { 249 if (S.empty() || S.front() != ']') 250 return false; 251 S = S.drop_front(); 252 } 253 if (S.empty() || S.front() != '}') 254 return false; 255 S = S.drop_front(); 256 if (!S.empty()) 257 return false; 258 // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}. 259 Info.setAllowsRegister(); 260 Name = S.data() - 1; 261 return true; 262 } 263 264 bool 265 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 266 StringRef CPU, 267 const std::vector<std::string> &FeatureVec) const override; 268 269 void adjustTargetOptions(const CodeGenOptions &CGOpts, 270 TargetOptions &TargetOpts) const override; 271 272 ArrayRef<Builtin::Info> getTargetBuiltins() const override; 273 274 void getTargetDefines(const LangOptions &Opts, 275 MacroBuilder &Builder) const override; 276 277 BuiltinVaListKind getBuiltinVaListKind() const override { 278 return TargetInfo::CharPtrBuiltinVaList; 279 } 280 281 static GPUInfo parseR600Name(StringRef Name); 282 283 static GPUInfo parseAMDGCNName(StringRef Name); 284 285 bool isValidCPUName(StringRef Name) const override { 286 if (getTriple().getArch() == llvm::Triple::amdgcn) 287 return GK_NONE != parseAMDGCNName(Name).Kind; 288 else 289 return GK_NONE != parseR600Name(Name).Kind; 290 } 291 292 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 293 294 bool setCPU(const std::string &Name) override { 295 if (getTriple().getArch() == llvm::Triple::amdgcn) 296 GPU = parseAMDGCNName(Name); 297 else 298 GPU = parseR600Name(Name); 299 300 return GPU.Kind != GK_NONE; 301 } 302 303 void setSupportedOpenCLOpts() override { 304 auto &Opts = getSupportedOpenCLOpts(); 305 Opts.support("cl_clang_storage_class_specifiers"); 306 Opts.support("cl_khr_icd"); 307 308 if (hasFP64) 309 Opts.support("cl_khr_fp64"); 310 if (GPU.Kind >= GK_EVERGREEN) { 311 Opts.support("cl_khr_byte_addressable_store"); 312 Opts.support("cl_khr_global_int32_base_atomics"); 313 Opts.support("cl_khr_global_int32_extended_atomics"); 314 Opts.support("cl_khr_local_int32_base_atomics"); 315 Opts.support("cl_khr_local_int32_extended_atomics"); 316 } 317 if (GPU.Kind >= GK_GFX6) { 318 Opts.support("cl_khr_fp16"); 319 Opts.support("cl_khr_int64_base_atomics"); 320 Opts.support("cl_khr_int64_extended_atomics"); 321 Opts.support("cl_khr_mipmap_image"); 322 Opts.support("cl_khr_subgroups"); 323 Opts.support("cl_khr_3d_image_writes"); 324 Opts.support("cl_amd_media_ops"); 325 Opts.support("cl_amd_media_ops2"); 326 } 327 } 328 329 LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const override { 330 switch (TK) { 331 case OCLTK_Image: 332 return LangAS::opencl_constant; 333 334 case OCLTK_ClkEvent: 335 case OCLTK_Queue: 336 case OCLTK_ReserveID: 337 return LangAS::opencl_global; 338 339 default: 340 return TargetInfo::getOpenCLTypeAddrSpace(TK); 341 } 342 } 343 344 llvm::Optional<LangAS> getConstantAddressSpace() const override { 345 return getLangASFromTargetAS(AS.Constant); 346 } 347 348 /// \returns Target specific vtbl ptr address space. 349 unsigned getVtblPtrAddressSpace() const override { return AS.Constant; } 350 351 /// \returns If a target requires an address within a target specific address 352 /// space \p AddressSpace to be converted in order to be used, then return the 353 /// corresponding target specific DWARF address space. 354 /// 355 /// \returns Otherwise return None and no conversion will be emitted in the 356 /// DWARF. 357 Optional<unsigned> 358 getDWARFAddressSpace(unsigned AddressSpace) const override { 359 const unsigned DWARF_Private = 1; 360 const unsigned DWARF_Local = 2; 361 if (AddressSpace == AS.Private) { 362 return DWARF_Private; 363 } else if (AddressSpace == AS.Local) { 364 return DWARF_Local; 365 } else { 366 return None; 367 } 368 } 369 370 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 371 switch (CC) { 372 default: 373 return CCCR_Warning; 374 case CC_C: 375 case CC_OpenCLKernel: 376 return CCCR_OK; 377 } 378 } 379 380 // In amdgcn target the null pointer in global, constant, and generic 381 // address space has value 0 but in private and local address space has 382 // value ~0. 383 uint64_t getNullPointerValue(LangAS AS) const override { 384 return AS == LangAS::opencl_local ? ~0 : 0; 385 } 386 }; 387 388 } // namespace targets 389 } // namespace clang 390 391 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H 392