27#include "llvm/IR/IntrinsicsAMDGPU.h"
32#define Check(C, ...) \
35 VS.CheckFailed(__VA_ARGS__); \
47 if (FlagName ==
"buffer.oob.mode" || FlagName ==
"tbuffer.oob.mode") {
49 "'" + ID->getString() +
50 "' module flag must use 'max' merge behaviour");
54 "' module flag must have a constant integer value");
56 "'" + ID->getString() +
"' module flag must be 0, 1, or 2");
60 if (FlagName ==
"xnack" || FlagName ==
"sramecc") {
62 "'" + ID->getString() +
63 "' module flag must use 'error' merge behaviour");
67 "' module flag must have a constant integer value");
69 "'" + ID->getString() +
"' module flag must be 0 or 1");
80 if (!VS.TT.isAMDGPU())
83 MDNode *ReqdWorkGroupSize =
F.getMetadata(
"reqd_work_group_size");
84 if (!ReqdWorkGroupSize || ReqdWorkGroupSize->getNumOperands() != 3)
88 for (
const MDOperand &
Op : ReqdWorkGroupSize->operands()) {
90 if (!
C ||
C->getValue().getActiveBits() > 64)
93 if (Dim != 0 && Product > std::numeric_limits<uint64_t>::max() / Dim)
98 Attribute FlatWorkGroupSize =
F.getFnAttribute(
"amdgpu-flat-work-group-size");
99 if (!FlatWorkGroupSize.
isValid()) {
100 VS.CheckFailed(
"reqd_work_group_size requires amdgpu-flat-work-group-size",
101 &
F, ReqdWorkGroupSize);
106 VS.CheckFailed(
"amdgpu-flat-work-group-size must be a string attribute",
112 std::pair<StringRef, StringRef>
Values = AttrValue.
split(
',');
115 bool Parsed = !
Values.second.contains(
',') &&
119 VS.CheckFailed(
"amdgpu-flat-work-group-size must be a pair of unsigned "
125 if (Min != Product || Max != Product) {
126 VS.CheckFailed(
"amdgpu-flat-work-group-size must equal the product of "
127 "reqd_work_group_size operands",
128 &
F, ReqdWorkGroupSize);
139 if (!VS.TT.isAMDGPU())
143 VS.CheckFailed(
"alloca on amdgpu must be in addrspace(5)", &AI);
150 case Intrinsic::amdgcn_kill:
160 case Intrinsic::amdgcn_kill: {
162 Check(CBI->getNumIndirectDests() == 1,
163 "callbr amdgcn_kill only supports one indirect dest");
167 const Instruction *Term = CBI->getIndirectDest(0)->getTerminator();
172 "callbr amdgcn_kill indirect dest needs to be unreachable");
176 case Intrinsic::amdgcn_cs_chain: {
189 VS.CheckFailed(
"Intrinsic cannot be called from functions with this "
190 "calling convention",
195 Check(
Call.paramHasAttr(2, Attribute::InReg),
196 "SGPR arguments must have the `inreg` attribute", &
Call);
197 Check(!
Call.paramHasAttr(3, Attribute::InReg),
198 "VGPR arguments must not have the `inreg` attribute", &
Call);
202 "flags must be 0 or 1 for llvm.amdgcn.cs.chain", &
Call);
207 Intrinsic::amdgcn_unreachable;
209 "llvm.amdgcn.cs.chain must be followed by unreachable", &
Call);
212 case Intrinsic::amdgcn_init_exec_from_input: {
215 "only inreg arguments to the parent function are valid as inputs to "
220 case Intrinsic::amdgcn_set_inactive_chain_arg: {
227 VS.CheckFailed(
"Intrinsic can only be used from functions with the "
228 "amdgpu_cs_chain or amdgpu_cs_chain_preserve "
229 "calling conventions",
234 unsigned InactiveIdx = 1;
235 Check(!
Call.paramHasAttr(InactiveIdx, Attribute::InReg),
236 "Value for inactive lanes must not have the `inreg` attribute",
239 "Value for inactive lanes must be a function argument", &
Call);
241 "Value for inactive lanes must be a VGPR function argument", &
Call);
244 case Intrinsic::amdgcn_call_whole_wave: {
246 Check(
F,
"Indirect whole wave calls are not allowed", &
Call);
250 "Callee must have the amdgpu_gfx_whole_wave calling convention",
253 Check(!
F->isVarArg(),
"Variadic whole wave calls are not allowed", &
Call);
256 "Call argument count must match callee argument count", &
Call);
258 Check(
F->arg_begin()->getType()->isIntegerTy(1),
259 "Callee must have i1 as its first argument", &
Call);
260 for (
auto [CallArg, FuncArg] :
262 Check(CallArg->getType() == FuncArg.getType(),
263 "Argument types must match", &
Call);
265 Check(
Call.paramHasAttr(FuncArg.getArgNo(), Attribute::InReg) ==
266 FuncArg.hasInRegAttr(),
267 "Argument inreg attributes must match", &
Call);
271 case Intrinsic::amdgcn_s_prefetch_data: {
274 Call.getArgOperand(0)->getType()->getPointerAddressSpace()),
275 "llvm.amdgcn.s.prefetch.data only supports global or constant memory");
278 case Intrinsic::amdgcn_load_to_lds:
279 case Intrinsic::amdgcn_load_async_to_lds:
280 case Intrinsic::amdgcn_global_load_lds:
281 case Intrinsic::amdgcn_global_load_async_lds:
282 case Intrinsic::amdgcn_raw_buffer_load_lds:
283 case Intrinsic::amdgcn_raw_buffer_load_async_lds:
284 case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
285 case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
286 case Intrinsic::amdgcn_struct_buffer_load_lds:
287 case Intrinsic::amdgcn_struct_buffer_load_async_lds:
288 case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
289 case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds: {
292 "invalid data size for load-to-LDS intrinsic; must be 1, 2, 4, 12, "
297 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
298 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
304 Check(CBSZ <= 4,
"invalid value for cbsz format",
Call,
305 Call.getArgOperand(3));
306 Check(BLGP <= 4,
"invalid value for blgp format",
Call,
307 Call.getArgOperand(4));
309 auto GetFormatNumRegs = [](
unsigned FormatVal) {
325 if (!Ty || !Ty->getElementType()->isIntegerTy(32))
327 unsigned NumElts = Ty->getNumElements();
328 return NumElts == 4 || NumElts == 6 || NumElts == 8;
333 Check(IsValidSrcASrcBVector(Src0Ty),
334 "operand 0 must be 4, 6 or 8 element i32 vector", &
Call, Src0);
335 Check(IsValidSrcASrcBVector(Src1Ty),
336 "operand 1 must be 4, 6 or 8 element i32 vector", &
Call, Src1);
338 Check(Src0Ty->getNumElements() >= GetFormatNumRegs(CBSZ),
339 "invalid vector type for format", &
Call, Src0,
Call.getArgOperand(3));
340 Check(Src1Ty->getNumElements() >= GetFormatNumRegs(BLGP),
341 "invalid vector type for format", &
Call, Src1,
Call.getArgOperand(5));
344 case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4:
345 case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4:
346 case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: {
352 Check(FmtA <= 4,
"invalid value for matrix format",
Call,
353 Call.getArgOperand(0));
354 Check(FmtB <= 4,
"invalid value for matrix format",
Call,
355 Call.getArgOperand(2));
357 auto GetFormatNumRegs = [](
unsigned FormatVal) {
373 if (!Ty || !Ty->getElementType()->isIntegerTy(32))
375 unsigned NumElts = Ty->getNumElements();
376 return NumElts == 16 || NumElts == 12 || NumElts == 8;
381 Check(IsValidSrcASrcBVector(Src0Ty),
382 "operand 1 must be 8, 12 or 16 element i32 vector", &
Call, Src0);
383 Check(IsValidSrcASrcBVector(Src1Ty),
384 "operand 3 must be 8, 12 or 16 element i32 vector", &
Call, Src1);
386 Check(Src0Ty->getNumElements() >= GetFormatNumRegs(FmtA),
387 "invalid vector type for format", &
Call, Src0,
Call.getArgOperand(0));
388 Check(Src1Ty->getNumElements() >= GetFormatNumRegs(FmtB),
389 "invalid vector type for format", &
Call, Src1,
Call.getArgOperand(2));
392 case Intrinsic::amdgcn_cooperative_atomic_load_32x4B:
393 case Intrinsic::amdgcn_cooperative_atomic_load_16x8B:
394 case Intrinsic::amdgcn_cooperative_atomic_load_8x16B:
395 case Intrinsic::amdgcn_cooperative_atomic_store_32x4B:
396 case Intrinsic::amdgcn_cooperative_atomic_store_16x8B:
397 case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: {
401 "cooperative atomic intrinsics require a generic or global pointer",
408 "cooperative atomic intrinsics require that the last argument is a "
413 case Intrinsic::amdgcn_av_load_b128:
414 case Intrinsic::amdgcn_av_store_b128: {
419 "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
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.
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.
@ 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 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)