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/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 bool validateAsmConstraint(const char *&Name, 119 TargetInfo::ConstraintInfo &Info) const override { 120 switch (*Name) { 121 default: 122 break; 123 case 'v': // vgpr 124 case 's': // sgpr 125 Info.setAllowsRegister(); 126 return true; 127 } 128 return false; 129 } 130 131 bool 132 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 133 StringRef CPU, 134 const std::vector<std::string> &FeatureVec) const override; 135 136 void adjustTargetOptions(const CodeGenOptions &CGOpts, 137 TargetOptions &TargetOpts) const override; 138 139 ArrayRef<Builtin::Info> getTargetBuiltins() const override; 140 141 void getTargetDefines(const LangOptions &Opts, 142 MacroBuilder &Builder) const override; 143 144 BuiltinVaListKind getBuiltinVaListKind() const override { 145 return TargetInfo::CharPtrBuiltinVaList; 146 } 147 148 static GPUKind parseR600Name(StringRef Name); 149 150 static GPUKind parseAMDGCNName(StringRef Name); 151 152 bool isValidCPUName(StringRef Name) const override { 153 if (getTriple().getArch() == llvm::Triple::amdgcn) 154 return GK_NONE != parseAMDGCNName(Name); 155 else 156 return GK_NONE != parseR600Name(Name); 157 } 158 159 bool setCPU(const std::string &Name) override { 160 if (getTriple().getArch() == llvm::Triple::amdgcn) 161 GPU = parseAMDGCNName(Name); 162 else 163 GPU = parseR600Name(Name); 164 165 return GPU != GK_NONE; 166 } 167 168 void setSupportedOpenCLOpts() override { 169 auto &Opts = getSupportedOpenCLOpts(); 170 Opts.support("cl_clang_storage_class_specifiers"); 171 Opts.support("cl_khr_icd"); 172 173 if (hasFP64) 174 Opts.support("cl_khr_fp64"); 175 if (GPU >= GK_EVERGREEN) { 176 Opts.support("cl_khr_byte_addressable_store"); 177 Opts.support("cl_khr_global_int32_base_atomics"); 178 Opts.support("cl_khr_global_int32_extended_atomics"); 179 Opts.support("cl_khr_local_int32_base_atomics"); 180 Opts.support("cl_khr_local_int32_extended_atomics"); 181 } 182 if (GPU >= GK_GFX6) { 183 Opts.support("cl_khr_fp16"); 184 Opts.support("cl_khr_int64_base_atomics"); 185 Opts.support("cl_khr_int64_extended_atomics"); 186 Opts.support("cl_khr_mipmap_image"); 187 Opts.support("cl_khr_subgroups"); 188 Opts.support("cl_khr_3d_image_writes"); 189 Opts.support("cl_amd_media_ops"); 190 Opts.support("cl_amd_media_ops2"); 191 } 192 } 193 194 LangAS::ID getOpenCLTypeAddrSpace(const Type *T) const override { 195 auto BT = dyn_cast<BuiltinType>(T); 196 197 if (!BT) 198 return TargetInfo::getOpenCLTypeAddrSpace(T); 199 200 switch (BT->getKind()) { 201 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ 202 case BuiltinType::Id: \ 203 return LangAS::opencl_constant; 204 #include "clang/Basic/OpenCLImageTypes.def" 205 206 default: 207 return TargetInfo::getOpenCLTypeAddrSpace(T); 208 } 209 } 210 211 llvm::Optional<unsigned> getConstantAddressSpace() const override { 212 return LangAS::FirstTargetAddressSpace + AS.Constant; 213 } 214 215 /// \returns Target specific vtbl ptr address space. 216 unsigned getVtblPtrAddressSpace() const override { return AS.Constant; } 217 218 /// \returns If a target requires an address within a target specific address 219 /// space \p AddressSpace to be converted in order to be used, then return the 220 /// corresponding target specific DWARF address space. 221 /// 222 /// \returns Otherwise return None and no conversion will be emitted in the 223 /// DWARF. 224 Optional<unsigned> 225 getDWARFAddressSpace(unsigned AddressSpace) const override { 226 const unsigned DWARF_Private = 1; 227 const unsigned DWARF_Local = 2; 228 if (AddressSpace == AS.Private) { 229 return DWARF_Private; 230 } else if (AddressSpace == AS.Local) { 231 return DWARF_Local; 232 } else { 233 return None; 234 } 235 } 236 237 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 238 switch (CC) { 239 default: 240 return CCCR_Warning; 241 case CC_C: 242 case CC_OpenCLKernel: 243 return CCCR_OK; 244 } 245 } 246 247 // In amdgcn target the null pointer in global, constant, and generic 248 // address space has value 0 but in private and local address space has 249 // value ~0. 250 uint64_t getNullPointerValue(unsigned AS) const override { 251 return AS == LangAS::opencl_local ? ~0 : 0; 252 } 253 }; 254 255 } // namespace targets 256 } // namespace clang 257 258 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H 259