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