clang 24.0.0git
SemaAMDGPU.cpp
Go to the documentation of this file.
1//===------ SemaAMDGPU.cpp ------- AMDGPU target-specific routines --------===//
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 semantic analysis functions specific to AMDGPU.
10//
11//===----------------------------------------------------------------------===//
12
14#include "clang/AST/Decl.h"
16#include "clang/AST/Expr.h"
22#include "clang/Sema/Scope.h"
23#include "clang/Sema/Sema.h"
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/ADT/StringExtras.h"
26#include "llvm/ADT/StringMap.h"
27#include "llvm/Support/AMDGPUAddrSpace.h"
28#include "llvm/Support/AMDGPUAsyncStages.h"
29#include "llvm/Support/AtomicOrdering.h"
30#include "llvm/TargetParser/AMDGPUTargetParser.h"
31#include "llvm/TargetParser/AtomicScope.h"
32#include <cstdint>
33#include <utility>
34
35namespace clang {
36
38
40 unsigned BuiltinID,
41 CallExpr *TheCall) {
42 const auto *FD = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
43 assert(FD && "AMDGPU builtins should not be used outside of a function");
44 llvm::StringMap<bool> CallerFeatureMap;
45 getASTContext().getFunctionFeatureMap(CallerFeatureMap, FD);
46 bool HasGFX950Insts =
47 Builtin::evaluateRequiredTargetFeatures("gfx950-insts", CallerFeatureMap);
48
49 switch (BuiltinID) {
50 case AMDGPU::BI__builtin_amdgcn_raw_ptr_buffer_load_lds:
51 case AMDGPU::BI__builtin_amdgcn_raw_ptr_buffer_load_async_lds:
52 case AMDGPU::BI__builtin_amdgcn_struct_ptr_buffer_load_lds:
53 case AMDGPU::BI__builtin_amdgcn_struct_ptr_buffer_load_async_lds:
54 case AMDGPU::BI__builtin_amdgcn_load_to_lds:
55 case AMDGPU::BI__builtin_amdgcn_load_async_to_lds:
56 case AMDGPU::BI__builtin_amdgcn_global_load_lds:
57 case AMDGPU::BI__builtin_amdgcn_global_load_async_lds: {
58 constexpr const int SizeIdx = 2;
59 llvm::APSInt Size;
60 Expr *ArgExpr = TheCall->getArg(SizeIdx);
61 // Check for instantiation-dependent expressions (e.g., involving template
62 // parameters). These will be checked again during template instantiation.
63 if (ArgExpr->isInstantiationDependent())
64 return false;
65 [[maybe_unused]] ExprResult R =
66 SemaRef.VerifyIntegerConstantExpression(ArgExpr, &Size);
67 assert(!R.isInvalid());
68 switch (Size.getSExtValue()) {
69 case 1:
70 case 2:
71 case 4:
72 return false;
73 case 12:
74 case 16: {
75 if (HasGFX950Insts)
76 return false;
77 [[fallthrough]];
78 }
79 default:
80 SemaRef.targetDiag(ArgExpr->getExprLoc(),
81 diag::err_amdgcn_load_lds_size_invalid_value)
82 << ArgExpr->getSourceRange();
83 SemaRef.targetDiag(ArgExpr->getExprLoc(),
84 diag::note_amdgcn_load_lds_size_valid_value)
85 << HasGFX950Insts << ArgExpr->getSourceRange();
86 return true;
87 }
88 }
89 case AMDGPU::BI__builtin_amdgcn_uicmp:
90 case AMDGPU::BI__builtin_amdgcn_uicmpl:
91 case AMDGPU::BI__builtin_amdgcn_sicmp:
92 case AMDGPU::BI__builtin_amdgcn_sicmpl:
93 case AMDGPU::BI__builtin_amdgcn_fcmp:
94 case AMDGPU::BI__builtin_amdgcn_fcmpf: {
95 // These builtins are deprecated in favor of
96 // __builtin_amdgcn_ballot_{w32|w64}. Suggest the replacement matching the
97 // wavefront size of the calling function.
98 bool IsWave32 = Builtin::evaluateRequiredTargetFeatures("wavefrontsize32",
99 CallerFeatureMap);
100 Diag(TheCall->getBeginLoc(), diag::warn_deprecated_builtin)
102 << (IsWave32 ? "__builtin_amdgcn_ballot_w32"
103 : "__builtin_amdgcn_ballot_w64");
104 return false;
105 }
106 case AMDGPU::BI__builtin_amdgcn_get_fpenv:
107 case AMDGPU::BI__builtin_amdgcn_set_fpenv:
108 return false;
109 case AMDGPU::BI__builtin_amdgcn_atomic_inc32:
110 case AMDGPU::BI__builtin_amdgcn_atomic_inc64:
111 case AMDGPU::BI__builtin_amdgcn_atomic_dec32:
112 case AMDGPU::BI__builtin_amdgcn_atomic_dec64:
113 case AMDGPU::BI__builtin_amdgcn_fence: {
114 bool IsFence = BuiltinID == AMDGPU::BI__builtin_amdgcn_fence;
115 unsigned OrderIndex = IsFence ? 0 : 2;
116 unsigned ScopeIndex = IsFence ? 1 : 3;
117 Expr *OrderExpr = TheCall->getArg(OrderIndex);
118 Expr *ScopeExpr = TheCall->getArg(ScopeIndex);
119
120 // Checks requiring constant evaluation are deferred until instantiation.
121 if (OrderExpr->isInstantiationDependent() ||
122 ScopeExpr->isInstantiationDependent())
123 return false;
124
125 Expr::EvalResult OrderResult;
126 if (!OrderExpr->EvaluateAsInt(OrderResult, getASTContext()))
127 return Diag(OrderExpr->getExprLoc(), diag::err_typecheck_expect_int)
128 << OrderExpr->getType();
129 uint64_t Ord = OrderResult.Val.getInt().getZExtValue();
130
131 // Check validity of memory ordering as per C11 / C++11's memory model.
132 // Only fence needs check. Atomic dec/inc allow all memory orders.
133 if (!llvm::isValidAtomicOrderingCABI(Ord))
134 return Diag(OrderExpr->getBeginLoc(),
135 diag::warn_atomic_op_has_invalid_memory_order)
136 << 0 << OrderExpr->getSourceRange();
137 switch (static_cast<llvm::AtomicOrderingCABI>(Ord)) {
138 case llvm::AtomicOrderingCABI::relaxed:
139 case llvm::AtomicOrderingCABI::consume:
140 if (IsFence)
141 return Diag(OrderExpr->getBeginLoc(),
142 diag::warn_atomic_op_has_invalid_memory_order)
143 << 0 << OrderExpr->getSourceRange();
144 break;
145 case llvm::AtomicOrderingCABI::acquire:
146 case llvm::AtomicOrderingCABI::release:
147 case llvm::AtomicOrderingCABI::acq_rel:
148 case llvm::AtomicOrderingCABI::seq_cst:
149 break;
150 }
151
152 Expr::EvalResult ScopeResult;
153 // Check that sync scope is a constant literal
154 if (!ScopeExpr->EvaluateAsConstantExpr(ScopeResult, getASTContext()))
155 return Diag(ScopeExpr->getExprLoc(), diag::err_expr_not_string_literal)
156 << ScopeExpr->getType();
157
158 // Reject any string that is not a valid synchronization scope name.
159 std::optional<std::string> ScopeName =
160 ScopeExpr->tryEvaluateString(getASTContext());
161 const llvm::Triple &TT = TI.getTriple();
162 if (ScopeName && !llvm::parseAtomicScopeIRString(TT, *ScopeName)) {
163 return Diag(ScopeExpr->getExprLoc(), diag::err_invalid_sync_scope)
164 << *ScopeName << ScopeExpr->getSourceRange();
165 }
166
167 return false;
168 }
169 case AMDGPU::BI__builtin_amdgcn_s_setreg:
170 return SemaRef.BuiltinConstantArgRange(TheCall, /*ArgNum=*/0, /*Low=*/0,
171 /*High=*/UINT16_MAX);
172 case AMDGPU::BI__builtin_amdgcn_flat_prefetch:
173 case AMDGPU::BI__builtin_amdgcn_global_prefetch: {
174 // Only th (bits 0-2, not 7), scope (bits 3-4) and nv (bit 5) may be set.
175 llvm::APSInt CPol;
176 if (SemaRef.BuiltinConstantArgRange(TheCall, /*ArgNum=*/1, /*Low=*/0,
177 /*High=*/63) ||
178 SemaRef.BuiltinConstantArg(TheCall, /*ArgNum=*/1, CPol))
179 return true;
180 if ((CPol.getZExtValue() & 0x7) != 0x7)
181 return false;
182 Expr *ArgExpr = TheCall->getArg(1);
183 SemaRef.targetDiag(ArgExpr->getExprLoc(),
184 diag::err_amdgcn_prefetch_reserved_th)
185 << ArgExpr->getSourceRange();
186 return true;
187 }
188 case AMDGPU::BI__builtin_amdgcn_s_wait_event: {
189 llvm::APSInt Result;
190 if (SemaRef.BuiltinConstantArg(TheCall, 0, Result))
191 return true;
192
194 "gfx12-insts", CallerFeatureMap);
195
196 // gfx11 -> gfx12 changed the interpretation of the bitmask. gfx12 inverted
197 // the intepretation for export_ready, but shifted the used bit by 1. Thus
198 // waiting for the export_ready event can use a value of 2 universally.
199 if (((IsGFX12Plus && !Result[1]) || (!IsGFX12Plus && Result[0])) ||
200 Result.getZExtValue() > 2) {
201 Expr *ArgExpr = TheCall->getArg(0);
202 SemaRef.targetDiag(ArgExpr->getExprLoc(),
203 diag::warn_amdgpu_s_wait_event_mask_no_effect_target)
204 << ArgExpr->getSourceRange();
205 SemaRef.targetDiag(ArgExpr->getExprLoc(),
206 diag::note_amdgpu_s_wait_event_suggested_value)
207 << ArgExpr->getSourceRange();
208 }
209
210 return false;
211 }
212 case AMDGPU::BI__builtin_amdgcn_mov_dpp:
213 return checkMovDPPFunctionCall(TheCall, 5, 1);
214 case AMDGPU::BI__builtin_amdgcn_mov_dpp8:
215 return checkMovDPPFunctionCall(TheCall, 2, 1);
216 case AMDGPU::BI__builtin_amdgcn_update_dpp:
217 return checkMovDPPFunctionCall(TheCall, 6, 2);
218 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp8:
219 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp8:
220 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_bf8:
221 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_bf8:
222 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp4:
223 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp4:
224 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp8:
225 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_bf8:
226 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp4:
227 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_fp6:
228 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_fp6:
229 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_bf6:
230 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_bf6:
231 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_fp6:
232 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_bf6:
233 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk32_bf16_bf6:
234 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk32_bf16_fp6:
235 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk32_f16_bf6:
236 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk32_f16_fp6:
237 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk32_f32_bf6:
238 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk32_f32_fp6:
239 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 15);
240 case AMDGPU::BI__builtin_amdgcn_asyncmark:
241 case AMDGPU::BI__builtin_amdgcn_wait_asyncmark: {
242 bool IsMark = BuiltinID == AMDGPU::BI__builtin_amdgcn_asyncmark;
243
244 // Check the sequence length limit is a constant.
245 llvm::APSInt NumMarks;
246 if (!IsMark && SemaRef.BuiltinConstantArg(TheCall, 0, NumMarks))
247 return true;
248
249 // The stage mask names the stages to act on, so every combination of known
250 // stage bits is meaningful, including none of them: the zero mask names
251 // every stage.
252 unsigned MaskArgNum = IsMark ? 0 : 1;
253 return SemaRef.BuiltinConstantArgRange(
254 TheCall, MaskArgNum, 0,
255 llvm::to_underlying(llvm::AMDGPU::AsyncStages::ALL));
256 }
257 case AMDGPU::BI__builtin_amdgcn_av_load_b8:
258 case AMDGPU::BI__builtin_amdgcn_av_load_b16:
259 case AMDGPU::BI__builtin_amdgcn_av_load_b32:
260 case AMDGPU::BI__builtin_amdgcn_av_load_b64:
261 case AMDGPU::BI__builtin_amdgcn_av_load_b128:
262 return checkAVLoadStore(TheCall, /*IsStore=*/false);
263 case AMDGPU::BI__builtin_amdgcn_av_store_b8:
264 case AMDGPU::BI__builtin_amdgcn_av_store_b16:
265 case AMDGPU::BI__builtin_amdgcn_av_store_b32:
266 case AMDGPU::BI__builtin_amdgcn_av_store_b64:
267 case AMDGPU::BI__builtin_amdgcn_av_store_b128:
268 return checkAVLoadStore(TheCall, /*IsStore=*/true);
269 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_load_32x4B:
270 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_load_16x8B:
271 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_load_8x16B:
272 return checkCoopAtomicFunctionCall(TheCall, /*IsStore=*/false);
273 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_store_32x4B:
274 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_store_16x8B:
275 case AMDGPU::BI__builtin_amdgcn_cooperative_atomic_store_8x16B:
276 return checkCoopAtomicFunctionCall(TheCall, /*IsStore=*/true);
277 case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b32:
278 case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b64:
279 case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b128:
280 case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b32:
281 case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b64:
282 case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b128:
283 return checkAtomicMonitorLoad(TheCall);
284 case AMDGPU::BI__builtin_amdgcn_image_load_1d_v4f32_i32:
285 case AMDGPU::BI__builtin_amdgcn_image_load_1darray_v4f32_i32:
286 case AMDGPU::BI__builtin_amdgcn_image_load_1d_v4f16_i32:
287 case AMDGPU::BI__builtin_amdgcn_image_load_1darray_v4f16_i32:
288 case AMDGPU::BI__builtin_amdgcn_image_load_2d_f32_i32:
289 case AMDGPU::BI__builtin_amdgcn_image_load_2d_v4f32_i32:
290 case AMDGPU::BI__builtin_amdgcn_image_load_2d_v4f16_i32:
291 case AMDGPU::BI__builtin_amdgcn_image_load_2darray_f32_i32:
292 case AMDGPU::BI__builtin_amdgcn_image_load_2darray_v4f32_i32:
293 case AMDGPU::BI__builtin_amdgcn_image_load_2darray_v4f16_i32:
294 case AMDGPU::BI__builtin_amdgcn_image_load_3d_v4f32_i32:
295 case AMDGPU::BI__builtin_amdgcn_image_load_3d_v4f16_i32:
296 case AMDGPU::BI__builtin_amdgcn_image_load_cube_v4f32_i32:
297 case AMDGPU::BI__builtin_amdgcn_image_load_cube_v4f16_i32:
298 case AMDGPU::BI__builtin_amdgcn_image_load_mip_1d_v4f32_i32:
299 case AMDGPU::BI__builtin_amdgcn_image_load_mip_1d_v4f16_i32:
300 case AMDGPU::BI__builtin_amdgcn_image_load_mip_1darray_v4f32_i32:
301 case AMDGPU::BI__builtin_amdgcn_image_load_mip_1darray_v4f16_i32:
302 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2d_f32_i32:
303 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2d_v4f32_i32:
304 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2d_v4f16_i32:
305 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2darray_f32_i32:
306 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2darray_v4f32_i32:
307 case AMDGPU::BI__builtin_amdgcn_image_load_mip_2darray_v4f16_i32:
308 case AMDGPU::BI__builtin_amdgcn_image_load_mip_3d_v4f32_i32:
309 case AMDGPU::BI__builtin_amdgcn_image_load_mip_3d_v4f16_i32:
310 case AMDGPU::BI__builtin_amdgcn_image_load_mip_cube_v4f32_i32:
311 case AMDGPU::BI__builtin_amdgcn_image_load_mip_cube_v4f16_i32:
312 case AMDGPU::BI__builtin_amdgcn_image_sample_1d_v4f32_f32:
313 case AMDGPU::BI__builtin_amdgcn_image_sample_1darray_v4f32_f32:
314 case AMDGPU::BI__builtin_amdgcn_image_sample_1d_v4f16_f32:
315 case AMDGPU::BI__builtin_amdgcn_image_sample_1darray_v4f16_f32:
316 case AMDGPU::BI__builtin_amdgcn_image_sample_2d_f32_f32:
317 case AMDGPU::BI__builtin_amdgcn_image_sample_2d_v4f32_f32:
318 case AMDGPU::BI__builtin_amdgcn_image_sample_2d_v4f16_f32:
319 case AMDGPU::BI__builtin_amdgcn_image_sample_2darray_f32_f32:
320 case AMDGPU::BI__builtin_amdgcn_image_sample_2darray_v4f32_f32:
321 case AMDGPU::BI__builtin_amdgcn_image_sample_2darray_v4f16_f32:
322 case AMDGPU::BI__builtin_amdgcn_image_sample_3d_v4f32_f32:
323 case AMDGPU::BI__builtin_amdgcn_image_sample_3d_v4f16_f32:
324 case AMDGPU::BI__builtin_amdgcn_image_sample_cube_v4f32_f32:
325 case AMDGPU::BI__builtin_amdgcn_image_sample_cube_v4f16_f32:
326 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_1d_v4f32_f32:
327 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_1d_v4f16_f32:
328 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_1darray_v4f32_f32:
329 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_1darray_v4f16_f32:
330 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2d_f32_f32:
331 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2d_v4f32_f32:
332 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2d_v4f16_f32:
333 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2darray_f32_f32:
334 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2darray_v4f32_f32:
335 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_2darray_v4f16_f32:
336 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_3d_v4f32_f32:
337 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_3d_v4f16_f32:
338 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_cube_v4f32_f32:
339 case AMDGPU::BI__builtin_amdgcn_image_sample_lz_cube_v4f16_f32:
340 case AMDGPU::BI__builtin_amdgcn_image_sample_l_1d_v4f32_f32:
341 case AMDGPU::BI__builtin_amdgcn_image_sample_l_1d_v4f16_f32:
342 case AMDGPU::BI__builtin_amdgcn_image_sample_l_1darray_v4f32_f32:
343 case AMDGPU::BI__builtin_amdgcn_image_sample_l_1darray_v4f16_f32:
344 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2d_f32_f32:
345 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2d_v4f16_f32:
346 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2d_v4f32_f32:
347 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2darray_f32_f32:
348 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2darray_v4f32_f32:
349 case AMDGPU::BI__builtin_amdgcn_image_sample_l_2darray_v4f16_f32:
350 case AMDGPU::BI__builtin_amdgcn_image_sample_l_3d_v4f32_f32:
351 case AMDGPU::BI__builtin_amdgcn_image_sample_l_3d_v4f16_f32:
352 case AMDGPU::BI__builtin_amdgcn_image_sample_l_cube_v4f32_f32:
353 case AMDGPU::BI__builtin_amdgcn_image_sample_l_cube_v4f16_f32:
354 case AMDGPU::BI__builtin_amdgcn_image_sample_d_1d_v4f32_f32:
355 case AMDGPU::BI__builtin_amdgcn_image_sample_d_1d_v4f16_f32:
356 case AMDGPU::BI__builtin_amdgcn_image_sample_d_1darray_v4f32_f32:
357 case AMDGPU::BI__builtin_amdgcn_image_sample_d_1darray_v4f16_f32:
358 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2d_f32_f32:
359 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2d_v4f32_f32:
360 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2d_v4f16_f32:
361 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2darray_f32_f32:
362 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2darray_v4f32_f32:
363 case AMDGPU::BI__builtin_amdgcn_image_sample_d_2darray_v4f16_f32:
364 case AMDGPU::BI__builtin_amdgcn_image_sample_d_3d_v4f32_f32:
365 case AMDGPU::BI__builtin_amdgcn_image_sample_d_3d_v4f16_f32:
366 case AMDGPU::BI__builtin_amdgcn_image_gather4_lz_2d_v4f32_f32:
367 case AMDGPU::BI__builtin_amdgcn_image_gather4_lz_2d_v4f16_f32: {
368 StringRef FeatureList(
369 getASTContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
371 CallerFeatureMap)) {
372 Diag(TheCall->getBeginLoc(), diag::err_builtin_needs_feature)
373 << FD->getDeclName() << FeatureList;
374 return false;
375 }
376
377 unsigned ArgCount = TheCall->getNumArgs() - 1;
378 llvm::APSInt Result;
379
380 // Compilain about dmask values which are too huge to fully fit into 4 bits
381 // (which is the actual size of the dmask in corresponding HW instructions).
382 constexpr unsigned DMaskArgNo = 0;
383 constexpr int Low = 0;
384 constexpr int High = 15;
385 if (SemaRef.BuiltinConstantArg(TheCall, DMaskArgNo, Result) ||
386 SemaRef.BuiltinConstantArgRange(TheCall, DMaskArgNo, Low, High,
387 /* RangeIsError = */ true))
388 return true;
389
390 // Dmask indicates which elements should be returned and it is not possible
391 // to return more values than there are elements in return type.
392 int NumElementsInRetTy = 1;
393 const Type *RetTy = TheCall->getType().getTypePtr();
394 if (auto *VTy = dyn_cast<VectorType>(RetTy))
395 NumElementsInRetTy = VTy->getNumElements();
396 int NumActiveBitsInDMask =
397 llvm::popcount(static_cast<uint8_t>(Result.getExtValue()));
398 if (NumActiveBitsInDMask > NumElementsInRetTy) {
399 Diag(TheCall->getBeginLoc(),
400 diag::err_amdgcn_dmask_has_too_many_bits_set);
401 return true;
402 }
403
404 // For gather, only one bit can be set indicating which exact component to
405 // return.
406 bool ExtraGatherChecks =
407 (BuiltinID ==
408 AMDGPU::BI__builtin_amdgcn_image_gather4_lz_2d_v4f32_f32 ||
409 BuiltinID ==
410 AMDGPU::BI__builtin_amdgcn_image_gather4_lz_2d_v4f16_f32) &&
411 SemaRef.BuiltinConstantArgPower2(TheCall, 0);
412
413 return ExtraGatherChecks ||
414 (SemaRef.BuiltinConstantArg(TheCall, ArgCount, Result)) ||
415 (SemaRef.BuiltinConstantArg(TheCall, (ArgCount - 1), Result));
416 }
417 case AMDGPU::BI__builtin_amdgcn_image_store_1d_v4f32_i32:
418 case AMDGPU::BI__builtin_amdgcn_image_store_1darray_v4f32_i32:
419 case AMDGPU::BI__builtin_amdgcn_image_store_1d_v4f16_i32:
420 case AMDGPU::BI__builtin_amdgcn_image_store_1darray_v4f16_i32:
421 case AMDGPU::BI__builtin_amdgcn_image_store_2d_f32_i32:
422 case AMDGPU::BI__builtin_amdgcn_image_store_2d_v4f32_i32:
423 case AMDGPU::BI__builtin_amdgcn_image_store_2d_v4f16_i32:
424 case AMDGPU::BI__builtin_amdgcn_image_store_2darray_f32_i32:
425 case AMDGPU::BI__builtin_amdgcn_image_store_2darray_v4f32_i32:
426 case AMDGPU::BI__builtin_amdgcn_image_store_2darray_v4f16_i32:
427 case AMDGPU::BI__builtin_amdgcn_image_store_3d_v4f32_i32:
428 case AMDGPU::BI__builtin_amdgcn_image_store_3d_v4f16_i32:
429 case AMDGPU::BI__builtin_amdgcn_image_store_cube_v4f32_i32:
430 case AMDGPU::BI__builtin_amdgcn_image_store_cube_v4f16_i32:
431 case AMDGPU::BI__builtin_amdgcn_image_store_mip_1d_v4f32_i32:
432 case AMDGPU::BI__builtin_amdgcn_image_store_mip_1d_v4f16_i32:
433 case AMDGPU::BI__builtin_amdgcn_image_store_mip_1darray_v4f32_i32:
434 case AMDGPU::BI__builtin_amdgcn_image_store_mip_1darray_v4f16_i32:
435 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2d_f32_i32:
436 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2d_v4f32_i32:
437 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2d_v4f16_i32:
438 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2darray_f32_i32:
439 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2darray_v4f32_i32:
440 case AMDGPU::BI__builtin_amdgcn_image_store_mip_2darray_v4f16_i32:
441 case AMDGPU::BI__builtin_amdgcn_image_store_mip_3d_v4f32_i32:
442 case AMDGPU::BI__builtin_amdgcn_image_store_mip_3d_v4f16_i32:
443 case AMDGPU::BI__builtin_amdgcn_image_store_mip_cube_v4f32_i32:
444 case AMDGPU::BI__builtin_amdgcn_image_store_mip_cube_v4f16_i32: {
445 StringRef FeatureList(
446 getASTContext().BuiltinInfo.getRequiredFeatures(BuiltinID));
448 CallerFeatureMap)) {
449 Diag(TheCall->getBeginLoc(), diag::err_builtin_needs_feature)
450 << FD->getDeclName() << FeatureList;
451 return false;
452 }
453
454 unsigned ArgCount = TheCall->getNumArgs() - 1;
455 llvm::APSInt Result;
456
457 // Complain about dmask values which are too huge to fully fit into 4 bits
458 // (which is the actual size of the dmask in corresponding HW instructions).
459 constexpr unsigned DMaskArgNo = 1;
460 return SemaRef.BuiltinConstantArgRange(TheCall, DMaskArgNo, /*Low=*/0,
461 /*High=*/15,
462 /*RangeIsError=*/true) ||
463 SemaRef.BuiltinConstantArg(TheCall, ArgCount, Result) ||
464 SemaRef.BuiltinConstantArg(TheCall, (ArgCount - 1), Result);
465 }
466 case AMDGPU::BI__builtin_amdgcn_wmma_i32_16x16x64_iu8:
467 case AMDGPU::BI__builtin_amdgcn_swmmac_i32_16x16x128_iu8: {
468 if (BuiltinID == AMDGPU::BI__builtin_amdgcn_wmma_i32_16x16x64_iu8) {
469 if (SemaRef.checkArgCountRange(TheCall, 7, 8))
470 return true;
471 if (TheCall->getNumArgs() == 7)
472 return false;
473 } else if (BuiltinID ==
474 AMDGPU::BI__builtin_amdgcn_swmmac_i32_16x16x128_iu8) {
475 if (SemaRef.checkArgCountRange(TheCall, 8, 9))
476 return true;
477 if (TheCall->getNumArgs() == 8)
478 return false;
479 }
480 // Check if the last argument (clamp operand) is a constant and is
481 // convertible to bool.
482 Expr *ClampArg = TheCall->getArg(TheCall->getNumArgs() - 1);
483 // 1) Ensure clamp argument is a constant expression
484 llvm::APSInt ClampValue;
485 if (!SemaRef.VerifyIntegerConstantExpression(ClampArg, &ClampValue)
486 .isUsable())
487 return true;
488 // 2) Check if the argument can be converted to bool type
489 if (!SemaRef.Context.hasSameType(ClampArg->getType(),
490 SemaRef.Context.BoolTy)) {
491 // Try to convert to bool
492 QualType BoolTy = SemaRef.Context.BoolTy;
493 ExprResult ClampExpr(ClampArg);
494 SemaRef.CheckSingleAssignmentConstraints(BoolTy, ClampExpr);
495 if (ClampExpr.isInvalid())
496 return true;
497 }
498 return false;
499 }
500 case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x32_bf16:
501 case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x4_f32:
502 case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x32_f16:
503 case AMDGPU::BI__builtin_amdgcn_wmma_f16_16x16x32_f16:
504 case AMDGPU::BI__builtin_amdgcn_wmma_bf16_16x16x32_bf16:
505 case AMDGPU::BI__builtin_amdgcn_wmma_bf16f32_16x16x32_bf16:
506 return SemaRef.BuiltinConstantArgRange(TheCall, /*ArgNum=*/0, /*Low=*/0,
507 /*High=*/0) ||
508 SemaRef.BuiltinConstantArgRange(TheCall, /*ArgNum=*/2, /*Low=*/0,
509 /*High=*/0);
510 default:
511 return false;
512 }
513}
514
516 bool MayStore) {
517 Expr::EvalResult AtomicOrdArgRes;
518 if (!E->EvaluateAsInt(AtomicOrdArgRes, getASTContext()))
519 llvm_unreachable("Intrinsic requires imm for atomic ordering argument!");
520 auto Ord =
521 llvm::AtomicOrderingCABI(AtomicOrdArgRes.Val.getInt().getZExtValue());
522
523 // Atomic ordering cannot be acq_rel in any case, acquire for stores or
524 // release for loads.
525 if (!llvm::isValidAtomicOrderingCABI((unsigned)Ord) ||
526 (!(MayLoad && MayStore) && (Ord == llvm::AtomicOrderingCABI::acq_rel)) ||
527 (!MayLoad && Ord == llvm::AtomicOrderingCABI::acquire) ||
528 (!MayStore && Ord == llvm::AtomicOrderingCABI::release)) {
529 return Diag(E->getBeginLoc(), diag::warn_atomic_op_has_invalid_memory_order)
530 << 0 << E->getSourceRange();
531 }
532
533 return false;
534}
535
536// Check that the first argument to TheCall is a global or generic pointer.
538 Expr *PtrArg = TheCall->getArg(0);
539 QualType PtrTy = PtrArg->getType()->getPointeeType();
540 unsigned AS =
541 S.getASTContext().getTargetAddressSpace(PtrTy.getAddressSpace());
542 if (AS != llvm::AMDGPUAS::FLAT_ADDRESS &&
543 AS != llvm::AMDGPUAS::GLOBAL_ADDRESS) {
544 return S.Diag(TheCall->getBeginLoc(),
545 diag::err_amdgcn_global_or_flat_pointer_required)
546 << PtrArg->getSourceRange();
547 }
548 return false;
549}
550
552 if (Scope->isValueDependent())
553 return false;
555 if (std::optional<llvm::APSInt> Result =
556 Scope->getIntegerConstantExpr(S.SemaRef.Context)) {
557 if (!ScopeModel->isValid(Result->getZExtValue())) {
558 return S.Diag(Scope->getBeginLoc(),
559 diag::err_atomic_op_has_invalid_sync_scope)
560 << Scope->getSourceRange();
561 }
562 }
563 return false;
564}
565
566bool SemaAMDGPU::checkAVLoadStore(CallExpr *TheCall, bool IsStore) {
567 if (checkGlobalOrFlatPointerArg(*this, TheCall))
568 return true;
569
570 Expr *Scope = TheCall->getArg(TheCall->getNumArgs() - 1);
571 return checkScopeAsInt(*this, Scope);
572}
573
575 bool Fail = checkGlobalOrFlatPointerArg(*this, TheCall);
576
577 Expr *AO = TheCall->getArg(IsStore ? 2 : 1);
578 Expr *Scope = TheCall->getArg(TheCall->getNumArgs() - 1);
579
580 if (AO->isValueDependent() || Scope->isValueDependent())
581 return false;
582
583 // Check atomic ordering
584 Fail |=
585 checkAtomicOrderingCABIArg(TheCall->getArg(IsStore ? 2 : 1),
586 /*MayLoad=*/!IsStore, /*MayStore=*/IsStore);
587
588 // Last argument is the syncscope as a string literal.
589 if (!isa<StringLiteral>(Scope->IgnoreParenImpCasts())) {
590 Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
591 << Scope->getSourceRange();
592 Fail = true;
593 }
594
595 return Fail;
596}
597
599 Expr *AO = TheCall->getArg(1);
600 Expr *Scope = TheCall->getArg(TheCall->getNumArgs() - 1);
601
602 if (AO->isValueDependent() || Scope->isValueDependent())
603 return false;
604
605 bool Fail = checkAtomicOrderingCABIArg(AO, /*MayLoad=*/true,
606 /*MayStore=*/false);
607 Fail |= checkScopeAsInt(*this, Scope);
608 return Fail;
609}
610
611bool SemaAMDGPU::checkMovDPPFunctionCall(CallExpr *TheCall, unsigned NumArgs,
612 unsigned NumDataArgs) {
613 assert(NumDataArgs <= 2);
614 if (SemaRef.checkArgCountRange(TheCall, NumArgs, NumArgs))
615 return true;
616 Expr *Args[2];
617 QualType ArgTys[2];
618 for (unsigned I = 0; I != NumDataArgs; ++I) {
619 Args[I] = TheCall->getArg(I);
620 ArgTys[I] = Args[I]->getType();
621 // TODO: Vectors can also be supported.
622 if (!ArgTys[I]->isArithmeticType() || ArgTys[I]->isAnyComplexType()) {
623 SemaRef.Diag(Args[I]->getBeginLoc(),
624 diag::err_typecheck_cond_expect_int_float)
625 << ArgTys[I] << Args[I]->getSourceRange();
626 return true;
627 }
628 }
629 if (NumDataArgs < 2)
630 return false;
631
632 if (getASTContext().hasSameUnqualifiedType(ArgTys[0], ArgTys[1]))
633 return false;
634
635 if (((ArgTys[0]->isUnsignedIntegerType() &&
636 ArgTys[1]->isSignedIntegerType()) ||
637 (ArgTys[0]->isSignedIntegerType() &&
638 ArgTys[1]->isUnsignedIntegerType())) &&
639 getASTContext().getTypeSize(ArgTys[0]) ==
640 getASTContext().getTypeSize(ArgTys[1]))
641 return false;
642
643 SemaRef.Diag(Args[1]->getBeginLoc(),
644 diag::err_typecheck_call_different_arg_types)
645 << ArgTys[0] << ArgTys[1];
646 return true;
647}
648
649static bool
651 const AMDGPUFlatWorkGroupSizeAttr &Attr) {
652 // Accept template arguments for now as they depend on something else.
653 // We'll get to check them when they eventually get instantiated.
654 if (MinExpr->isValueDependent() || MaxExpr->isValueDependent())
655 return false;
656
657 uint32_t Min = 0;
658 if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0))
659 return true;
660
661 uint32_t Max = 0;
662 if (!S.checkUInt32Argument(Attr, MaxExpr, Max, 1))
663 return true;
664
665 if (Min == 0 && Max != 0) {
666 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
667 << &Attr << 0;
668 return true;
669 }
670 if (Min > Max) {
671 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
672 << &Attr << 1;
673 return true;
674 }
675
676 return false;
677}
678
679AMDGPUFlatWorkGroupSizeAttr *
681 Expr *MinExpr, Expr *MaxExpr) {
682 ASTContext &Context = getASTContext();
683 AMDGPUFlatWorkGroupSizeAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
684
685 if (checkAMDGPUFlatWorkGroupSizeArguments(SemaRef, MinExpr, MaxExpr, TmpAttr))
686 return nullptr;
687 return ::new (Context)
688 AMDGPUFlatWorkGroupSizeAttr(Context, CI, MinExpr, MaxExpr);
689}
690
692 const AttributeCommonInfo &CI,
693 Expr *MinExpr, Expr *MaxExpr) {
694 if (auto *Attr = CreateAMDGPUFlatWorkGroupSizeAttr(CI, MinExpr, MaxExpr))
695 D->addAttr(Attr);
696}
697
699 const ParsedAttr &AL) {
700 Expr *MinExpr = AL.getArgAsExpr(0);
701 Expr *MaxExpr = AL.getArgAsExpr(1);
702
703 addAMDGPUFlatWorkGroupSizeAttr(D, AL, MinExpr, MaxExpr);
704}
705
706static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr,
707 Expr *MaxExpr,
708 const AMDGPUWavesPerEUAttr &Attr) {
709 if (S.DiagnoseUnexpandedParameterPack(MinExpr) ||
710 (MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr)))
711 return true;
712
713 // Accept template arguments for now as they depend on something else.
714 // We'll get to check them when they eventually get instantiated.
715 if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent()))
716 return false;
717
718 uint32_t Min = 0;
719 if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0))
720 return true;
721
722 uint32_t Max = 0;
723 if (MaxExpr && !S.checkUInt32Argument(Attr, MaxExpr, Max, 1))
724 return true;
725
726 if (Min == 0 && Max != 0) {
727 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
728 << &Attr << 0;
729 return true;
730 }
731 if (Max != 0 && Min > Max) {
732 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
733 << &Attr << 1;
734 return true;
735 }
736
737 return false;
738}
739
740AMDGPUWavesPerEUAttr *
742 Expr *MinExpr, Expr *MaxExpr) {
743 ASTContext &Context = getASTContext();
744 AMDGPUWavesPerEUAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
745
746 if (checkAMDGPUWavesPerEUArguments(SemaRef, MinExpr, MaxExpr, TmpAttr))
747 return nullptr;
748
749 return ::new (Context) AMDGPUWavesPerEUAttr(Context, CI, MinExpr, MaxExpr);
750}
751
753 Expr *MinExpr, Expr *MaxExpr) {
754 if (auto *Attr = CreateAMDGPUWavesPerEUAttr(CI, MinExpr, MaxExpr))
755 D->addAttr(Attr);
756}
757
760 return;
761
762 Expr *MinExpr = AL.getArgAsExpr(0);
763 Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
764
765 addAMDGPUWavesPerEUAttr(D, AL, MinExpr, MaxExpr);
766}
767
769 Diag(AL.getLoc(), diag::warn_amdgpu_num_reg_attr_deprecated) << AL;
770
771 uint32_t NumSGPR = 0;
772 Expr *NumSGPRExpr = AL.getArgAsExpr(0);
773 if (!SemaRef.checkUInt32Argument(AL, NumSGPRExpr, NumSGPR))
774 return;
775
776 D->addAttr(::new (getASTContext())
777 AMDGPUNumSGPRAttr(getASTContext(), AL, NumSGPR));
778}
779
781 Diag(AL.getLoc(), diag::warn_amdgpu_num_reg_attr_deprecated) << AL;
782
783 uint32_t NumVGPR = 0;
784 Expr *NumVGPRExpr = AL.getArgAsExpr(0);
785 if (!SemaRef.checkUInt32Argument(AL, NumVGPRExpr, NumVGPR))
786 return;
787
788 D->addAttr(::new (getASTContext())
789 AMDGPUNumVGPRAttr(getASTContext(), AL, NumVGPR));
790}
791
792static bool
794 Expr *ZExpr,
795 const AMDGPUMaxNumWorkGroupsAttr &Attr) {
796 if (S.DiagnoseUnexpandedParameterPack(XExpr) ||
797 (YExpr && S.DiagnoseUnexpandedParameterPack(YExpr)) ||
798 (ZExpr && S.DiagnoseUnexpandedParameterPack(ZExpr)))
799 return true;
800
801 // Accept template arguments for now as they depend on something else.
802 // We'll get to check them when they eventually get instantiated.
803 if (XExpr->isValueDependent() || (YExpr && YExpr->isValueDependent()) ||
804 (ZExpr && ZExpr->isValueDependent()))
805 return false;
806
807 uint32_t NumWG = 0;
808 Expr *Exprs[3] = {XExpr, YExpr, ZExpr};
809 for (int i = 0; i < 3; i++) {
810 if (Exprs[i]) {
811 if (!S.checkUInt32Argument(Attr, Exprs[i], NumWG, i,
812 /*StrictlyUnsigned=*/true))
813 return true;
814 if (NumWG == 0) {
815 S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
816 << &Attr << Exprs[i]->getSourceRange();
817 return true;
818 }
819 }
820 }
821
822 return false;
823}
824
826 const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr) {
827 ASTContext &Context = getASTContext();
828 AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr);
829 assert(!SemaRef.isSFINAEContext() &&
830 "Can't produce SFINAE diagnostic pointing to temporary attribute");
831
832 if (checkAMDGPUMaxNumWorkGroupsArguments(SemaRef, XExpr, YExpr, ZExpr,
833 TmpAttr))
834 return nullptr;
835
836 return ::new (Context)
837 AMDGPUMaxNumWorkGroupsAttr(Context, CI, XExpr, YExpr, ZExpr);
838}
839
841 const AttributeCommonInfo &CI,
842 Expr *XExpr, Expr *YExpr,
843 Expr *ZExpr) {
844 if (auto *Attr = CreateAMDGPUMaxNumWorkGroupsAttr(CI, XExpr, YExpr, ZExpr))
845 D->addAttr(Attr);
846}
847
849 const ParsedAttr &AL) {
850 Expr *YExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
851 Expr *ZExpr = (AL.getNumArgs() > 2) ? AL.getArgAsExpr(2) : nullptr;
852 addAMDGPUMaxNumWorkGroupsAttr(D, AL, AL.getArgAsExpr(0), YExpr, ZExpr);
853}
854
857 ASTContext &Ctx = getASTContext();
858 QualType BoolTy = Ctx.getLogicalOperationType();
859 SourceLocation Loc = CE->getExprLoc();
860
861 if (!CE->getBuiltinCallee())
862 return *ExpandedPredicates
863 .insert(SemaRef.BuildBoolLiteral(Loc, false).get())
864 .first;
865
866 bool P = false;
867 unsigned BI = CE->getBuiltinCallee();
868 if (Ctx.BuiltinInfo.isAuxBuiltinID(BI))
869 BI = Ctx.BuiltinInfo.getAuxBuiltinID(BI);
870
871 if (BI == AMDGPU::BI__builtin_amdgcn_processor_is) {
872 auto *GFX = dyn_cast<StringLiteral>(CE->getArg(0)->IgnoreParenCasts());
873 if (!GFX) {
874 Diag(Loc, diag::err_amdgcn_processor_is_arg_not_literal);
875 return nullptr;
876 }
877
878 StringRef N = GFX->getString();
879 const TargetInfo &TI = Ctx.getTargetInfo();
880 if (llvm::AMDGPU::parseArchAMDGCN(N) == llvm::AMDGPU::GK_NONE) {
881 Diag(Loc, diag::err_amdgcn_processor_is_arg_invalid_value) << N;
883 llvm::AMDGPU::fillValidArchListAMDGCN(ValidList);
884 if (!ValidList.empty())
885 Diag(Loc, diag::note_amdgcn_processor_is_valid_options)
886 << llvm::join(ValidList, ", ");
887 return nullptr;
888 }
889 if (TI.getTriple().isSPIRV()) {
890 CE->setType(BoolTy);
891 return *ExpandedPredicates.insert(CE).first;
892 }
893
894 P = TI.isProcessorName(N);
895 } else {
896 Expr *Arg = CE->getArg(0);
897 if (!Arg || Arg->getType() != Ctx.BuiltinFnTy) {
898 Diag(Loc, diag::err_amdgcn_is_invocable_arg_invalid_value) << Arg;
899 return nullptr;
900 }
901
902 if (Ctx.getTargetInfo().getTriple().isSPIRV()) {
903 CE->setType(BoolTy);
904 return *ExpandedPredicates.insert(CE).first;
905 }
906
908
909 StringRef RF = Ctx.BuiltinInfo.getRequiredFeatures(FD->getBuiltinID());
910 llvm::StringMap<bool> CF;
911 Ctx.getFunctionFeatureMap(CF, FD);
912
914 }
915
916 return *ExpandedPredicates.insert(SemaRef.BuildBoolLiteral(Loc, P).get())
917 .first;
918}
919
921 return ExpandedPredicates.contains(E);
922}
923
925 PotentiallyUnguardedBuiltinUsers.insert(FD);
926}
927
929 return PotentiallyUnguardedBuiltinUsers.contains(FD);
930}
931
932namespace {
933/// This class implements -Wamdgpu-unguarded-builtin-usage.
934///
935/// This is done with a traversal of the AST of a function that includes a
936/// call to a target specific builtin. Whenever we encounter an \c if of the
937/// form: \c if(__builtin_amdgcn_is_invocable), we consider the then statement
938/// guarded.
939class DiagnoseUnguardedBuiltins : public DynamicRecursiveASTVisitor {
940 // TODO: this could eventually be extended to consider what happens when there
941 // are multiple target architectures specified via target("arch=gfxXXX")
942 // target("arch=gfxyyy") etc., as well as feature disabling via "-XXX".
943 Sema &SemaRef;
944
945 SmallVector<StringRef> TargetFeatures;
947 SmallVector<unsigned> GuardedBuiltins;
948
949 static Expr *FindPredicate(Expr *Cond) {
950 if (auto *CE = dyn_cast<CallExpr>(Cond)) {
951 if (CE->getBuiltinCallee() == AMDGPU::BI__builtin_amdgcn_is_invocable ||
952 CE->getBuiltinCallee() == AMDGPU::BI__builtin_amdgcn_processor_is)
953 return Cond;
954 } else if (auto *UO = dyn_cast<UnaryOperator>(Cond)) {
955 return FindPredicate(UO->getSubExpr());
956 } else if (auto *BO = dyn_cast<BinaryOperator>(Cond)) {
957 if ((Cond = FindPredicate(BO->getLHS())))
958 return Cond;
959 return FindPredicate(BO->getRHS());
960 }
961 return nullptr;
962 }
963
964 bool EnterPredicateGuardedContext(CallExpr *P);
965 void ExitPredicateGuardedContext(bool WasProcessorCheck);
966 bool TraverseGuardedStmt(Stmt *S, CallExpr *P);
967
968public:
969 DiagnoseUnguardedBuiltins(Sema &SemaRef) : SemaRef(SemaRef) {
970 if (auto *TAT = SemaRef.getCurFunctionDecl(true)->getAttr<TargetAttr>()) {
971 // We use the somewhat misnamed x86 accessors because they provide exactly
972 // what we require.
973 TAT->getX86AddedFeatures(TargetFeatures);
974 if (auto GFXIP = TAT->getX86Architecture())
975 CurrentGFXIP.emplace_back(TAT->getLocation(), *GFXIP);
976 }
977 }
978
979 bool TraverseLambdaExpr(LambdaExpr *LE) override {
980 if (SemaRef.AMDGPU().HasPotentiallyUnguardedBuiltinUsage(
981 LE->getCallOperator()))
982 return true; // We have already handled this.
983 return DynamicRecursiveASTVisitor::TraverseLambdaExpr(LE);
984 }
985
986 bool TraverseStmt(Stmt *S) override {
987 if (!S)
988 return true;
990 }
991
992 void IssueDiagnostics(Stmt *S) { TraverseStmt(S); }
993
994 bool TraverseIfStmt(IfStmt *If) override {
995 if (auto *CE = dyn_cast_or_null<CallExpr>(FindPredicate(If->getCond())))
996 return TraverseGuardedStmt(If, CE);
997 return DynamicRecursiveASTVisitor::TraverseIfStmt(If);
998 }
999
1000 bool TraverseCaseStmt(CaseStmt *CS) override {
1001 return TraverseStmt(CS->getSubStmt());
1002 }
1003
1004 bool TraverseConditionalOperator(ConditionalOperator *CO) override {
1005 if (auto *CE = dyn_cast_or_null<CallExpr>(FindPredicate(CO->getCond())))
1006 return TraverseGuardedStmt(CO, CE);
1007 return DynamicRecursiveASTVisitor::TraverseConditionalOperator(CO);
1008 }
1009
1010 bool VisitAsmStmt(AsmStmt *ASM) override;
1011 bool VisitCallExpr(CallExpr *CE) override;
1012};
1013
1014bool DiagnoseUnguardedBuiltins::EnterPredicateGuardedContext(CallExpr *P) {
1015 bool IsProcessorCheck =
1016 P->getBuiltinCallee() == AMDGPU::BI__builtin_amdgcn_processor_is;
1017
1018 if (IsProcessorCheck) {
1019 StringRef G = cast<clang::StringLiteral>(P->getArg(0))->getString();
1020 // TODO: handle generic ISAs.
1021 if (!CurrentGFXIP.empty() && G != CurrentGFXIP.back().second) {
1022 SemaRef.Diag(P->getExprLoc(),
1023 diag::err_amdgcn_conflicting_is_processor_options)
1024 << P;
1025 SemaRef.Diag(CurrentGFXIP.back().first,
1026 diag::note_amdgcn_previous_is_processor_guard);
1027 }
1028 CurrentGFXIP.emplace_back(P->getExprLoc(), G);
1029 } else {
1030 auto *FD = cast<FunctionDecl>(
1031 cast<DeclRefExpr>(P->getArg(0))->getReferencedDeclOfCallee());
1032 GuardedBuiltins.push_back(FD->getBuiltinID());
1033 }
1034
1035 return IsProcessorCheck;
1036}
1037
1038void DiagnoseUnguardedBuiltins::ExitPredicateGuardedContext(bool WasProcCheck) {
1039 if (WasProcCheck)
1040 CurrentGFXIP.pop_back();
1041 else
1042 GuardedBuiltins.pop_back();
1043}
1044
1045inline std::pair<Stmt *, Stmt *> GetTraversalOrder(Stmt *S) {
1046 std::pair<Stmt *, Stmt *> Ordered;
1047 Expr *Condition = nullptr;
1048
1049 if (auto *CO = dyn_cast<ConditionalOperator>(S)) {
1050 Condition = CO->getCond();
1051 Ordered = {CO->getTrueExpr(), CO->getFalseExpr()};
1052 } else if (auto *If = dyn_cast<IfStmt>(S)) {
1053 Condition = If->getCond();
1054 Ordered = {If->getThen(), If->getElse()};
1055 }
1056
1057 if (auto *UO = dyn_cast<UnaryOperator>(Condition))
1058 if (UO->getOpcode() == UnaryOperatorKind::UO_LNot)
1059 std::swap(Ordered.first, Ordered.second);
1060
1061 return Ordered;
1062}
1063
1064bool DiagnoseUnguardedBuiltins::TraverseGuardedStmt(Stmt *S, CallExpr *P) {
1065 assert(S && "Unexpected missing Statement!");
1066 assert(P && "Unexpected missing Predicate!");
1067
1068 auto [Guarded, Unguarded] = GetTraversalOrder(S);
1069
1070 bool WasProcessorCheck = EnterPredicateGuardedContext(P);
1071
1072 bool Continue = TraverseStmt(Guarded);
1073
1074 ExitPredicateGuardedContext(WasProcessorCheck);
1075
1076 return Continue && TraverseStmt(Unguarded);
1077}
1078
1079bool DiagnoseUnguardedBuiltins::VisitAsmStmt(AsmStmt *ASM) {
1080 // TODO: should we check if the ASM is valid for the target? Can we?
1081 if (!CurrentGFXIP.empty())
1082 return true;
1083
1084 std::string S = ASM->generateAsmString(SemaRef.getASTContext());
1085 SemaRef.Diag(ASM->getAsmLoc(), diag::warn_amdgcn_unguarded_asm_stmt) << S;
1086 SemaRef.Diag(ASM->getAsmLoc(), diag::note_amdgcn_unguarded_asm_silence) << S;
1087
1088 return true;
1089}
1090
1091bool DiagnoseUnguardedBuiltins::VisitCallExpr(CallExpr *CE) {
1092 unsigned ID = CE->getBuiltinCallee();
1093 Builtin::Context &BInfo = SemaRef.getASTContext().BuiltinInfo;
1094
1095 if (!ID)
1096 return true;
1097 if (!BInfo.isTSBuiltin(ID))
1098 return true;
1099 if (ID == AMDGPU::BI__builtin_amdgcn_processor_is ||
1100 ID == AMDGPU::BI__builtin_amdgcn_is_invocable)
1101 return true;
1102 if (llvm::find(GuardedBuiltins, ID) != GuardedBuiltins.end())
1103 return true;
1104
1105 StringRef FL(BInfo.getRequiredFeatures(ID));
1106 llvm::StringMap<bool> FeatureMap;
1107 if (CurrentGFXIP.empty()) {
1108 for (auto &&F : TargetFeatures)
1109 FeatureMap[F] = true;
1110 for (auto &&GID : GuardedBuiltins)
1111 for (auto &&F : llvm::split(BInfo.getRequiredFeatures(GID), ','))
1112 FeatureMap[F] = true;
1113 } else {
1114 static const llvm::Triple AMDGCN(llvm::Triple::amdgpu,
1115 llvm::Triple::NoSubArch, llvm::Triple::AMD,
1116 llvm::Triple::AMDHSA);
1117 llvm::AMDGPU::fillAMDGPUFeatureMap(CurrentGFXIP.back().second, AMDGCN,
1118 FeatureMap);
1119 }
1120
1121 FunctionDecl *BI = CE->getDirectCallee();
1122 SourceLocation BICallLoc = CE->getExprLoc();
1123 if (Builtin::evaluateRequiredTargetFeatures(FL, FeatureMap)) {
1124 SemaRef.Diag(BICallLoc, diag::warn_amdgcn_unguarded_builtin) << BI;
1125 SemaRef.Diag(BICallLoc, diag::note_amdgcn_unguarded_builtin_silence) << BI;
1126 } else {
1127 StringRef GFXIP = CurrentGFXIP.empty() ? "" : CurrentGFXIP.back().second;
1128 SemaRef.Diag(BICallLoc, diag::err_amdgcn_incompatible_builtin)
1129 << BI << FL << !CurrentGFXIP.empty() << GFXIP;
1130 if (!CurrentGFXIP.empty())
1131 SemaRef.Diag(CurrentGFXIP.back().first,
1132 diag::note_amdgcn_previous_is_processor_guard);
1133 }
1134
1135 return true;
1136}
1137} // Unnamed namespace
1138
1140 DiagnoseUnguardedBuiltins(SemaRef).IssueDiagnostics(FD->getBody());
1141}
1142
1144 ASTContext &Ctx = getASTContext();
1145 llvm::Triple TT = Ctx.getTargetInfo().getTriple();
1146 const Type *BaseTy = Ty->getPointeeOrArrayElementType();
1147
1148 if (Ctx.getTargetInfo().getTriple().isSPIRV()) {
1149 // The AMDGPU named barrier type requires special handling in the back-end
1150 // and is not supported for SPIR-V
1151 if (BaseTy->isAMDGPUNamedBarrierType()) {
1152 SemaRef.Diag(Loc, diag::err_amdgpu_target_ext_type_unsupported)
1153 << Ty << TT.str();
1154 return false;
1155 }
1156 }
1157
1158 return true;
1159}
1160
1162 for (FieldDecl *FD : R->fields()) {
1163 QualType FDTy = FD->getType();
1165 return FD;
1166 }
1167
1168 return nullptr;
1169}
1170
1172 ASTContext &Context = getASTContext();
1173 if (R->isInvalidDecl())
1174 return;
1175
1176 if (!Context.getTargetInfo().hasAMDGPUTypes() &&
1177 (!Context.getAuxTargetInfo() ||
1178 !Context.getAuxTargetInfo()->hasAMDGPUTypes()))
1179 return;
1180
1181 bool IsWrapper = false;
1182 std::function<void()> DiagWrapperNote;
1183
1184 // First, check if this is a named barrier wrapper by virtue of the class
1185 // declaring a named barrier field. This covers both C and C++.
1186 if (FieldDecl *NamedBarrField = getNamedBarrierField(R)) {
1187 // If this record contains a named barrier field, it must have only one
1188 // field.
1189 if (R->getNumFields() > 1) {
1190 SemaRef.Diag(NamedBarrField->getLocation(),
1191 diag::err_amdgpu_invalid_field_not_a_wrapper)
1192 << NamedBarrField->getType();
1193 SemaRef.Diag(
1194 R->getLocation(),
1195 diag::note_amdgpu_not_a_named_barrier_wrapper_too_many_fields)
1196 << R->getDeclName();
1197 return;
1198 }
1199
1200 IsWrapper = true;
1201 DiagWrapperNote = [this, R, NamedBarrField]() {
1202 SemaRef.Diag(NamedBarrField->getLocation(),
1203 diag::note_amdgpu_named_barrier_reason_field)
1204 << R->getDeclName() << NamedBarrField->getDeclName();
1205 };
1206 }
1207
1208 // Then, for C++ classes, check if this is a named barrier wrapper by virtue
1209 // of inheriting one.
1210 const auto *CxxR = dyn_cast<CXXRecordDecl>(R);
1211 if (CxxR && !IsWrapper) {
1212 for (CXXBaseSpecifier BS : CxxR->bases()) {
1213 const RecordDecl *Base = BS.getType()->getAsRecordDecl();
1214 if (!Base || !Base->hasAttr<AMDGPUNamedBarrierWrapperAttr>())
1215 continue;
1216
1217 IsWrapper = true;
1218 DiagWrapperNote = [this, BS, R]() {
1219 // Print using the CXXBaseSpecifier type as it includes the template
1220 // parameters.
1221 SemaRef.Diag(BS.getBeginLoc(),
1222 diag::note_amdgpu_named_barrier_reason_inherited)
1223 << R->getDeclName() << BS.getType();
1224 };
1225 }
1226 }
1227
1228 if (!IsWrapper)
1229 return;
1230
1231 // Set the attribute even if the wrapper may be found to be invalid later.
1232 R->addAttr(
1233 AMDGPUNamedBarrierWrapperAttr::CreateImplicit(Context, SourceRange()));
1234
1235 // This is a wrapper CXXRecordDecl, it must have a C++11 standard layout.
1236 if (CxxR && !CxxR->isCXX11StandardLayout()) {
1237 SemaRef.Diag(R->getLocation(),
1238 diag::err_amdgpu_named_barrier_wrapper_non_standard_layout)
1239 << R->getDeclName();
1240 assert(DiagWrapperNote &&
1241 "IsWrapper is set but no context diagnostic provided");
1242 DiagWrapperNote();
1243 }
1244}
1245} // namespace clang
This file declares semantic analysis functions specific to AMDGPU.
Enumerates target-specific builtins in their own namespaces within namespace clang.
APSInt & getInt()
Definition APValue.h:573
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
Builtin::Context & BuiltinInfo
Definition ASTContext.h:854
CanQualType getLogicalOperationType() const
The result type of logical operations, '<', '>', '!=', etc.
CanQualType BuiltinFnTy
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:971
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
unsigned getTargetAddressSpace(LangAS AS) const
bool isInvalid() const
Definition Ownership.h:167
static std::unique_ptr< AtomicScopeModel > create(AtomicScopeModelKind K)
Create an atomic scope model by AtomicScopeModelKind.
Definition SyncScope.h:299
Attr - This represents one attribute.
Definition Attr.h:47
SourceLocation getLocation() const
Definition Attr.h:100
SourceLocation getLoc() const
llvm::SmallString< 64 > getQuotedName(unsigned ID) const
Return the identifier name for the specified builtin inside single quotes for a diagnostic,...
Definition Builtins.cpp:99
bool isAuxBuiltinID(unsigned ID) const
Return true if the builtin ID belongs exclusively to the AuxTarget, and false if it belongs to both p...
Definition Builtins.h:445
unsigned getAuxBuiltinID(unsigned ID) const
Return real builtin ID (i.e.
Definition Builtins.h:451
const char * getRequiredFeatures(unsigned ID) const
Definition Builtins.cpp:118
Represents a base class of a C++ class.
Definition DeclCXX.h:146
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:3012
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3216
SourceLocation getBeginLoc() const
Definition Expr.h:3346
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
Definition Expr.cpp:1624
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3203
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void addAttr(Attr *A)
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
This represents one expression.
Definition Expr.h:114
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3134
void setType(QualType t)
Definition Expr.h:147
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:179
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3125
Decl * getReferencedDeclOfCallee()
Definition Expr.cpp:1578
bool EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, ConstantExprKind Kind=ConstantExprKind::Normal) const
Evaluate an expression that is required to be a constant expression.
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:225
std::optional< std::string > tryEvaluateString(ASTContext &Ctx) const
If the current Expr can be evaluated to a pointer to a null-terminated constant string,...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:146
Represents a member of a struct/union/class.
Definition Decl.h:3311
Represents a function declaration or definition.
Definition Decl.h:2071
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3284
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition ParsedAttr.h:371
Expr * getArgAsExpr(unsigned Arg) const
Definition ParsedAttr.h:383
bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at least as many args as Num.
bool checkAtMostNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at most as many args as Num.
A (possibly-)qualified type.
Definition TypeBase.h:938
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8578
Represents a struct/union/class.
Definition Decl.h:4476
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
void handleAMDGPUMaxNumWorkGroupsAttr(Decl *D, const ParsedAttr &AL)
void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size attribute to a particular declar...
bool checkCoopAtomicFunctionCall(CallExpr *TheCall, bool IsStore)
bool HasPotentiallyUnguardedBuiltinUsage(FunctionDecl *FD) const
void handleAMDGPUFlatWorkGroupSizeAttr(Decl *D, const ParsedAttr &AL)
bool checkAVLoadStore(CallExpr *TheCall, bool IsStore)
bool checkAtomicMonitorLoad(CallExpr *TheCall)
bool checkAtomicOrderingCABIArg(Expr *E, bool MayLoad, bool MayStore)
Emits a diagnostic if the E is not an atomic ordering encoded in the C ABI format,...
void handleAMDGPUNumSGPRAttr(Decl *D, const ParsedAttr &AL)
AMDGPUMaxNumWorkGroupsAttr * CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr)
Create an AMDGPUMaxNumWorkGroupsAttr attribute.
Expr * ExpandAMDGPUPredicateBuiltIn(Expr *CE)
Expand a valid use of the feature identification builtins into its corresponding sequence of instruct...
AMDGPUWavesPerEUAttr * CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
bool CheckAMDGCNBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall)
void DiagnoseUnguardedBuiltinUsage(FunctionDecl *FD)
bool checkAMDGPUTypeSupport(QualType Ty, SourceLocation Loc)
Check if Ty is supported on this AMDGPU target.
void handleAMDGPUNumVGPRAttr(Decl *D, const ParsedAttr &AL)
AMDGPUFlatWorkGroupSizeAttr * CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
void AddPotentiallyUnguardedBuiltinUser(FunctionDecl *FD)
Diagnose unguarded usages of AMDGPU builtins and recommend guarding with __builtin_amdgcn_is_invocabl...
bool checkMovDPPFunctionCall(CallExpr *TheCall, unsigned NumArgs, unsigned NumDataArgs)
void handleAMDGPUWavesPerEUAttr(Decl *D, const ParsedAttr &AL)
void checkNamedBarrierWrapper(RecordDecl *R)
Called in ActOnFields - whenever a C/C++ Record is being finalized.
bool IsPredicate(Expr *E) const
void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a particular declaration.
void addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr)
addAMDGPUMaxNumWorkGroupsAttr - Adds an amdgpu_max_num_work_groups attribute to a particular declarat...
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:862
ASTContext & Context
Definition Sema.h:1331
bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, UnexpandedParameterPackContext UPPC)
If the given type contains an unexpanded parameter pack, diagnose the error.
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)
If Expr is a valid integer constant, get the value of the integer expression and return success or fa...
Definition Sema.h:5042
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
Exposes information about the current target.
Definition TargetInfo.h:228
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
virtual bool isProcessorName(StringRef Name) const
Returns true if the target's processor is compatible with the processor named by Name,...
The base class of the type hierarchy.
Definition TypeBase.h:1879
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition TypeBase.h:9391
bool isAMDGPUNamedBarrierTypeOrWrapper() const
Check if the type is the AMDGPU named barrier type/a RecordType of a named barrier wrapper,...
Definition Type.cpp:5690
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool isAMDGPUNamedBarrierType() const
Check if the type is the AMDGPU named barrier type, or an array thereof.
Definition Type.cpp:5686
Defines the clang::TargetInfo interface.
bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)
Returns true if the required target features of a builtin function are enabled.
bool LE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1512
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
static FieldDecl * getNamedBarrierField(const RecordDecl *R)
static bool checkScopeAsInt(SemaAMDGPU &S, Expr *Scope)
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Result
The result type of a method or function.
Definition TypeBase.h:906
static bool checkAMDGPUMaxNumWorkGroupsArguments(Sema &S, Expr *XExpr, Expr *YExpr, Expr *ZExpr, const AMDGPUMaxNumWorkGroupsAttr &Attr)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr, const AMDGPUFlatWorkGroupSizeAttr &Attr)
static bool checkGlobalOrFlatPointerArg(SemaAMDGPU &S, CallExpr *TheCall)
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr, const AMDGPUWavesPerEUAttr &Attr)
int const char * function
Definition c++config.h:31
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 __builtin_riscv_mqwacc_i64 uint8_t
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:667
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:669