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();
194 "callbr amdgcn_kill indirect dest needs to be unreachable");
198 case Intrinsic::amdgcn_cs_chain: {
211 VS.CheckFailed(
"Intrinsic cannot be called from functions with this "
212 "calling convention",
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);
224 "flags must be 0 or 1 for llvm.amdgcn.cs.chain", &
Call);
229 Intrinsic::amdgcn_unreachable;
231 "llvm.amdgcn.cs.chain must be followed by unreachable", &
Call);
234 case Intrinsic::amdgcn_init_exec_from_input: {
237 "only inreg arguments to the parent function are valid as inputs to "
242 case Intrinsic::amdgcn_set_inactive_chain_arg: {
249 VS.CheckFailed(
"Intrinsic can only be used from functions with the "
250 "amdgpu_cs_chain or amdgpu_cs_chain_preserve "
251 "calling conventions",
256 unsigned InactiveIdx = 1;
257 Check(!
Call.paramHasAttr(InactiveIdx, Attribute::InReg),
258 "Value for inactive lanes must not have the `inreg` attribute",
261 "Value for inactive lanes must be a function argument", &
Call);
263 "Value for inactive lanes must be a VGPR function argument", &
Call);
266 case Intrinsic::amdgcn_call_whole_wave: {
268 Check(
F,
"Indirect whole wave calls are not allowed", &
Call);
272 "Callee must have the amdgpu_gfx_whole_wave calling convention",
275 Check(!
F->isVarArg(),
"Variadic whole wave calls are not allowed", &
Call);
278 "Call argument count must match callee argument count", &
Call);
280 Check(
F->arg_begin()->getType()->isIntegerTy(1),
281 "Callee must have i1 as its first argument", &
Call);
282 for (
auto [CallArg, FuncArg] :
284 Check(CallArg->getType() == FuncArg.getType(),
285 "Argument types must match", &
Call);
287 Check(
Call.paramHasAttr(FuncArg.getArgNo(), Attribute::InReg) ==
288 FuncArg.hasInRegAttr(),
289 "Argument inreg attributes must match", &
Call);
293 case Intrinsic::amdgcn_s_prefetch_data: {
296 Call.getArgOperand(0)->getType()->getPointerAddressSpace()),
297 "llvm.amdgcn.s.prefetch.data only supports global or constant memory");
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: {
314 "invalid data size for load-to-LDS intrinsic; must be 1, 2, 4, 12, "
319 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
320 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
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));
331 auto GetFormatNumRegs = [](
unsigned FormatVal) {
347 if (!Ty || !Ty->getElementType()->isIntegerTy(32))
349 unsigned NumElts = Ty->getNumElements();
350 return NumElts == 4 || NumElts == 6 || NumElts == 8;
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);
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));
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: {
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));
379 auto GetFormatNumRegs = [](
unsigned FormatVal) {
395 if (!Ty || !Ty->getElementType()->isIntegerTy(32))
397 unsigned NumElts = Ty->getNumElements();
398 return NumElts == 16 || NumElts == 12 || NumElts == 8;
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);
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));
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: {
423 "cooperative atomic intrinsics require a generic or global pointer",
430 "cooperative atomic intrinsics require that the last argument is a "
435 case Intrinsic::amdgcn_av_load_b128:
436 case Intrinsic::amdgcn_av_store_b128: {
441 "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)