1 //===--- AMDGPU.cpp - Implement AMDGPU target feature support -------------===// 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 implements AMDGPU TargetInfo objects. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AMDGPU.h" 15 #include "clang/Basic/Builtins.h" 16 #include "clang/Basic/LangOptions.h" 17 #include "clang/Basic/MacroBuilder.h" 18 #include "clang/Basic/TargetBuiltins.h" 19 #include "clang/Frontend/CodeGenOptions.h" 20 #include "llvm/ADT/StringSwitch.h" 21 22 using namespace clang; 23 using namespace clang::targets; 24 25 namespace clang { 26 namespace targets { 27 28 // If you edit the description strings, make sure you update 29 // getPointerWidthV(). 30 31 static const char *const DataLayoutStringR600 = 32 "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128" 33 "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"; 34 35 static const char *const DataLayoutStringAMDGCN = 36 "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32" 37 "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128" 38 "-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"; 39 40 const LangASMap AMDGPUTargetInfo::AMDGPUDefIsGenMap = { 41 Generic, // Default 42 Global, // opencl_global 43 Local, // opencl_local 44 Constant, // opencl_constant 45 Private, // opencl_private 46 Generic, // opencl_generic 47 Global, // cuda_device 48 Constant, // cuda_constant 49 Local // cuda_shared 50 }; 51 52 const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = { 53 Private, // Default 54 Global, // opencl_global 55 Local, // opencl_local 56 Constant, // opencl_constant 57 Private, // opencl_private 58 Generic, // opencl_generic 59 Global, // cuda_device 60 Constant, // cuda_constant 61 Local // cuda_shared 62 }; 63 } // namespace targets 64 } // namespace clang 65 66 const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = { 67 #define BUILTIN(ID, TYPE, ATTRS) \ 68 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 69 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 70 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, 71 #include "clang/Basic/BuiltinsAMDGPU.def" 72 }; 73 74 const char *const AMDGPUTargetInfo::GCCRegNames[] = { 75 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", 76 "v9", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", 77 "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26", 78 "v27", "v28", "v29", "v30", "v31", "v32", "v33", "v34", "v35", 79 "v36", "v37", "v38", "v39", "v40", "v41", "v42", "v43", "v44", 80 "v45", "v46", "v47", "v48", "v49", "v50", "v51", "v52", "v53", 81 "v54", "v55", "v56", "v57", "v58", "v59", "v60", "v61", "v62", 82 "v63", "v64", "v65", "v66", "v67", "v68", "v69", "v70", "v71", 83 "v72", "v73", "v74", "v75", "v76", "v77", "v78", "v79", "v80", 84 "v81", "v82", "v83", "v84", "v85", "v86", "v87", "v88", "v89", 85 "v90", "v91", "v92", "v93", "v94", "v95", "v96", "v97", "v98", 86 "v99", "v100", "v101", "v102", "v103", "v104", "v105", "v106", "v107", 87 "v108", "v109", "v110", "v111", "v112", "v113", "v114", "v115", "v116", 88 "v117", "v118", "v119", "v120", "v121", "v122", "v123", "v124", "v125", 89 "v126", "v127", "v128", "v129", "v130", "v131", "v132", "v133", "v134", 90 "v135", "v136", "v137", "v138", "v139", "v140", "v141", "v142", "v143", 91 "v144", "v145", "v146", "v147", "v148", "v149", "v150", "v151", "v152", 92 "v153", "v154", "v155", "v156", "v157", "v158", "v159", "v160", "v161", 93 "v162", "v163", "v164", "v165", "v166", "v167", "v168", "v169", "v170", 94 "v171", "v172", "v173", "v174", "v175", "v176", "v177", "v178", "v179", 95 "v180", "v181", "v182", "v183", "v184", "v185", "v186", "v187", "v188", 96 "v189", "v190", "v191", "v192", "v193", "v194", "v195", "v196", "v197", 97 "v198", "v199", "v200", "v201", "v202", "v203", "v204", "v205", "v206", 98 "v207", "v208", "v209", "v210", "v211", "v212", "v213", "v214", "v215", 99 "v216", "v217", "v218", "v219", "v220", "v221", "v222", "v223", "v224", 100 "v225", "v226", "v227", "v228", "v229", "v230", "v231", "v232", "v233", 101 "v234", "v235", "v236", "v237", "v238", "v239", "v240", "v241", "v242", 102 "v243", "v244", "v245", "v246", "v247", "v248", "v249", "v250", "v251", 103 "v252", "v253", "v254", "v255", "s0", "s1", "s2", "s3", "s4", 104 "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s13", 105 "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", 106 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", 107 "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39", "s40", 108 "s41", "s42", "s43", "s44", "s45", "s46", "s47", "s48", "s49", 109 "s50", "s51", "s52", "s53", "s54", "s55", "s56", "s57", "s58", 110 "s59", "s60", "s61", "s62", "s63", "s64", "s65", "s66", "s67", 111 "s68", "s69", "s70", "s71", "s72", "s73", "s74", "s75", "s76", 112 "s77", "s78", "s79", "s80", "s81", "s82", "s83", "s84", "s85", 113 "s86", "s87", "s88", "s89", "s90", "s91", "s92", "s93", "s94", 114 "s95", "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103", 115 "s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111", "s112", 116 "s113", "s114", "s115", "s116", "s117", "s118", "s119", "s120", "s121", 117 "s122", "s123", "s124", "s125", "s126", "s127", "exec", "vcc", "scc", 118 "m0", "flat_scratch", "exec_lo", "exec_hi", "vcc_lo", "vcc_hi", 119 "flat_scratch_lo", "flat_scratch_hi" 120 }; 121 122 ArrayRef<const char *> AMDGPUTargetInfo::getGCCRegNames() const { 123 return llvm::makeArrayRef(GCCRegNames); 124 } 125 126 bool AMDGPUTargetInfo::initFeatureMap( 127 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 128 const std::vector<std::string> &FeatureVec) const { 129 130 // XXX - What does the member GPU mean if device name string passed here? 131 if (isAMDGCN(getTriple())) { 132 if (CPU.empty()) 133 CPU = "gfx600"; 134 135 switch (parseAMDGCNName(CPU).Kind) { 136 case GK_GFX906: 137 Features["dl-insts"] = true; 138 LLVM_FALLTHROUGH; 139 case GK_GFX904: 140 case GK_GFX902: 141 case GK_GFX900: 142 Features["gfx9-insts"] = true; 143 LLVM_FALLTHROUGH; 144 case GK_GFX810: 145 case GK_GFX803: 146 case GK_GFX802: 147 case GK_GFX801: 148 Features["vi-insts"] = true; 149 Features["16-bit-insts"] = true; 150 Features["dpp"] = true; 151 Features["s-memrealtime"] = true; 152 LLVM_FALLTHROUGH; 153 case GK_GFX704: 154 case GK_GFX703: 155 case GK_GFX702: 156 case GK_GFX701: 157 case GK_GFX700: 158 Features["ci-insts"] = true; 159 LLVM_FALLTHROUGH; 160 case GK_GFX601: 161 case GK_GFX600: 162 break; 163 case GK_NONE: 164 return false; 165 default: 166 llvm_unreachable("Unhandled GPU!"); 167 } 168 } else { 169 if (CPU.empty()) 170 CPU = "r600"; 171 172 switch (parseR600Name(CPU).Kind) { 173 case GK_CAYMAN: 174 case GK_CYPRESS: 175 case GK_RV770: 176 case GK_RV670: 177 // TODO: Add fp64 when implemented. 178 break; 179 case GK_TURKS: 180 case GK_CAICOS: 181 case GK_BARTS: 182 case GK_SUMO: 183 case GK_REDWOOD: 184 case GK_JUNIPER: 185 case GK_CEDAR: 186 case GK_RV730: 187 case GK_RV710: 188 case GK_RS880: 189 case GK_R630: 190 case GK_R600: 191 break; 192 default: 193 llvm_unreachable("Unhandled GPU!"); 194 } 195 } 196 197 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec); 198 } 199 200 void AMDGPUTargetInfo::adjustTargetOptions(const CodeGenOptions &CGOpts, 201 TargetOptions &TargetOpts) const { 202 bool hasFP32Denormals = false; 203 bool hasFP64Denormals = false; 204 GPUInfo CGOptsGPU = parseGPUName(TargetOpts.CPU); 205 for (auto &I : TargetOpts.FeaturesAsWritten) { 206 if (I == "+fp32-denormals" || I == "-fp32-denormals") 207 hasFP32Denormals = true; 208 if (I == "+fp64-fp16-denormals" || I == "-fp64-fp16-denormals") 209 hasFP64Denormals = true; 210 } 211 if (!hasFP32Denormals) 212 TargetOpts.Features.push_back( 213 (Twine(CGOptsGPU.HasFastFMAF && CGOptsGPU.HasFullRateF32Denorms && 214 !CGOpts.FlushDenorm 215 ? '+' 216 : '-') + 217 Twine("fp32-denormals")) 218 .str()); 219 // Always do not flush fp64 or fp16 denorms. 220 if (!hasFP64Denormals && CGOptsGPU.HasFP64) 221 TargetOpts.Features.push_back("+fp64-fp16-denormals"); 222 } 223 224 constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::InvalidGPU; 225 constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::R600GPUs[]; 226 constexpr AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::AMDGCNGPUs[]; 227 228 AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseR600Name(StringRef Name) { 229 const auto *Result = llvm::find_if( 230 R600GPUs, [Name](const GPUInfo &GPU) { return GPU.Name == Name; }); 231 232 if (Result == std::end(R600GPUs)) 233 return InvalidGPU; 234 return *Result; 235 } 236 237 AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseAMDGCNName(StringRef Name) { 238 const auto *Result = llvm::find_if( 239 AMDGCNGPUs, [Name](const GPUInfo &GPU) { return GPU.Name == Name; }); 240 241 if (Result == std::end(AMDGCNGPUs)) 242 return InvalidGPU; 243 return *Result; 244 } 245 246 AMDGPUTargetInfo::GPUInfo AMDGPUTargetInfo::parseGPUName(StringRef Name) const { 247 if (isAMDGCN(getTriple())) 248 return parseAMDGCNName(Name); 249 else 250 return parseR600Name(Name); 251 } 252 253 void AMDGPUTargetInfo::fillValidCPUList( 254 SmallVectorImpl<StringRef> &Values) const { 255 if (isAMDGCN(getTriple())) 256 llvm::for_each(AMDGCNGPUs, [&Values](const GPUInfo &GPU) { 257 Values.emplace_back(GPU.Name);}); 258 else 259 llvm::for_each(R600GPUs, [&Values](const GPUInfo &GPU) { 260 Values.emplace_back(GPU.Name);}); 261 } 262 263 void AMDGPUTargetInfo::setAddressSpaceMap(bool DefaultIsPrivate) { 264 AddrSpaceMap = DefaultIsPrivate ? &AMDGPUDefIsPrivMap : &AMDGPUDefIsGenMap; 265 } 266 267 AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple, 268 const TargetOptions &Opts) 269 : TargetInfo(Triple), 270 GPU(isAMDGCN(Triple) ? AMDGCNGPUs[0] : parseR600Name(Opts.CPU)) { 271 resetDataLayout(isAMDGCN(getTriple()) ? DataLayoutStringAMDGCN 272 : DataLayoutStringR600); 273 assert(DataLayout->getAllocaAddrSpace() == Private); 274 275 setAddressSpaceMap(Triple.getOS() == llvm::Triple::Mesa3D || 276 !isAMDGCN(Triple)); 277 UseAddrSpaceMapMangling = true; 278 279 // Set pointer width and alignment for target address space 0. 280 PointerWidth = PointerAlign = DataLayout->getPointerSizeInBits(); 281 if (getMaxPointerWidth() == 64) { 282 LongWidth = LongAlign = 64; 283 SizeType = UnsignedLong; 284 PtrDiffType = SignedLong; 285 IntPtrType = SignedLong; 286 } 287 288 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 289 } 290 291 void AMDGPUTargetInfo::adjust(LangOptions &Opts) { 292 TargetInfo::adjust(Opts); 293 // ToDo: There are still a few places using default address space as private 294 // address space in OpenCL, which needs to be cleaned up, then Opts.OpenCL 295 // can be removed from the following line. 296 setAddressSpaceMap(/*DefaultIsPrivate=*/Opts.OpenCL || 297 !isAMDGCN(getTriple())); 298 } 299 300 ArrayRef<Builtin::Info> AMDGPUTargetInfo::getTargetBuiltins() const { 301 return llvm::makeArrayRef(BuiltinInfo, clang::AMDGPU::LastTSBuiltin - 302 Builtin::FirstTSBuiltin); 303 } 304 305 void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts, 306 MacroBuilder &Builder) const { 307 Builder.defineMacro("__AMD__"); 308 Builder.defineMacro("__AMDGPU__"); 309 310 if (isAMDGCN(getTriple())) 311 Builder.defineMacro("__AMDGCN__"); 312 else 313 Builder.defineMacro("__R600__"); 314 315 if (GPU.Kind != GK_NONE) 316 Builder.defineMacro(Twine("__") + Twine(GPU.CanonicalName) + Twine("__")); 317 318 // TODO: __HAS_FMAF__, __HAS_LDEXPF__, __HAS_FP64__ are deprecated and will be 319 // removed in the near future. 320 if (GPU.HasFMAF) 321 Builder.defineMacro("__HAS_FMAF__"); 322 if (GPU.HasFastFMAF) 323 Builder.defineMacro("FP_FAST_FMAF"); 324 if (GPU.HasLDEXPF) 325 Builder.defineMacro("__HAS_LDEXPF__"); 326 if (GPU.HasFP64) 327 Builder.defineMacro("__HAS_FP64__"); 328 if (GPU.HasFastFMA) 329 Builder.defineMacro("FP_FAST_FMA"); 330 } 331