LLVM 24.0.0git
VerifierAMDGPU.cpp
Go to the documentation of this file.
1//===-- VerifierAMDGPU.cpp - AMDGPU-specific IR verification ---------------==//
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 contains AMDGPU-specific IR verification logic that was extracted
10// from Verifier.cpp for code organization purposes only. These checks are
11// always compiled and linked as part of LLVMCore — this is not a target-
12// dependent IR verifier, which would require a different design.
13//
14// This file should only contain checks for AMDGPU-specific IR constructs
15// (e.g. amdgcn intrinsics, AMDGPU address spaces). It must not contain
16// checks for generic IR that might behave differently under AMDGPU.
17//
18//===----------------------------------------------------------------------===//
19
20#include "VerifierInternal.h"
22#include "llvm/IR/CallingConv.h"
23#include "llvm/IR/Constants.h"
25#include "llvm/IR/Function.h"
28#include "llvm/IR/IntrinsicsAMDGPU.h"
30
31using namespace llvm;
32
33#define Check(C, ...) \
34 do { \
35 if (!(C)) { \
36 VS.CheckFailed(__VA_ARGS__); \
37 return; \
38 } \
39 } while (false)
40
43 const MDNode *Op) {
44 StringRef FlagName = ID->getString();
45 if (!FlagName.consume_front("amdgpu."))
46 return;
47
48 if (FlagName == "buffer.oob.mode" || FlagName == "tbuffer.oob.mode") {
49 Check(MFB == Module::Max,
50 "'" + ID->getString() +
51 "' module flag must use 'max' merge behaviour");
54 Check(Value, "'" + ID->getString() +
55 "' module flag must have a constant integer value");
56 Check(Value->getZExtValue() <= 2,
57 "'" + ID->getString() + "' module flag must be 0, 1, or 2");
58 return;
59 }
60
61 if (FlagName == "xnack" || FlagName == "sramecc") {
62 Check(MFB == Module::Error,
63 "'" + ID->getString() +
64 "' module flag must use 'error' merge behaviour");
67 Check(Value, "'" + ID->getString() +
68 "' module flag must have a constant integer value");
69 Check(Value->getZExtValue() <= 1,
70 "'" + ID->getString() + "' module flag must be 0 or 1");
71 return;
72 }
73}
74
75// Verify that when a function has !reqd_work_group_size metadata, it also has
76// an amdgpu-flat-work-group-size attribute that matches the product of the
77// reqd_work_group_size operands.
79 const Function &F) {
80 // This is not required for other targets so we only check for AMDGPU.
81 if (!VS.TT.isAMDGPU())
82 return;
83
84 MDNode *ReqdWorkGroupSize = F.getMetadata("reqd_work_group_size");
85 if (!ReqdWorkGroupSize || ReqdWorkGroupSize->getNumOperands() != 3)
86 return;
87
88 uint64_t Product = 1;
89 for (const MDOperand &Op : ReqdWorkGroupSize->operands()) {
91 if (!C || C->getValue().getActiveBits() > 64)
92 return;
93 uint64_t Dim = C->getZExtValue();
94 if (Dim != 0 && Product > std::numeric_limits<uint64_t>::max() / Dim)
95 return;
96 Product *= Dim;
97 }
98
99 Attribute FlatWorkGroupSize = F.getFnAttribute("amdgpu-flat-work-group-size");
100 if (!FlatWorkGroupSize.isValid()) {
101 VS.CheckFailed("reqd_work_group_size requires amdgpu-flat-work-group-size",
102 &F, ReqdWorkGroupSize);
103 return;
104 }
105
106 if (!FlatWorkGroupSize.isStringAttribute()) {
107 VS.CheckFailed("amdgpu-flat-work-group-size must be a string attribute",
108 &F);
109 return;
110 }
111
112 StringRef AttrValue = FlatWorkGroupSize.getValueAsString();
113 std::pair<StringRef, StringRef> Values = AttrValue.split(',');
114 uint64_t Min = 0;
115 uint64_t Max = 0;
116 bool Parsed = !Values.second.contains(',') &&
117 llvm::to_integer(Values.first.trim(), Min) &&
118 llvm::to_integer(Values.second.trim(), Max);
119 if (!Parsed) {
120 VS.CheckFailed("amdgpu-flat-work-group-size must be a pair of unsigned "
121 "integers",
122 &F);
123 return;
124 }
125
126 if (Min != Product || Max != Product) {
127 VS.CheckFailed("amdgpu-flat-work-group-size must equal the product of "
128 "reqd_work_group_size operands",
129 &F, ReqdWorkGroupSize);
130 }
131}
132
137
139 const GlobalVariable &GV) {
140 // This is not required for other targets so we only check for AMDGPU.
141 if (!VS.TT.isAMDGPU())
142 return;
143
144 // The VGPR address space is a view of one wave's own vector registers, which
145 // exist only while that wave runs. A global variable needs storage that
146 // outlives any particular wave, so there is nothing here for it to name.
148 VS.CheckFailed("global variable on amdgpu must not be in addrspace(13)",
149 &GV);
150}
151
153 // This is not required for other targets so we only check for AMDGPU.
154 if (!VS.TT.isAMDGPU())
155 return;
156
159 VS.CheckFailed("alloca on amdgpu must be in addrspace(5) or addrspace(13)",
160 &AI);
161
162 // Only static allocas can live in VGPRs; a dynamically sized one has no
163 // register-file representation. (Other address spaces are already rejected
164 // above, so this only adds the more specific diagnostic for addrspace(13).)
165 if (!AI.isStaticAlloca() && AI.getAddressSpace() == AMDGPUAS::VGPR)
166 VS.CheckFailed("dynamic alloca on amdgpu must be in addrspace(5)", &AI);
167}
168
170 switch (ID) {
171 default:
172 return false;
173 case Intrinsic::amdgcn_kill:
174 return true;
175 }
176}
177
179 CallBase &Call) {
180 switch (ID) {
181 default:
182 return;
183 case Intrinsic::amdgcn_kill: {
184 if (auto *CBI = dyn_cast<CallBrInst>(&Call)) {
185 Check(CBI->getNumIndirectDests() == 1,
186 "callbr amdgcn_kill only supports one indirect dest");
187 // We assume that amdgcn_unreachable is only introduced by
188 // AMDGPUUnifyDivergentExitNodes, which replaces the block's original
189 // unreachable terminator by a call to amdgcn_unreachable + a return.
190 const Instruction *Term = CBI->getIndirectDest(0)->getTerminator();
191 const CallInst *CI = dyn_cast_if_present<CallInst>(Term->getPrevNode());
193 (CI && CI->getIntrinsicID() == Intrinsic::amdgcn_unreachable),
194 "callbr amdgcn_kill indirect dest needs to be unreachable");
195 }
196 break;
197 }
198 case Intrinsic::amdgcn_cs_chain: {
199 CallingConv::ID CallerCC = Call.getCaller()->getCallingConv();
200 switch (CallerCC) {
209 break;
210 default:
211 VS.CheckFailed("Intrinsic cannot be called from functions with this "
212 "calling convention",
213 &Call);
214 break;
215 }
216
217 Check(Call.paramHasAttr(2, Attribute::InReg),
218 "SGPR arguments must have the `inreg` attribute", &Call);
219 Check(!Call.paramHasAttr(3, Attribute::InReg),
220 "VGPR arguments must not have the `inreg` attribute", &Call);
221
222 ConstantInt *FlagsArg = cast<ConstantInt>(Call.getArgOperand(4));
223 Check(FlagsArg->getValue().ult(2),
224 "flags must be 0 or 1 for llvm.amdgcn.cs.chain", &Call);
225
226 Instruction *Next = Call.getNextNode();
227 bool IsAMDUnreachable = isa_and_nonnull<IntrinsicInst>(Next) &&
228 cast<IntrinsicInst>(Next)->getIntrinsicID() ==
229 Intrinsic::amdgcn_unreachable;
230 Check(Next && (isa<UnreachableInst>(Next) || IsAMDUnreachable),
231 "llvm.amdgcn.cs.chain must be followed by unreachable", &Call);
232 break;
233 }
234 case Intrinsic::amdgcn_init_exec_from_input: {
235 const Argument *Arg = dyn_cast<Argument>(Call.getOperand(0));
236 Check(Arg && Arg->hasInRegAttr(),
237 "only inreg arguments to the parent function are valid as inputs to "
238 "this intrinsic",
239 &Call);
240 break;
241 }
242 case Intrinsic::amdgcn_set_inactive_chain_arg: {
243 CallingConv::ID CallerCC = Call.getCaller()->getCallingConv();
244 switch (CallerCC) {
247 break;
248 default:
249 VS.CheckFailed("Intrinsic can only be used from functions with the "
250 "amdgpu_cs_chain or amdgpu_cs_chain_preserve "
251 "calling conventions",
252 &Call);
253 break;
254 }
255
256 unsigned InactiveIdx = 1;
257 Check(!Call.paramHasAttr(InactiveIdx, Attribute::InReg),
258 "Value for inactive lanes must not have the `inreg` attribute",
259 &Call);
260 Check(isa<Argument>(Call.getArgOperand(InactiveIdx)),
261 "Value for inactive lanes must be a function argument", &Call);
262 Check(!cast<Argument>(Call.getArgOperand(InactiveIdx))->hasInRegAttr(),
263 "Value for inactive lanes must be a VGPR function argument", &Call);
264 break;
265 }
266 case Intrinsic::amdgcn_call_whole_wave: {
267 Function *F = dyn_cast<Function>(Call.getArgOperand(0));
268 Check(F, "Indirect whole wave calls are not allowed", &Call);
269
270 CallingConv::ID CC = F->getCallingConv();
272 "Callee must have the amdgpu_gfx_whole_wave calling convention",
273 &Call);
274
275 Check(!F->isVarArg(), "Variadic whole wave calls are not allowed", &Call);
276
277 Check(Call.arg_size() == F->arg_size(),
278 "Call argument count must match callee argument count", &Call);
279
280 Check(F->arg_begin()->getType()->isIntegerTy(1),
281 "Callee must have i1 as its first argument", &Call);
282 for (auto [CallArg, FuncArg] :
283 drop_begin(zip_equal(Call.args(), F->args()))) {
284 Check(CallArg->getType() == FuncArg.getType(),
285 "Argument types must match", &Call);
286
287 Check(Call.paramHasAttr(FuncArg.getArgNo(), Attribute::InReg) ==
288 FuncArg.hasInRegAttr(),
289 "Argument inreg attributes must match", &Call);
290 }
291 break;
292 }
293 case Intrinsic::amdgcn_s_prefetch_data: {
294 Check(
296 Call.getArgOperand(0)->getType()->getPointerAddressSpace()),
297 "llvm.amdgcn.s.prefetch.data only supports global or constant memory");
298 break;
299 }
300 case Intrinsic::amdgcn_load_to_lds:
301 case Intrinsic::amdgcn_load_async_to_lds:
302 case Intrinsic::amdgcn_global_load_lds:
303 case Intrinsic::amdgcn_global_load_async_lds:
304 case Intrinsic::amdgcn_raw_buffer_load_lds:
305 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
306 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
307 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
308 case Intrinsic::amdgcn_struct_buffer_load_lds:
309 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
310 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
311 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
312 uint64_t Size = cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue();
313 Check(Size == 1 || Size == 2 || Size == 4 || Size == 12 || Size == 16,
314 "invalid data size for load-to-LDS intrinsic; must be 1, 2, 4, 12, "
315 "or 16",
316 &Call);
317 break;
318 }
319 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
320 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
321 Value *Src0 = Call.getArgOperand(0);
322 Value *Src1 = Call.getArgOperand(1);
323
324 uint64_t CBSZ = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue();
325 uint64_t BLGP = cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue();
326 Check(CBSZ <= 4, "invalid value for cbsz format", Call,
327 Call.getArgOperand(3));
328 Check(BLGP <= 4, "invalid value for blgp format", Call,
329 Call.getArgOperand(4));
330
331 auto GetFormatNumRegs = [](unsigned FormatVal) {
332 switch (FormatVal) {
333 case 0:
334 case 1:
335 return 8u;
336 case 2:
337 case 3:
338 return 6u;
339 case 4:
340 return 4u;
341 default:
342 llvm_unreachable("invalid format value");
343 }
344 };
345
346 auto IsValidSrcASrcBVector = [](FixedVectorType *Ty) {
347 if (!Ty || !Ty->getElementType()->isIntegerTy(32))
348 return false;
349 unsigned NumElts = Ty->getNumElements();
350 return NumElts == 4 || NumElts == 6 || NumElts == 8;
351 };
352
353 FixedVectorType *Src0Ty = dyn_cast<FixedVectorType>(Src0->getType());
354 FixedVectorType *Src1Ty = dyn_cast<FixedVectorType>(Src1->getType());
355 Check(IsValidSrcASrcBVector(Src0Ty),
356 "operand 0 must be 4, 6 or 8 element i32 vector", &Call, Src0);
357 Check(IsValidSrcASrcBVector(Src1Ty),
358 "operand 1 must be 4, 6 or 8 element i32 vector", &Call, Src1);
359
360 Check(Src0Ty->getNumElements() >= GetFormatNumRegs(CBSZ),
361 "invalid vector type for format", &Call, Src0, Call.getArgOperand(3));
362 Check(Src1Ty->getNumElements() >= GetFormatNumRegs(BLGP),
363 "invalid vector type for format", &Call, Src1, Call.getArgOperand(5));
364 break;
365 }
366 case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4:
367 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
368 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
369 Value *Src0 = Call.getArgOperand(1);
370 Value *Src1 = Call.getArgOperand(3);
371
372 unsigned FmtA = cast<ConstantInt>(Call.getArgOperand(0))->getZExtValue();
373 unsigned FmtB = cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue();
374 Check(FmtA <= 4, "invalid value for matrix format", Call,
375 Call.getArgOperand(0));
376 Check(FmtB <= 4, "invalid value for matrix format", Call,
377 Call.getArgOperand(2));
378
379 auto GetFormatNumRegs = [](unsigned FormatVal) {
380 switch (FormatVal) {
381 case 0:
382 case 1:
383 return 16u;
384 case 2:
385 case 3:
386 return 12u;
387 case 4:
388 return 8u;
389 default:
390 llvm_unreachable("invalid format value");
391 }
392 };
393
394 auto IsValidSrcASrcBVector = [](FixedVectorType *Ty) {
395 if (!Ty || !Ty->getElementType()->isIntegerTy(32))
396 return false;
397 unsigned NumElts = Ty->getNumElements();
398 return NumElts == 16 || NumElts == 12 || NumElts == 8;
399 };
400
401 FixedVectorType *Src0Ty = dyn_cast<FixedVectorType>(Src0->getType());
402 FixedVectorType *Src1Ty = dyn_cast<FixedVectorType>(Src1->getType());
403 Check(IsValidSrcASrcBVector(Src0Ty),
404 "operand 1 must be 8, 12 or 16 element i32 vector", &Call, Src0);
405 Check(IsValidSrcASrcBVector(Src1Ty),
406 "operand 3 must be 8, 12 or 16 element i32 vector", &Call, Src1);
407
408 Check(Src0Ty->getNumElements() >= GetFormatNumRegs(FmtA),
409 "invalid vector type for format", &Call, Src0, Call.getArgOperand(0));
410 Check(Src1Ty->getNumElements() >= GetFormatNumRegs(FmtB),
411 "invalid vector type for format", &Call, Src1, Call.getArgOperand(2));
412 break;
413 }
414 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
415 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
416 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
417 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
418 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
419 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
420 Value *PtrArg = Call.getArgOperand(0);
421 const unsigned AS = PtrArg->getType()->getPointerAddressSpace();
423 "cooperative atomic intrinsics require a generic or global pointer",
424 &Call, PtrArg);
425
427 cast<MetadataAsValue>(Call.getArgOperand(Call.arg_size() - 1));
428 MDNode *MD = cast<MDNode>(Op->getMetadata());
429 Check((MD->getNumOperands() == 1) && isa<MDString>(MD->getOperand(0)),
430 "cooperative atomic intrinsics require that the last argument is a "
431 "metadata string",
432 &Call, Op);
433 break;
434 }
435 case Intrinsic::amdgcn_av_load_b128:
436 case Intrinsic::amdgcn_av_store_b128: {
438 cast<MetadataAsValue>(Call.getArgOperand(Call.arg_size() - 1));
439 MDNode *MD = dyn_cast<MDNode>(Op->getMetadata());
440 Check(MD && (MD->getNumOperands() == 1) && isa<MDString>(MD->getOperand(0)),
441 "the last argument to av load/store intrinsics must be a "
442 "metadata string",
443 &Call, Op);
444 break;
445 }
446 }
447}
448
449#undef Check
AMDGPU address space definition.
uint64_t uint64_t
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define F(x, y, z)
Definition MD5.cpp:54
This file contains some functions that are useful when dealing with strings.
#define Check(C,...)
static void verifyAMDGPUReqdWorkGroupSize(VerifierSupport &VS, const Function &F)
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1115
an instruction to allocate memory on the stack
LLVM_ABI bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
unsigned getAddressSpace() const
Return the address space for the allocation.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
LLVM_ABI bool hasInRegAttr() const
Return true if this argument has the inreg attribute.
Definition Function.cpp:286
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:106
LLVM_ABI bool isStringAttribute() const
Return true if the attribute is a string (target-dependent) attribute.
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:262
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
This class represents a function call, abstracting a target machine's calling convention.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
Class to represent fixed width SIMD vectors.
unsigned getAddressSpace() const
Metadata node.
Definition Metadata.h:1081
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1437
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1443
Tracking metadata reference owned by Metadata.
Definition Metadata.h:902
A single uniqued string.
Definition Metadata.h:733
Metadata wrapper in the Value hierarchy.
Definition Metadata.h:184
ModFlagBehavior
This enumeration defines the supported behaviors of module flags.
Definition Module.h:118
@ Error
Emits an error if two values disagree, otherwise the resulting value is that of the operands.
Definition Module.h:121
@ Max
Takes the max of the two values, which are required to be integers.
Definition Module.h:150
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:661
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ VGPR
Address space for VGPRs.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
bool isFlatGlobalAddrSpace(unsigned AS)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_CS_ChainPreserve
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
Definition Metadata.h:720
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:707
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
Definition STLExtras.h:856
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
void verifyAMDGPUAlloca(VerifierSupport &VS, const AllocaInst &AI)
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
void verifyAMDGPUFunctionMetadata(VerifierSupport &VS, const Function &F)
void verifyAMDGPUIntrinsicCall(VerifierSupport &VS, Intrinsic::ID ID, CallBase &Call)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
void verifyAMDGPUGlobalVariable(VerifierSupport &VS, const GlobalVariable &GV)
void verifyAMDGPUModuleFlag(VerifierSupport &VS, const MDString *ID, Module::ModFlagBehavior MFB, const MDNode *Op)
bool to_integer(StringRef S, N &Num, unsigned Base=0)
Convert the string S to an integer of the specified type using the radix Base. If Base is 0,...
bool isAMDGPUCallBrIntrinsic(Intrinsic::ID ID)