clang 22.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
17#include "clang/Sema/Sema.h"
18#include "llvm/Support/AtomicOrdering.h"
19#include <cstdint>
20
21namespace clang {
22
24
26 CallExpr *TheCall) {
27 // position of memory order and scope arguments in the builtin
28 unsigned OrderIndex, ScopeIndex;
29
30 const auto *FD = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
31 assert(FD && "AMDGPU builtins should not be used outside of a function");
32 llvm::StringMap<bool> CallerFeatureMap;
33 getASTContext().getFunctionFeatureMap(CallerFeatureMap, FD);
34 bool HasGFX950Insts =
35 Builtin::evaluateRequiredTargetFeatures("gfx950-insts", CallerFeatureMap);
36
37 switch (BuiltinID) {
38 case AMDGPU::BI__builtin_amdgcn_raw_ptr_buffer_load_lds:
39 case AMDGPU::BI__builtin_amdgcn_struct_ptr_buffer_load_lds:
40 case AMDGPU::BI__builtin_amdgcn_load_to_lds:
41 case AMDGPU::BI__builtin_amdgcn_global_load_lds: {
42 constexpr const int SizeIdx = 2;
43 llvm::APSInt Size;
44 Expr *ArgExpr = TheCall->getArg(SizeIdx);
45 [[maybe_unused]] ExprResult R =
47 assert(!R.isInvalid());
48 switch (Size.getSExtValue()) {
49 case 1:
50 case 2:
51 case 4:
52 return false;
53 case 12:
54 case 16: {
55 if (HasGFX950Insts)
56 return false;
57 [[fallthrough]];
58 }
59 default:
60 Diag(ArgExpr->getExprLoc(), diag::err_amdgcn_load_lds_size_invalid_value)
61 << ArgExpr->getSourceRange();
62 Diag(ArgExpr->getExprLoc(), diag::note_amdgcn_load_lds_size_valid_value)
63 << HasGFX950Insts << ArgExpr->getSourceRange();
64 return true;
65 }
66 }
67 case AMDGPU::BI__builtin_amdgcn_get_fpenv:
68 case AMDGPU::BI__builtin_amdgcn_set_fpenv:
69 return false;
70 case AMDGPU::BI__builtin_amdgcn_atomic_inc32:
71 case AMDGPU::BI__builtin_amdgcn_atomic_inc64:
72 case AMDGPU::BI__builtin_amdgcn_atomic_dec32:
73 case AMDGPU::BI__builtin_amdgcn_atomic_dec64:
74 OrderIndex = 2;
75 ScopeIndex = 3;
76 break;
77 case AMDGPU::BI__builtin_amdgcn_fence:
78 OrderIndex = 0;
79 ScopeIndex = 1;
80 break;
81 case AMDGPU::BI__builtin_amdgcn_mov_dpp:
82 return checkMovDPPFunctionCall(TheCall, 5, 1);
83 case AMDGPU::BI__builtin_amdgcn_mov_dpp8:
84 return checkMovDPPFunctionCall(TheCall, 2, 1);
85 case AMDGPU::BI__builtin_amdgcn_update_dpp:
86 return checkMovDPPFunctionCall(TheCall, 6, 2);
87 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp8:
88 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp8:
89 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_bf8:
90 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_bf8:
91 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f16_fp4:
92 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_bf16_fp4:
93 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp8:
94 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_bf8:
95 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk8_f32_fp4:
96 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_fp6:
97 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_fp6:
98 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f16_bf6:
99 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_bf16_bf6:
100 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_fp6:
101 case AMDGPU::BI__builtin_amdgcn_cvt_scale_pk16_f32_bf6:
102 return SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 7);
103 default:
104 return false;
105 }
106
107 ExprResult Arg = TheCall->getArg(OrderIndex);
108 auto ArgExpr = Arg.get();
109 Expr::EvalResult ArgResult;
110
111 if (!ArgExpr->EvaluateAsInt(ArgResult, getASTContext()))
112 return Diag(ArgExpr->getExprLoc(), diag::err_typecheck_expect_int)
113 << ArgExpr->getType();
114 auto Ord = ArgResult.Val.getInt().getZExtValue();
115
116 // Check validity of memory ordering as per C11 / C++11's memody model.
117 // Only fence needs check. Atomic dec/inc allow all memory orders.
118 if (!llvm::isValidAtomicOrderingCABI(Ord))
119 return Diag(ArgExpr->getBeginLoc(),
120 diag::warn_atomic_op_has_invalid_memory_order)
121 << 0 << ArgExpr->getSourceRange();
122 switch (static_cast<llvm::AtomicOrderingCABI>(Ord)) {
123 case llvm::AtomicOrderingCABI::relaxed:
124 case llvm::AtomicOrderingCABI::consume:
125 if (BuiltinID == AMDGPU::BI__builtin_amdgcn_fence)
126 return Diag(ArgExpr->getBeginLoc(),
127 diag::warn_atomic_op_has_invalid_memory_order)
128 << 0 << ArgExpr->getSourceRange();
129 break;
130 case llvm::AtomicOrderingCABI::acquire:
131 case llvm::AtomicOrderingCABI::release:
132 case llvm::AtomicOrderingCABI::acq_rel:
133 case llvm::AtomicOrderingCABI::seq_cst:
134 break;
135 }
136
137 Arg = TheCall->getArg(ScopeIndex);
138 ArgExpr = Arg.get();
139 Expr::EvalResult ArgResult1;
140 // Check that sync scope is a constant literal
141 if (!ArgExpr->EvaluateAsConstantExpr(ArgResult1, getASTContext()))
142 return Diag(ArgExpr->getExprLoc(), diag::err_expr_not_string_literal)
143 << ArgExpr->getType();
144
145 return false;
146}
147
148bool SemaAMDGPU::checkMovDPPFunctionCall(CallExpr *TheCall, unsigned NumArgs,
149 unsigned NumDataArgs) {
150 assert(NumDataArgs <= 2);
151 if (SemaRef.checkArgCountRange(TheCall, NumArgs, NumArgs))
152 return true;
153 Expr *Args[2];
154 QualType ArgTys[2];
155 for (unsigned I = 0; I != NumDataArgs; ++I) {
156 Args[I] = TheCall->getArg(I);
157 ArgTys[I] = Args[I]->getType();
158 // TODO: Vectors can also be supported.
159 if (!ArgTys[I]->isArithmeticType() || ArgTys[I]->isAnyComplexType()) {
160 SemaRef.Diag(Args[I]->getBeginLoc(),
161 diag::err_typecheck_cond_expect_int_float)
162 << ArgTys[I] << Args[I]->getSourceRange();
163 return true;
164 }
165 }
166 if (NumDataArgs < 2)
167 return false;
168
169 if (getASTContext().hasSameUnqualifiedType(ArgTys[0], ArgTys[1]))
170 return false;
171
172 if (((ArgTys[0]->isUnsignedIntegerType() &&
173 ArgTys[1]->isSignedIntegerType()) ||
174 (ArgTys[0]->isSignedIntegerType() &&
175 ArgTys[1]->isUnsignedIntegerType())) &&
176 getASTContext().getTypeSize(ArgTys[0]) ==
177 getASTContext().getTypeSize(ArgTys[1]))
178 return false;
179
180 SemaRef.Diag(Args[1]->getBeginLoc(),
181 diag::err_typecheck_call_different_arg_types)
182 << ArgTys[0] << ArgTys[1];
183 return true;
184}
185
186static bool
188 const AMDGPUFlatWorkGroupSizeAttr &Attr) {
189 // Accept template arguments for now as they depend on something else.
190 // We'll get to check them when they eventually get instantiated.
191 if (MinExpr->isValueDependent() || MaxExpr->isValueDependent())
192 return false;
193
194 uint32_t Min = 0;
195 if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0))
196 return true;
197
198 uint32_t Max = 0;
199 if (!S.checkUInt32Argument(Attr, MaxExpr, Max, 1))
200 return true;
201
202 if (Min == 0 && Max != 0) {
203 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
204 << &Attr << 0;
205 return true;
206 }
207 if (Min > Max) {
208 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
209 << &Attr << 1;
210 return true;
211 }
212
213 return false;
214}
215
216AMDGPUFlatWorkGroupSizeAttr *
218 Expr *MinExpr, Expr *MaxExpr) {
219 ASTContext &Context = getASTContext();
220 AMDGPUFlatWorkGroupSizeAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
221
222 if (checkAMDGPUFlatWorkGroupSizeArguments(SemaRef, MinExpr, MaxExpr, TmpAttr))
223 return nullptr;
224 return ::new (Context)
225 AMDGPUFlatWorkGroupSizeAttr(Context, CI, MinExpr, MaxExpr);
226}
227
229 const AttributeCommonInfo &CI,
230 Expr *MinExpr, Expr *MaxExpr) {
231 if (auto *Attr = CreateAMDGPUFlatWorkGroupSizeAttr(CI, MinExpr, MaxExpr))
232 D->addAttr(Attr);
233}
234
236 const ParsedAttr &AL) {
237 Expr *MinExpr = AL.getArgAsExpr(0);
238 Expr *MaxExpr = AL.getArgAsExpr(1);
239
240 addAMDGPUFlatWorkGroupSizeAttr(D, AL, MinExpr, MaxExpr);
241}
242
243static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr,
244 Expr *MaxExpr,
245 const AMDGPUWavesPerEUAttr &Attr) {
246 if (S.DiagnoseUnexpandedParameterPack(MinExpr) ||
247 (MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr)))
248 return true;
249
250 // Accept template arguments for now as they depend on something else.
251 // We'll get to check them when they eventually get instantiated.
252 if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent()))
253 return false;
254
255 uint32_t Min = 0;
256 if (!S.checkUInt32Argument(Attr, MinExpr, Min, 0))
257 return true;
258
259 uint32_t Max = 0;
260 if (MaxExpr && !S.checkUInt32Argument(Attr, MaxExpr, Max, 1))
261 return true;
262
263 if (Min == 0 && Max != 0) {
264 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
265 << &Attr << 0;
266 return true;
267 }
268 if (Max != 0 && Min > Max) {
269 S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
270 << &Attr << 1;
271 return true;
272 }
273
274 return false;
275}
276
277AMDGPUWavesPerEUAttr *
279 Expr *MinExpr, Expr *MaxExpr) {
280 ASTContext &Context = getASTContext();
281 AMDGPUWavesPerEUAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
282
283 if (checkAMDGPUWavesPerEUArguments(SemaRef, MinExpr, MaxExpr, TmpAttr))
284 return nullptr;
285
286 return ::new (Context) AMDGPUWavesPerEUAttr(Context, CI, MinExpr, MaxExpr);
287}
288
290 Expr *MinExpr, Expr *MaxExpr) {
291 if (auto *Attr = CreateAMDGPUWavesPerEUAttr(CI, MinExpr, MaxExpr))
292 D->addAttr(Attr);
293}
294
297 return;
298
299 Expr *MinExpr = AL.getArgAsExpr(0);
300 Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
301
302 addAMDGPUWavesPerEUAttr(D, AL, MinExpr, MaxExpr);
303}
304
306 uint32_t NumSGPR = 0;
307 Expr *NumSGPRExpr = AL.getArgAsExpr(0);
308 if (!SemaRef.checkUInt32Argument(AL, NumSGPRExpr, NumSGPR))
309 return;
310
311 D->addAttr(::new (getASTContext())
312 AMDGPUNumSGPRAttr(getASTContext(), AL, NumSGPR));
313}
314
316 uint32_t NumVGPR = 0;
317 Expr *NumVGPRExpr = AL.getArgAsExpr(0);
318 if (!SemaRef.checkUInt32Argument(AL, NumVGPRExpr, NumVGPR))
319 return;
320
321 D->addAttr(::new (getASTContext())
322 AMDGPUNumVGPRAttr(getASTContext(), AL, NumVGPR));
323}
324
325static bool
327 Expr *ZExpr,
328 const AMDGPUMaxNumWorkGroupsAttr &Attr) {
329 if (S.DiagnoseUnexpandedParameterPack(XExpr) ||
330 (YExpr && S.DiagnoseUnexpandedParameterPack(YExpr)) ||
331 (ZExpr && S.DiagnoseUnexpandedParameterPack(ZExpr)))
332 return true;
333
334 // Accept template arguments for now as they depend on something else.
335 // We'll get to check them when they eventually get instantiated.
336 if (XExpr->isValueDependent() || (YExpr && YExpr->isValueDependent()) ||
337 (ZExpr && ZExpr->isValueDependent()))
338 return false;
339
340 uint32_t NumWG = 0;
341 Expr *Exprs[3] = {XExpr, YExpr, ZExpr};
342 for (int i = 0; i < 3; i++) {
343 if (Exprs[i]) {
344 if (!S.checkUInt32Argument(Attr, Exprs[i], NumWG, i,
345 /*StrictlyUnsigned=*/true))
346 return true;
347 if (NumWG == 0) {
348 S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
349 << &Attr << Exprs[i]->getSourceRange();
350 return true;
351 }
352 }
353 }
354
355 return false;
356}
357
359 const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr) {
360 ASTContext &Context = getASTContext();
361 AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr);
362
363 if (checkAMDGPUMaxNumWorkGroupsArguments(SemaRef, XExpr, YExpr, ZExpr,
364 TmpAttr))
365 return nullptr;
366
367 return ::new (Context)
368 AMDGPUMaxNumWorkGroupsAttr(Context, CI, XExpr, YExpr, ZExpr);
369}
370
372 const AttributeCommonInfo &CI,
373 Expr *XExpr, Expr *YExpr,
374 Expr *ZExpr) {
375 if (auto *Attr = CreateAMDGPUMaxNumWorkGroupsAttr(CI, XExpr, YExpr, ZExpr))
376 D->addAttr(Attr);
377}
378
380 const ParsedAttr &AL) {
381 Expr *YExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
382 Expr *ZExpr = (AL.getNumArgs() > 2) ? AL.getArgAsExpr(2) : nullptr;
383 addAMDGPUMaxNumWorkGroupsAttr(D, AL, AL.getArgAsExpr(0), YExpr, ZExpr);
384}
385
386} // namespace clang
const Decl * D
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:489
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
void getFunctionFeatureMap(llvm::StringMap< bool > &FeatureMap, const FunctionDecl *) const
PtrTy get() const
Definition: Ownership.h:171
bool isInvalid() const
Definition: Ownership.h:167
Attr - This represents one attribute.
Definition: Attr.h:44
SourceLocation getLocation() const
Definition: Attr.h:97
SourceLocation getLoc() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2879
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3083
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
This represents one expression.
Definition: Expr.h:112
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:177
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:273
QualType getType() const
Definition: Expr.h:144
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.
Definition: ParsedAttr.cpp:293
bool checkAtMostNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at most as many args as Num.
Definition: ParsedAttr.cpp:298
A (possibly-)qualified type.
Definition: TypeBase.h:937
void handleAMDGPUMaxNumWorkGroupsAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaAMDGPU.cpp:379
void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size attribute to a particular declar...
Definition: SemaAMDGPU.cpp:228
SemaAMDGPU(Sema &S)
Definition: SemaAMDGPU.cpp:23
void handleAMDGPUFlatWorkGroupSizeAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaAMDGPU.cpp:235
void handleAMDGPUNumSGPRAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaAMDGPU.cpp:305
AMDGPUMaxNumWorkGroupsAttr * CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, Expr *XExpr, Expr *YExpr, Expr *ZExpr)
Create an AMDGPUMaxNumWorkGroupsAttr attribute.
Definition: SemaAMDGPU.cpp:358
AMDGPUWavesPerEUAttr * CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
Definition: SemaAMDGPU.cpp:278
void handleAMDGPUNumVGPRAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaAMDGPU.cpp:315
AMDGPUFlatWorkGroupSizeAttr * CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
Definition: SemaAMDGPU.cpp:217
bool checkMovDPPFunctionCall(CallExpr *TheCall, unsigned NumArgs, unsigned NumDataArgs)
Definition: SemaAMDGPU.cpp:148
void handleAMDGPUWavesPerEUAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaAMDGPU.cpp:295
bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall)
Definition: SemaAMDGPU.cpp:25
void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a particular declaration.
Definition: SemaAMDGPU.cpp:289
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...
Definition: SemaAMDGPU.cpp:371
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:61
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
Definition: Sema.cpp:1647
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:4819
bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount)
Checks that a call expression's argument count is in the desired range.
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=AllowFoldKind::No)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
Definition: SemaExpr.cpp:17422
bool BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, bool RangeIsError=true)
BuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr TheCall is a constant express...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:334
bool evaluateRequiredTargetFeatures(llvm::StringRef RequiredFatures, const llvm::StringMap< bool > &TargetFetureMap)
Returns true if the required target features of a builtin function are enabled.
The JSON file list parser is used to communicate input to InstallAPI.
static bool checkAMDGPUMaxNumWorkGroupsArguments(Sema &S, Expr *XExpr, Expr *YExpr, Expr *ZExpr, const AMDGPUMaxNumWorkGroupsAttr &Attr)
Definition: SemaAMDGPU.cpp:326
static bool checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr, const AMDGPUFlatWorkGroupSizeAttr &Attr)
Definition: SemaAMDGPU.cpp:187
static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr, const AMDGPUWavesPerEUAttr &Attr)
Definition: SemaAMDGPU.cpp:243
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:647