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/AST/Type.h" 18 #include "clang/Basic/TargetInfo.h" 19 #include "clang/Basic/TargetOptions.h" 20 #include "llvm/ADT/StringSet.h" 21 #include "llvm/ADT/Triple.h" 22 #include "llvm/Support/Compiler.h" 23 24 namespace clang { 25 namespace targets { 26 27 class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { 28 29 static const Builtin::Info BuiltinInfo[]; 30 static const char *const GCCRegNames[]; 31 32 struct LLVM_LIBRARY_VISIBILITY AddrSpace { 33 unsigned Generic, Global, Local, Constant, Private; 34 AddrSpace(bool IsGenericZero_ = false) { 35 if (IsGenericZero_) { 36 Generic = 0; 37 Global = 1; 38 Local = 3; 39 Constant = 2; 40 Private = 5; 41 } else { 42 Generic = 4; 43 Global = 1; 44 Local = 3; 45 Constant = 2; 46 Private = 0; 47 } 48 } 49 }; 50 51 /// \brief The GPU profiles supported by the AMDGPU target. 52 enum GPUKind { 53 GK_NONE, 54 GK_R600, 55 GK_R600_DOUBLE_OPS, 56 GK_R700, 57 GK_R700_DOUBLE_OPS, 58 GK_EVERGREEN, 59 GK_EVERGREEN_DOUBLE_OPS, 60 GK_NORTHERN_ISLANDS, 61 GK_CAYMAN, 62 GK_GFX6, 63 GK_GFX7, 64 GK_GFX8, 65 GK_GFX9 66 } GPU; 67 68 bool hasFP64 : 1; 69 bool hasFMAF : 1; 70 bool hasLDEXPF : 1; 71 const AddrSpace AS; 72 73 static bool hasFullSpeedFMAF32(StringRef GPUName) { 74 return parseAMDGCNName(GPUName) >= GK_GFX9; 75 } 76 77 static bool isAMDGCN(const llvm::Triple &TT) { 78 return TT.getArch() == llvm::Triple::amdgcn; 79 } 80 81 static bool isGenericZero(const llvm::Triple &TT) { 82 return TT.getEnvironmentName() == "amdgiz" || 83 TT.getEnvironmentName() == "amdgizcl"; 84 } 85 86 public: 87 AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); 88 89 void setAddressSpaceMap(bool DefaultIsPrivate); 90 91 void adjust(LangOptions &Opts) override; 92 93 uint64_t getPointerWidthV(unsigned AddrSpace) const override { 94 if (GPU <= GK_CAYMAN) 95 return 32; 96 97 if (AddrSpace == AS.Private || AddrSpace == AS.Local) { 98 return 32; 99 } 100 return 64; 101 } 102 103 uint64_t getPointerAlignV(unsigned AddrSpace) const override { 104 return getPointerWidthV(AddrSpace); 105 } 106 107 uint64_t getMaxPointerWidth() const override { 108 return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32; 109 } 110 111 const char *getClobbers() const override { return ""; } 112 113 ArrayRef<const char *> getGCCRegNames() const override; 114 115 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 116 return None; 117 } 118 119 /// Accepted register names: (n, m is unsigned integer, n < m) 120 /// v 121 /// s 122 /// {vn}, {v[n]} 123 /// {sn}, {s[n]} 124 /// {S} , where S is a special register name 125 ////{v[n:m]} 126 /// {s[n:m]} 127 bool validateAsmConstraint(const char *&Name, 128 TargetInfo::ConstraintInfo &Info) const override { 129 static const ::llvm::StringSet<> SpecialRegs({ 130 "exec", "vcc", "flat_scratch", "m0", "scc", "tba", "tma", 131 "flat_scratch_lo", "flat_scratch_hi", "vcc_lo", "vcc_hi", "exec_lo", 132 "exec_hi", "tma_lo", "tma_hi", "tba_lo", "tba_hi", 133 }); 134 135 StringRef S(Name); 136 bool HasLeftParen = false; 137 if (S.front() == '{') { 138 HasLeftParen = true; 139 S = S.drop_front(); 140 } 141 if (S.empty()) 142 return false; 143 if (S.front() != 'v' && S.front() != 's') { 144 if (!HasLeftParen) 145 return false; 146 auto E = S.find('}'); 147 if (!SpecialRegs.count(S.substr(0, E))) 148 return false; 149 S = S.drop_front(E + 1); 150 if (!S.empty()) 151 return false; 152 // Found {S} where S is a special register. 153 Info.setAllowsRegister(); 154 Name = S.data() - 1; 155 return true; 156 } 157 S = S.drop_front(); 158 if (!HasLeftParen) { 159 if (!S.empty()) 160 return false; 161 // Found s or v. 162 Info.setAllowsRegister(); 163 Name = S.data() - 1; 164 return true; 165 } 166 bool HasLeftBracket = false; 167 if (!S.empty() && S.front() == '[') { 168 HasLeftBracket = true; 169 S = S.drop_front(); 170 } 171 unsigned long long N; 172 if (S.empty() || consumeUnsignedInteger(S, 10, N)) 173 return false; 174 if (!S.empty() && S.front() == ':') { 175 if (!HasLeftBracket) 176 return false; 177 S = S.drop_front(); 178 unsigned long long M; 179 if (consumeUnsignedInteger(S, 10, M) || N >= M) 180 return false; 181 } 182 if (HasLeftBracket) { 183 if (S.empty() || S.front() != ']') 184 return false; 185 S = S.drop_front(); 186 } 187 if (S.empty() || S.front() != '}') 188 return false; 189 S = S.drop_front(); 190 if (!S.empty()) 191 return false; 192 // Found {vn}, {sn}, {v[n]}, {s[n]}, {v[n:m]}, or {s[n:m]}. 193 Info.setAllowsRegister(); 194 Name = S.data() - 1; 195 return true; 196 } 197 198 bool 199 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 200 StringRef CPU, 201 const std::vector<std::string> &FeatureVec) const override; 202 203 void adjustTargetOptions(const CodeGenOptions &CGOpts, 204 TargetOptions &TargetOpts) const override; 205 206 ArrayRef<Builtin::Info> getTargetBuiltins() const override; 207 208 void getTargetDefines(const LangOptions &Opts, 209 MacroBuilder &Builder) const override; 210 211 BuiltinVaListKind getBuiltinVaListKind() const override { 212 return TargetInfo::CharPtrBuiltinVaList; 213 } 214 215 static GPUKind parseR600Name(StringRef Name); 216 217 static GPUKind parseAMDGCNName(StringRef Name); 218 219 bool isValidCPUName(StringRef Name) const override { 220 if (getTriple().getArch() == llvm::Triple::amdgcn) 221 return GK_NONE != parseAMDGCNName(Name); 222 else 223 return GK_NONE != parseR600Name(Name); 224 } 225 226 bool setCPU(const std::string &Name) override { 227 if (getTriple().getArch() == llvm::Triple::amdgcn) 228 GPU = parseAMDGCNName(Name); 229 else 230 GPU = parseR600Name(Name); 231 232 return GPU != GK_NONE; 233 } 234 235 void setSupportedOpenCLOpts() override { 236 auto &Opts = getSupportedOpenCLOpts(); 237 Opts.support("cl_clang_storage_class_specifiers"); 238 Opts.support("cl_khr_icd"); 239 240 if (hasFP64) 241 Opts.support("cl_khr_fp64"); 242 if (GPU >= GK_EVERGREEN) { 243 Opts.support("cl_khr_byte_addressable_store"); 244 Opts.support("cl_khr_global_int32_base_atomics"); 245 Opts.support("cl_khr_global_int32_extended_atomics"); 246 Opts.support("cl_khr_local_int32_base_atomics"); 247 Opts.support("cl_khr_local_int32_extended_atomics"); 248 } 249 if (GPU >= GK_GFX6) { 250 Opts.support("cl_khr_fp16"); 251 Opts.support("cl_khr_int64_base_atomics"); 252 Opts.support("cl_khr_int64_extended_atomics"); 253 Opts.support("cl_khr_mipmap_image"); 254 Opts.support("cl_khr_subgroups"); 255 Opts.support("cl_khr_3d_image_writes"); 256 Opts.support("cl_amd_media_ops"); 257 Opts.support("cl_amd_media_ops2"); 258 } 259 } 260 261 LangAS getOpenCLTypeAddrSpace(const Type *T) const override { 262 auto BT = dyn_cast<BuiltinType>(T); 263 264 if (!BT) 265 return TargetInfo::getOpenCLTypeAddrSpace(T); 266 267 switch (BT->getKind()) { 268 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ 269 case BuiltinType::Id: \ 270 return LangAS::opencl_constant; 271 #include "clang/Basic/OpenCLImageTypes.def" 272 case BuiltinType::OCLClkEvent: 273 case BuiltinType::OCLQueue: 274 case BuiltinType::OCLReserveID: 275 return LangAS::opencl_global; 276 277 default: 278 return TargetInfo::getOpenCLTypeAddrSpace(T); 279 } 280 } 281 282 llvm::Optional<LangAS> getConstantAddressSpace() const override { 283 return getLangASFromTargetAS(AS.Constant); 284 } 285 286 /// \returns Target specific vtbl ptr address space. 287 unsigned getVtblPtrAddressSpace() const override { return AS.Constant; } 288 289 /// \returns If a target requires an address within a target specific address 290 /// space \p AddressSpace to be converted in order to be used, then return the 291 /// corresponding target specific DWARF address space. 292 /// 293 /// \returns Otherwise return None and no conversion will be emitted in the 294 /// DWARF. 295 Optional<unsigned> 296 getDWARFAddressSpace(unsigned AddressSpace) const override { 297 const unsigned DWARF_Private = 1; 298 const unsigned DWARF_Local = 2; 299 if (AddressSpace == AS.Private) { 300 return DWARF_Private; 301 } else if (AddressSpace == AS.Local) { 302 return DWARF_Local; 303 } else { 304 return None; 305 } 306 } 307 308 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 309 switch (CC) { 310 default: 311 return CCCR_Warning; 312 case CC_C: 313 case CC_OpenCLKernel: 314 return CCCR_OK; 315 } 316 } 317 318 // In amdgcn target the null pointer in global, constant, and generic 319 // address space has value 0 but in private and local address space has 320 // value ~0. 321 uint64_t getNullPointerValue(LangAS AS) const override { 322 return AS == LangAS::opencl_local ? ~0 : 0; 323 } 324 }; 325 326 } // namespace targets 327 } // namespace clang 328 329 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H 330