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/Triple.h" 20 #include "llvm/Support/Compiler.h" 21 22 namespace clang { 23 namespace targets { 24 25 class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo { 26 27 static const Builtin::Info BuiltinInfo[]; 28 static const char *const GCCRegNames[]; 29 30 struct LLVM_LIBRARY_VISIBILITY AddrSpace { 31 unsigned Generic, Global, Local, Constant, Private; 32 AddrSpace(bool IsGenericZero_ = false) { 33 if (IsGenericZero_) { 34 Generic = 0; 35 Global = 1; 36 Local = 3; 37 Constant = 2; 38 Private = 5; 39 } else { 40 Generic = 4; 41 Global = 1; 42 Local = 3; 43 Constant = 2; 44 Private = 0; 45 } 46 } 47 }; 48 49 /// \brief The GPU profiles supported by the AMDGPU target. 50 enum GPUKind { 51 GK_NONE, 52 GK_R600, 53 GK_R600_DOUBLE_OPS, 54 GK_R700, 55 GK_R700_DOUBLE_OPS, 56 GK_EVERGREEN, 57 GK_EVERGREEN_DOUBLE_OPS, 58 GK_NORTHERN_ISLANDS, 59 GK_CAYMAN, 60 GK_GFX6, 61 GK_GFX7, 62 GK_GFX8, 63 GK_GFX9 64 } GPU; 65 66 bool hasFP64 : 1; 67 bool hasFMAF : 1; 68 bool hasLDEXPF : 1; 69 const AddrSpace AS; 70 71 static bool hasFullSpeedFMAF32(StringRef GPUName) { 72 return parseAMDGCNName(GPUName) >= GK_GFX9; 73 } 74 75 static bool isAMDGCN(const llvm::Triple &TT) { 76 return TT.getArch() == llvm::Triple::amdgcn; 77 } 78 79 static bool isGenericZero(const llvm::Triple &TT) { 80 return TT.getEnvironmentName() == "amdgiz" || 81 TT.getEnvironmentName() == "amdgizcl"; 82 } 83 84 public: 85 AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts); 86 87 void setAddressSpaceMap(bool DefaultIsPrivate); 88 89 void adjust(LangOptions &Opts) override; 90 91 uint64_t getPointerWidthV(unsigned AddrSpace) const override { 92 if (GPU <= GK_CAYMAN) 93 return 32; 94 95 if (AddrSpace == AS.Private || AddrSpace == AS.Local) { 96 return 32; 97 } 98 return 64; 99 } 100 101 uint64_t getPointerAlignV(unsigned AddrSpace) const override { 102 return getPointerWidthV(AddrSpace); 103 } 104 105 uint64_t getMaxPointerWidth() const override { 106 return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32; 107 } 108 109 const char *getClobbers() const override { return ""; } 110 111 ArrayRef<const char *> getGCCRegNames() const override; 112 113 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 114 return None; 115 } 116 117 bool validateAsmConstraint(const char *&Name, 118 TargetInfo::ConstraintInfo &Info) const override { 119 switch (*Name) { 120 default: 121 break; 122 case 'v': // vgpr 123 case 's': // sgpr 124 Info.setAllowsRegister(); 125 return true; 126 } 127 return false; 128 } 129 130 bool 131 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 132 StringRef CPU, 133 const std::vector<std::string> &FeatureVec) const override; 134 135 void adjustTargetOptions(const CodeGenOptions &CGOpts, 136 TargetOptions &TargetOpts) const override; 137 138 ArrayRef<Builtin::Info> getTargetBuiltins() const override; 139 140 void getTargetDefines(const LangOptions &Opts, 141 MacroBuilder &Builder) const override; 142 143 BuiltinVaListKind getBuiltinVaListKind() const override { 144 return TargetInfo::CharPtrBuiltinVaList; 145 } 146 147 static GPUKind parseR600Name(StringRef Name); 148 149 static GPUKind parseAMDGCNName(StringRef Name); 150 151 bool isValidCPUName(StringRef Name) const override { 152 if (getTriple().getArch() == llvm::Triple::amdgcn) 153 return GK_NONE != parseAMDGCNName(Name); 154 else 155 return GK_NONE != parseR600Name(Name); 156 } 157 158 bool setCPU(const std::string &Name) override { 159 if (getTriple().getArch() == llvm::Triple::amdgcn) 160 GPU = parseAMDGCNName(Name); 161 else 162 GPU = parseR600Name(Name); 163 164 return GPU != GK_NONE; 165 } 166 167 void setSupportedOpenCLOpts() override { 168 auto &Opts = getSupportedOpenCLOpts(); 169 Opts.support("cl_clang_storage_class_specifiers"); 170 Opts.support("cl_khr_icd"); 171 172 if (hasFP64) 173 Opts.support("cl_khr_fp64"); 174 if (GPU >= GK_EVERGREEN) { 175 Opts.support("cl_khr_byte_addressable_store"); 176 Opts.support("cl_khr_global_int32_base_atomics"); 177 Opts.support("cl_khr_global_int32_extended_atomics"); 178 Opts.support("cl_khr_local_int32_base_atomics"); 179 Opts.support("cl_khr_local_int32_extended_atomics"); 180 } 181 if (GPU >= GK_GFX6) { 182 Opts.support("cl_khr_fp16"); 183 Opts.support("cl_khr_int64_base_atomics"); 184 Opts.support("cl_khr_int64_extended_atomics"); 185 Opts.support("cl_khr_mipmap_image"); 186 Opts.support("cl_khr_subgroups"); 187 Opts.support("cl_khr_3d_image_writes"); 188 Opts.support("cl_amd_media_ops"); 189 Opts.support("cl_amd_media_ops2"); 190 } 191 } 192 193 LangAS::ID getOpenCLImageAddrSpace() const override { 194 return LangAS::opencl_constant; 195 } 196 197 llvm::Optional<unsigned> getConstantAddressSpace() const override { 198 return LangAS::FirstTargetAddressSpace + AS.Constant; 199 } 200 201 /// \returns Target specific vtbl ptr address space. 202 unsigned getVtblPtrAddressSpace() const override { return AS.Constant; } 203 204 /// \returns If a target requires an address within a target specific address 205 /// space \p AddressSpace to be converted in order to be used, then return the 206 /// corresponding target specific DWARF address space. 207 /// 208 /// \returns Otherwise return None and no conversion will be emitted in the 209 /// DWARF. 210 Optional<unsigned> 211 getDWARFAddressSpace(unsigned AddressSpace) const override { 212 const unsigned DWARF_Private = 1; 213 const unsigned DWARF_Local = 2; 214 if (AddressSpace == AS.Private) { 215 return DWARF_Private; 216 } else if (AddressSpace == AS.Local) { 217 return DWARF_Local; 218 } else { 219 return None; 220 } 221 } 222 223 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 224 switch (CC) { 225 default: 226 return CCCR_Warning; 227 case CC_C: 228 case CC_OpenCLKernel: 229 return CCCR_OK; 230 } 231 } 232 233 // In amdgcn target the null pointer in global, constant, and generic 234 // address space has value 0 but in private and local address space has 235 // value ~0. 236 uint64_t getNullPointerValue(unsigned AS) const override { 237 return AS == LangAS::opencl_local ? ~0 : 0; 238 } 239 }; 240 241 } // namespace targets 242 } // namespace clang 243 244 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_AMDGPU_H 245