1//===--- AMDGPU.cpp - Implement AMDGPU target feature support -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements AMDGPU TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AMDGPU.h"
14#include "clang/Basic/Builtins.h"
15#include "clang/Basic/Diagnostic.h"
16#include "clang/Basic/LangOptions.h"
17#include "clang/Basic/MacroBuilder.h"
18#include "clang/Basic/TargetBuiltins.h"
19#include "clang/Basic/TargetID.h"
20#include "llvm/ADT/SmallString.h"
21#include "llvm/TargetParser/AMDGPUTargetParser.h"
22using namespace clang;
23using namespace clang::targets;
24
25namespace clang {
26namespace targets {
27
28// If you edit the description strings, make sure you update
29// getPointerWidthV().
30
31const LangASMap AMDGPUTargetInfo::AMDGPUAddrSpaceMap = {
32 {LangAS::Default, llvm::AMDGPUAS::FLAT_ADDRESS},
33 {LangAS::opencl_global, llvm::AMDGPUAS::GLOBAL_ADDRESS},
34 {LangAS::opencl_local, llvm::AMDGPUAS::LOCAL_ADDRESS},
35 {LangAS::opencl_constant, llvm::AMDGPUAS::CONSTANT_ADDRESS},
36 {LangAS::opencl_private, llvm::AMDGPUAS::PRIVATE_ADDRESS},
37 {LangAS::opencl_generic, llvm::AMDGPUAS::FLAT_ADDRESS},
38 {LangAS::opencl_global_device, llvm::AMDGPUAS::GLOBAL_ADDRESS},
39 {LangAS::opencl_global_host, llvm::AMDGPUAS::GLOBAL_ADDRESS},
40 {LangAS::cuda_device, llvm::AMDGPUAS::GLOBAL_ADDRESS},
41 {LangAS::cuda_constant, llvm::AMDGPUAS::CONSTANT_ADDRESS},
42 {LangAS::cuda_shared, llvm::AMDGPUAS::LOCAL_ADDRESS},
43 {LangAS::sycl_global, llvm::AMDGPUAS::GLOBAL_ADDRESS},
44 {LangAS::sycl_global_device, llvm::AMDGPUAS::GLOBAL_ADDRESS},
45 {LangAS::sycl_global_host, llvm::AMDGPUAS::GLOBAL_ADDRESS},
46 {LangAS::sycl_local, llvm::AMDGPUAS::LOCAL_ADDRESS},
47 {LangAS::sycl_private, llvm::AMDGPUAS::PRIVATE_ADDRESS},
48 {LangAS::sycl_generic, llvm::AMDGPUAS::FLAT_ADDRESS},
49 {LangAS::sycl_constant, llvm::AMDGPUAS::CONSTANT_ADDRESS},
50 {LangAS::ptr32_sptr, llvm::AMDGPUAS::FLAT_ADDRESS},
51 {LangAS::ptr32_uptr, llvm::AMDGPUAS::FLAT_ADDRESS},
52 {LangAS::ptr64, llvm::AMDGPUAS::FLAT_ADDRESS},
53 {LangAS::hlsl_groupshared, llvm::AMDGPUAS::FLAT_ADDRESS},
54 {LangAS::hlsl_constant, llvm::AMDGPUAS::CONSTANT_ADDRESS},
55 // FIXME(pr/122103): hlsl_private -> PRIVATE is wrong, but at least this
56 // will break loudly.
57 {LangAS::hlsl_private, llvm::AMDGPUAS::PRIVATE_ADDRESS},
58 {LangAS::hlsl_device, llvm::AMDGPUAS::GLOBAL_ADDRESS},
59 {LangAS::hlsl_input, llvm::AMDGPUAS::PRIVATE_ADDRESS},
60 {LangAS::hlsl_output, llvm::AMDGPUAS::PRIVATE_ADDRESS},
61 {LangAS::hlsl_push_constant, llvm::AMDGPUAS::GLOBAL_ADDRESS},
62 {LangAS::amdgpu_barrier, llvm::AMDGPUAS::BARRIER},
63};
64
65} // namespace targets
66} // namespace clang
67
68static constexpr int NumBuiltins =
69 clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin;
70
71#define GET_BUILTIN_STR_TABLE
72#include "clang/Basic/BuiltinsAMDGPU.inc"
73#undef GET_BUILTIN_STR_TABLE
74
75static constexpr Builtin::Info BuiltinInfos[] = {
76#define GET_BUILTIN_INFOS
77#include "clang/Basic/BuiltinsAMDGPU.inc"
78#undef GET_BUILTIN_INFOS
79};
80static_assert(std::size(BuiltinInfos) == NumBuiltins);
81
82const char *const AMDGPUTargetInfo::GCCRegNames[] = {
83 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
84 "v9", "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17",
85 "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26",
86 "v27", "v28", "v29", "v30", "v31", "v32", "v33", "v34", "v35",
87 "v36", "v37", "v38", "v39", "v40", "v41", "v42", "v43", "v44",
88 "v45", "v46", "v47", "v48", "v49", "v50", "v51", "v52", "v53",
89 "v54", "v55", "v56", "v57", "v58", "v59", "v60", "v61", "v62",
90 "v63", "v64", "v65", "v66", "v67", "v68", "v69", "v70", "v71",
91 "v72", "v73", "v74", "v75", "v76", "v77", "v78", "v79", "v80",
92 "v81", "v82", "v83", "v84", "v85", "v86", "v87", "v88", "v89",
93 "v90", "v91", "v92", "v93", "v94", "v95", "v96", "v97", "v98",
94 "v99", "v100", "v101", "v102", "v103", "v104", "v105", "v106", "v107",
95 "v108", "v109", "v110", "v111", "v112", "v113", "v114", "v115", "v116",
96 "v117", "v118", "v119", "v120", "v121", "v122", "v123", "v124", "v125",
97 "v126", "v127", "v128", "v129", "v130", "v131", "v132", "v133", "v134",
98 "v135", "v136", "v137", "v138", "v139", "v140", "v141", "v142", "v143",
99 "v144", "v145", "v146", "v147", "v148", "v149", "v150", "v151", "v152",
100 "v153", "v154", "v155", "v156", "v157", "v158", "v159", "v160", "v161",
101 "v162", "v163", "v164", "v165", "v166", "v167", "v168", "v169", "v170",
102 "v171", "v172", "v173", "v174", "v175", "v176", "v177", "v178", "v179",
103 "v180", "v181", "v182", "v183", "v184", "v185", "v186", "v187", "v188",
104 "v189", "v190", "v191", "v192", "v193", "v194", "v195", "v196", "v197",
105 "v198", "v199", "v200", "v201", "v202", "v203", "v204", "v205", "v206",
106 "v207", "v208", "v209", "v210", "v211", "v212", "v213", "v214", "v215",
107 "v216", "v217", "v218", "v219", "v220", "v221", "v222", "v223", "v224",
108 "v225", "v226", "v227", "v228", "v229", "v230", "v231", "v232", "v233",
109 "v234", "v235", "v236", "v237", "v238", "v239", "v240", "v241", "v242",
110 "v243", "v244", "v245", "v246", "v247", "v248", "v249", "v250", "v251",
111 "v252", "v253", "v254", "v255", "s0", "s1", "s2", "s3", "s4",
112 "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s13",
113 "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
114 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
115 "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39", "s40",
116 "s41", "s42", "s43", "s44", "s45", "s46", "s47", "s48", "s49",
117 "s50", "s51", "s52", "s53", "s54", "s55", "s56", "s57", "s58",
118 "s59", "s60", "s61", "s62", "s63", "s64", "s65", "s66", "s67",
119 "s68", "s69", "s70", "s71", "s72", "s73", "s74", "s75", "s76",
120 "s77", "s78", "s79", "s80", "s81", "s82", "s83", "s84", "s85",
121 "s86", "s87", "s88", "s89", "s90", "s91", "s92", "s93", "s94",
122 "s95", "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103",
123 "s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111", "s112",
124 "s113", "s114", "s115", "s116", "s117", "s118", "s119", "s120", "s121",
125 "s122", "s123", "s124", "s125", "s126", "s127", "exec", "vcc", "scc",
126 "m0", "flat_scratch", "exec_lo", "exec_hi", "vcc_lo", "vcc_hi",
127 "flat_scratch_lo", "flat_scratch_hi",
128 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8",
129 "a9", "a10", "a11", "a12", "a13", "a14", "a15", "a16", "a17",
130 "a18", "a19", "a20", "a21", "a22", "a23", "a24", "a25", "a26",
131 "a27", "a28", "a29", "a30", "a31", "a32", "a33", "a34", "a35",
132 "a36", "a37", "a38", "a39", "a40", "a41", "a42", "a43", "a44",
133 "a45", "a46", "a47", "a48", "a49", "a50", "a51", "a52", "a53",
134 "a54", "a55", "a56", "a57", "a58", "a59", "a60", "a61", "a62",
135 "a63", "a64", "a65", "a66", "a67", "a68", "a69", "a70", "a71",
136 "a72", "a73", "a74", "a75", "a76", "a77", "a78", "a79", "a80",
137 "a81", "a82", "a83", "a84", "a85", "a86", "a87", "a88", "a89",
138 "a90", "a91", "a92", "a93", "a94", "a95", "a96", "a97", "a98",
139 "a99", "a100", "a101", "a102", "a103", "a104", "a105", "a106", "a107",
140 "a108", "a109", "a110", "a111", "a112", "a113", "a114", "a115", "a116",
141 "a117", "a118", "a119", "a120", "a121", "a122", "a123", "a124", "a125",
142 "a126", "a127", "a128", "a129", "a130", "a131", "a132", "a133", "a134",
143 "a135", "a136", "a137", "a138", "a139", "a140", "a141", "a142", "a143",
144 "a144", "a145", "a146", "a147", "a148", "a149", "a150", "a151", "a152",
145 "a153", "a154", "a155", "a156", "a157", "a158", "a159", "a160", "a161",
146 "a162", "a163", "a164", "a165", "a166", "a167", "a168", "a169", "a170",
147 "a171", "a172", "a173", "a174", "a175", "a176", "a177", "a178", "a179",
148 "a180", "a181", "a182", "a183", "a184", "a185", "a186", "a187", "a188",
149 "a189", "a190", "a191", "a192", "a193", "a194", "a195", "a196", "a197",
150 "a198", "a199", "a200", "a201", "a202", "a203", "a204", "a205", "a206",
151 "a207", "a208", "a209", "a210", "a211", "a212", "a213", "a214", "a215",
152 "a216", "a217", "a218", "a219", "a220", "a221", "a222", "a223", "a224",
153 "a225", "a226", "a227", "a228", "a229", "a230", "a231", "a232", "a233",
154 "a234", "a235", "a236", "a237", "a238", "a239", "a240", "a241", "a242",
155 "a243", "a244", "a245", "a246", "a247", "a248", "a249", "a250", "a251",
156 "a252", "a253", "a254", "a255"
157};
158
159ArrayRef<const char *> AMDGPUTargetInfo::getGCCRegNames() const {
160 return llvm::ArrayRef(GCCRegNames);
161}
162
163bool AMDGPUTargetInfo::initFeatureMap(
164 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
165 const std::vector<std::string> &FeatureVec) const {
166
167 using namespace llvm::AMDGPU;
168
169 if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec))
170 return false;
171
172 auto HasError = fillAMDGPUFeatureMap(GPU: CPU, T: getTriple(), Features);
173 switch (HasError.first) {
174 default:
175 break;
176 case llvm::AMDGPU::INVALID_FEATURE_COMBINATION:
177 Diags.Report(DiagID: diag::err_invalid_feature_combination) << HasError.second;
178 return false;
179 case llvm::AMDGPU::UNSUPPORTED_TARGET_FEATURE:
180 Diags.Report(DiagID: diag::err_opt_not_valid_on_target) << HasError.second;
181 return false;
182 }
183
184 return true;
185}
186
187void AMDGPUTargetInfo::fillValidCPUList(
188 SmallVectorImpl<StringRef> &Values) const {
189 if (getTriple().isAMDGCN())
190 llvm::AMDGPU::fillValidArchListAMDGCN(Values, SubArch: getTriple().getSubArch());
191 else
192 llvm::AMDGPU::fillValidArchListR600(Values);
193}
194
195AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
196 const TargetOptions &Opts)
197 : TargetInfo(Triple),
198 GPUKind(Triple.isAMDGCN()
199 ? (Opts.CPU.empty() ? llvm::AMDGPU::getGPUKindFromSubArch(
200 SubArch: Triple.getSubArch())
201 : llvm::AMDGPU::parseArchAMDGCN(CPU: Opts.CPU))
202 : llvm::AMDGPU::parseArchR600(CPU: Opts.CPU)) {
203 resetDataLayout();
204
205 AddrSpaceMap = &AMDGPUAddrSpaceMap;
206 UseAddrSpaceMapMangling = true;
207 HasAMDGPUTypes = true;
208
209 if (Triple.isAMDGCN()) {
210 // __bf16 is always available as a load/store only type on AMDGCN.
211 BFloat16Width = BFloat16Align = 16;
212 BFloat16Format = &llvm::APFloat::BFloat();
213 }
214
215 // TODO: This is not really true for targets without half support, but also
216 // should just be assumed true for the dummy target.
217 HasFastHalfType = true;
218 HasFloat16 = true;
219 WavefrontSize = llvm::AMDGPU::getFeatureBitset(AK: GPUKind).test(
220 I: llvm::AMDGPU::FEAT_SUPPORTS_WAVE32)
221 ? 32
222 : 64;
223
224 // Set pointer width and alignment for the generic address space.
225 PointerWidth = PointerAlign = getPointerWidthV(AS: LangAS::Default);
226 if (getMaxPointerWidth() == 64) {
227 LongWidth = LongAlign = 64;
228 SizeType = UnsignedLong;
229 PtrDiffType = SignedLong;
230 IntPtrType = SignedLong;
231 Int64Type = SignedLong;
232 IntMaxType = SignedLong;
233 }
234
235 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
236 CUMode = !llvm::AMDGPU::getFeatureBitset(AK: GPUKind).test(
237 I: llvm::AMDGPU::FEAT_SUPPORTS_WGP);
238
239 for (auto F : {"image-insts", "gws", "vmem-to-lds-load-insts", "supports-wgp",
240 "supports-wave32", "xnack-support", "sramecc-support",
241 "xnack-on-off-modes"}) {
242 if (GPUKind != llvm::AMDGPU::GK_NONE)
243 ReadOnlyFeatures.insert(key: F);
244 }
245 HalfArgsAndReturns = true;
246
247 if (Opts.AMDGPUXnackState != TargetOptions::AMDGPUFeatureState::Any) {
248 OffloadArchFeatures["xnack"] =
249 Opts.AMDGPUXnackState == TargetOptions::AMDGPUFeatureState::Enabled;
250 }
251
252 if (Opts.AMDGPUSramEccState != TargetOptions::AMDGPUFeatureState::Any) {
253 OffloadArchFeatures["sramecc"] =
254 Opts.AMDGPUSramEccState == TargetOptions::AMDGPUFeatureState::Enabled;
255 }
256}
257
258void AMDGPUTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts,
259 const TargetInfo *Aux) {
260 TargetInfo::adjust(Diags, Opts, Aux);
261 AtomicOpts = AtomicOptions(Opts);
262}
263
264llvm::SmallVector<Builtin::InfosShard>
265AMDGPUTargetInfo::getTargetBuiltins() const {
266 return {{.Strings: &BuiltinStrings, .Infos: BuiltinInfos}};
267}
268
269void AMDGPUTargetInfo::getTargetDefines(const LangOptions &Opts,
270 MacroBuilder &Builder) const {
271 Builder.defineMacro(Name: "__AMD__");
272 Builder.defineMacro(Name: "__AMDGPU__");
273
274 if (getTriple().isAMDGCN())
275 Builder.defineMacro(Name: "__AMDGCN__");
276 else
277 Builder.defineMacro(Name: "__R600__");
278
279 // TODO: __HAS_FMAF__, __HAS_LDEXPF__, __HAS_FP64__ are deprecated and will be
280 // removed in the near future.
281 if (hasFMAF())
282 Builder.defineMacro(Name: "__HAS_FMAF__");
283 if (hasFastFMAF())
284 Builder.defineMacro(Name: "FP_FAST_FMAF");
285 if (hasLDEXPF())
286 Builder.defineMacro(Name: "__HAS_LDEXPF__");
287 if (hasFP64())
288 Builder.defineMacro(Name: "__HAS_FP64__");
289 if (hasFastFMA())
290 Builder.defineMacro(Name: "FP_FAST_FMA");
291 if (HasFastHalfType)
292 Builder.defineMacro(Name: "FP_FAST_FMA_HALF");
293
294 Builder.defineMacro(Name: "__AMDGCN_CUMODE__", Value: Twine(CUMode));
295
296 // Legacy HIP host code relies on these default attributes to be defined.
297 bool IsHIPHost = Opts.HIP && !Opts.CUDAIsDevice;
298 if (GPUKind == llvm::AMDGPU::GK_NONE && !IsHIPHost)
299 return;
300
301 llvm::SmallString<16> CanonName =
302 (getTriple().isAMDGCN() ? getArchNameAMDGCN(AK: GPUKind)
303 : getArchNameR600(AK: GPUKind));
304
305 // Sanitize the name of generic targets, the only names containing '-'.
306 // e.g. gfx10-1-generic -> gfx10_1_generic
307 llvm::replace(Range&: CanonName, OldValue: '-', NewValue: '_');
308
309 Builder.defineMacro(Name: Twine("__") + Twine(CanonName) + Twine("__"));
310 // Emit macros for gfx family e.g. gfx906 -> __GFX9__, gfx1030 -> __GFX10___
311 if (getTriple().isAMDGCN() && !IsHIPHost) {
312 assert(StringRef(CanonName).starts_with("gfx") &&
313 "Invalid amdgcn canonical name");
314 StringRef CanonFamilyName = getArchFamilyNameAMDGCN(AK: GPUKind);
315 Builder.defineMacro(Name: Twine("__") + Twine(CanonFamilyName.upper()) +
316 Twine("__"));
317 Builder.defineMacro(Name: "__amdgcn_processor__",
318 Value: Twine("\"") + Twine(CanonName) + Twine("\""));
319 Builder.defineMacro(
320 Name: "__amdgcn_target_id__",
321 Value: Twine("\"") +
322 Twine(getCanonicalTargetID(Processor: getArchNameAMDGCN(AK: GPUKind),
323 Features: OffloadArchFeatures)) +
324 Twine("\""));
325 for (auto F : getAllPossibleTargetIDFeatures(T: getTriple(), Processor: CanonName)) {
326 auto Loc = OffloadArchFeatures.find(Key: F);
327 if (Loc != OffloadArchFeatures.end()) {
328 std::string NewF = F.str();
329 llvm::replace(Range&: NewF, OldValue: '-', NewValue: '_');
330 Builder.defineMacro(Name: Twine("__amdgcn_feature_") + Twine(NewF) +
331 Twine("__"),
332 Value: Loc->second ? "1" : "0");
333 }
334 }
335 }
336
337 if (Opts.AtomicIgnoreDenormalMode)
338 Builder.defineMacro(Name: "__AMDGCN_UNSAFE_FP_ATOMICS__");
339}
340
341void AMDGPUTargetInfo::setAuxTarget(const TargetInfo *Aux) {
342 assert(HalfFormat == Aux->HalfFormat);
343 assert(FloatFormat == Aux->FloatFormat);
344 assert(DoubleFormat == Aux->DoubleFormat);
345
346 // On x86_64 long double is 80-bit extended precision format, which is
347 // not supported by AMDGPU. 128-bit floating point format is also not
348 // supported by AMDGPU. Therefore keep its own format for these two types.
349 auto SaveLongDoubleFormat = LongDoubleFormat;
350 auto SaveFloat128Format = Float128Format;
351 auto SaveLongDoubleWidth = LongDoubleWidth;
352 auto SaveLongDoubleAlign = LongDoubleAlign;
353 copyAuxTarget(Aux);
354 LongDoubleFormat = SaveLongDoubleFormat;
355 Float128Format = SaveFloat128Format;
356 LongDoubleWidth = SaveLongDoubleWidth;
357 LongDoubleAlign = SaveLongDoubleAlign;
358 // For certain builtin types support on the host target, claim they are
359 // support to pass the compilation of the host code during the device-side
360 // compilation.
361 // FIXME: As the side effect, we also accept `__float128` uses in the device
362 // code. To rejct these builtin types supported in the host target but not in
363 // the device target, one approach would support `device_builtin` attribute
364 // so that we could tell the device builtin types from the host ones. The
365 // also solves the different representations of the same builtin type, such
366 // as `size_t` in the MSVC environment.
367 if (Aux->hasFloat128Type()) {
368 HasFloat128 = true;
369 Float128Format = DoubleFormat;
370 }
371}
372