28#include "llvm/IR/IntrinsicsAMDGPU.h"
33#define Check(C, ...) \
36 VS.CheckFailed(__VA_ARGS__); \
48 if (FlagName ==
"buffer.oob.mode" || FlagName ==
"tbuffer.oob.mode") {
50 "'" + ID->getString() +
51 "' module flag must use 'max' merge behaviour");
55 "' module flag must have a constant integer value");
57 "'" + ID->getString() +
"' module flag must be 0, 1, or 2");
61 if (FlagName ==
"xnack" || FlagName ==
"sramecc") {
63 "'" + ID->getString() +
64 "' module flag must use 'error' merge behaviour");
68 "' module flag must have a constant integer value");
70 "'" + ID->getString() +
"' module flag must be 0 or 1");
81 if (!VS.TT.isAMDGPU())
84 MDNode *ReqdWorkGroupSize =
F.getMetadata(
"reqd_work_group_size");
85 if (!ReqdWorkGroupSize || ReqdWorkGroupSize->getNumOperands() != 3)
89 for (
const MDOperand &
Op : ReqdWorkGroupSize->operands()) {
91 if (!
C ||
C->getValue().getActiveBits() > 64)
94 if (Dim != 0 && Product > std::numeric_limits<uint64_t>::max() / Dim)
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);
107 VS.CheckFailed(
"amdgpu-flat-work-group-size must be a string attribute",
113 std::pair<StringRef, StringRef>
Values = AttrValue.
split(
',');
116 bool Parsed = !
Values.second.contains(
',') &&
120 VS.CheckFailed(
"amdgpu-flat-work-group-size must be a pair of unsigned "
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);
141 if (!VS.TT.isAMDGPU())
148 VS.CheckFailed(
"global variable on amdgpu must not be in addrspace(13)",
154 if (!VS.TT.isAMDGPU())
159 VS.CheckFailed(
"alloca on amdgpu must be in addrspace(5) or addrspace(13)",
166 VS.CheckFailed(
"dynamic alloca on amdgpu must be in addrspace(5)", &AI);
173 case Intrinsic::amdgcn_kill:
183 case Intrinsic::amdgcn_kill: {
185 Check(CBI->getNumIndirectDests() == 1,
186 "callbr amdgcn_kill only supports one indirect dest");
190 const Instruction *Term = CBI->getIndirectDest(0)->getTerminator();
195 "callbr amdgcn_kill indirect dest needs to be unreachable");
199 case Intrinsic::amdgcn_cs_chain: {
212 VS.CheckFailed(
"Intrinsic cannot be called from functions with this "
213 "calling convention",
218 Check(
Call.paramHasAttr(2, Attribute::InReg),
219 "SGPR arguments must have the `inreg` attribute", &
Call);
220 Check(!
Call.paramHasAttr(3, Attribute::InReg),
221 "VGPR arguments must not have the `inreg` attribute", &
Call);
225 "flags must be 0 or 1 for llvm.amdgcn.cs.chain", &
Call);
230 Intrinsic::amdgcn_unreachable;
232 "llvm.amdgcn.cs.chain must be followed by unreachable", &
Call);
235 case Intrinsic::amdgcn_init_exec_from_input: {
238 "only inreg arguments to the parent function are valid as inputs to "
243 case Intrinsic::amdgcn_set_inactive_chain_arg: {
250 VS.CheckFailed(
"Intrinsic can only be used from functions with the "
251 "amdgpu_cs_chain or amdgpu_cs_chain_preserve "
252 "calling conventions",
257 unsigned InactiveIdx = 1;
258 Check(!
Call.paramHasAttr(InactiveIdx, Attribute::InReg),
259 "Value for inactive lanes must not have the `inreg` attribute",
262 "Value for inactive lanes must be a function argument", &
Call);
264 "Value for inactive lanes must be a VGPR function argument", &
Call);
267 case Intrinsic::amdgcn_call_whole_wave: {
269 Check(
F,
"Indirect whole wave calls are not allowed", &
Call);
273 "Callee must have the amdgpu_gfx_whole_wave calling convention",
276 Check(!
F->isVarArg(),
"Variadic whole wave calls are not allowed", &
Call);
279 "Call argument count must match callee argument count", &
Call);
281 Check(
F->arg_begin()->getType()->isIntegerTy(1),
282 "Callee must have i1 as its first argument", &
Call);
283 for (
auto [CallArg, FuncArg] :
285 Check(CallArg->getType() == FuncArg.getType(),
286 "Argument types must match", &
Call);
288 Check(
Call.paramHasAttr(FuncArg.getArgNo(), Attribute::InReg) ==
289 FuncArg.hasInRegAttr(),
290 "Argument inreg attributes must match", &
Call);
294 case Intrinsic::amdgcn_s_prefetch_data: {
297 Call.getArgOperand(0)->getType()->getPointerAddressSpace()),
298 "llvm.amdgcn.s.prefetch.data only supports global or constant memory");
301 case Intrinsic::amdgcn_load_to_lds:
302 case Intrinsic::amdgcn_load_async_to_lds:
303 case Intrinsic::amdgcn_global_load_lds:
304 case Intrinsic::amdgcn_global_load_async_lds:
305 case Intrinsic::amdgcn_raw_buffer_load_lds:
306 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
307 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
308 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
309 case Intrinsic::amdgcn_struct_buffer_load_lds:
310 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
311 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
312 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
315 "invalid data size for load-to-LDS intrinsic; must be 1, 2, 4, 12, "
320 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
321 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
327 Check(CBSZ <= 4,
"invalid value for cbsz format",
Call,
328 Call.getArgOperand(3));
329 Check(BLGP <= 4,
"invalid value for blgp format",
Call,
330 Call.getArgOperand(4));
332 auto GetFormatNumRegs = [](
unsigned FormatVal) {
348 if (!Ty || !Ty->getElementType()->isIntegerTy(32))
350 unsigned NumElts = Ty->getNumElements();
351 return NumElts == 4 || NumElts == 6 || NumElts == 8;
356 Check(IsValidSrcASrcBVector(Src0Ty),
357 "operand 0 must be 4, 6 or 8 element i32 vector", &
Call, Src0);
358 Check(IsValidSrcASrcBVector(Src1Ty),
359 "operand 1 must be 4, 6 or 8 element i32 vector", &
Call, Src1);
361 Check(Src0Ty->getNumElements() >= GetFormatNumRegs(CBSZ),
362 "invalid vector type for format", &
Call, Src0,
Call.getArgOperand(3));
363 Check(Src1Ty->getNumElements() >= GetFormatNumRegs(BLGP),
364 "invalid vector type for format", &
Call, Src1,
Call.getArgOperand(5));
367 case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4:
368 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
369 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
375 Check(FmtA <= 4,
"invalid value for matrix format",
Call,
376 Call.getArgOperand(0));
377 Check(FmtB <= 4,
"invalid value for matrix format",
Call,
378 Call.getArgOperand(2));
380 auto GetFormatNumRegs = [](
unsigned FormatVal) {
396 if (!Ty || !Ty->getElementType()->isIntegerTy(32))
398 unsigned NumElts = Ty->getNumElements();
399 return NumElts == 16 || NumElts == 12 || NumElts == 8;
404 Check(IsValidSrcASrcBVector(Src0Ty),
405 "operand 1 must be 8, 12 or 16 element i32 vector", &
Call, Src0);
406 Check(IsValidSrcASrcBVector(Src1Ty),
407 "operand 3 must be 8, 12 or 16 element i32 vector", &
Call, Src1);
409 Check(Src0Ty->getNumElements() >= GetFormatNumRegs(FmtA),
410 "invalid vector type for format", &
Call, Src0,
Call.getArgOperand(0));
411 Check(Src1Ty->getNumElements() >= GetFormatNumRegs(FmtB),
412 "invalid vector type for format", &
Call, Src1,
Call.getArgOperand(2));
415 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
416 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
417 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
418 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
419 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
420 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
424 "cooperative atomic intrinsics require a generic or global pointer",
431 "cooperative atomic intrinsics require that the last argument is a "
436 case Intrinsic::amdgcn_av_load_b128:
437 case Intrinsic::amdgcn_av_store_b128: {
442 "the last argument to av load/store intrinsics must be a "
AMDGPU address space definition.
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...
static void verifyAMDGPUReqdWorkGroupSize(VerifierSupport &VS, const Function &F)
bool ult(const APInt &RHS) const
Unsigned less than comparison.
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.
LLVM_ABI bool hasInRegAttr() const
Return true if this argument has the inreg attribute.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
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.
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.
const APInt & getValue() const
Return the constant as an APInt value reference.
Class to represent fixed width SIMD vectors.
unsigned getAddressSpace() const
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
Tracking metadata reference owned by Metadata.
ModFlagBehavior
This enumeration defines the supported behaviors of module flags.
@ Error
Emits an error if two values disagree, otherwise the resulting value is that of the operands.
@ Max
Takes the max of the two values, which are required to be integers.
Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
#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.
@ 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.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
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.
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.
RelativeUniformCounterPtr Values
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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 ...
void verifyAMDGPUAlloca(VerifierSupport &VS, const AllocaInst &AI)
bool isa_and_nonnull(const Y &Val)
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...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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)