25#include "llvm/IR/IntrinsicsAMDGPU.h"
26#include "llvm/IR/IntrinsicsR600.h"
32#define DEBUG_TYPE "amdgpu-subtarget"
42 const unsigned WavesPerWorkgroup =
43 std::max(1u, (WorkGroupSize + WaveSize - 1) / WaveSize);
45 const unsigned WorkGroupsPerCU =
55 uint32_t LDSBytes, std::pair<unsigned, unsigned> FlatWorkGroupSizes)
const {
60 LDSBytes =
alignTo(LDSBytes, Granularity);
72 auto PropsFromWGSize = [=](
unsigned WGSize)
73 -> std::tuple<const unsigned, const unsigned, unsigned> {
74 unsigned WavesPerWG =
divideCeil(WGSize, WaveSize);
76 return {WavesPerWG, WGsPerCU, WavesPerWG * WGsPerCU};
83 const auto [MinWGSize, MaxWGSize] = FlatWorkGroupSizes;
84 auto [MinWavesPerWG, MaxWGsPerCU, MaxWavesPerCU] = PropsFromWGSize(MinWGSize);
85 auto [MaxWavesPerWG, MinWGsPerCU, MinWavesPerCU] = PropsFromWGSize(MaxWGSize);
90 if (MinWavesPerCU >= MaxWavesPerCU) {
98 unsigned MinWavesPerCUForWGSize =
99 divideCeil(WaveSlotsPerCU, MinWGsPerCU + 1) * MinWGsPerCU;
100 if (MinWavesPerCU > MinWavesPerCUForWGSize) {
101 unsigned ExcessSlots = MinWavesPerCU - MinWavesPerCUForWGSize;
102 if (
unsigned ExcessSlotsPerWG = ExcessSlots / MinWGsPerCU) {
109 MinWavesPerCU -= MinWGsPerCU * std::min(ExcessSlotsPerWG,
110 MaxWavesPerWG - MinWavesPerWG);
117 unsigned LeftoverSlots = WaveSlotsPerCU - MaxWGsPerCU * MinWavesPerWG;
118 if (
unsigned LeftoverSlotsPerWG = LeftoverSlots / MaxWGsPerCU) {
125 MaxWavesPerCU += MaxWGsPerCU * std::min(LeftoverSlotsPerWG,
126 ((MaxWGSize - 1) / WaveSize) + 1 -
144std::pair<unsigned, unsigned>
162 std::pair<unsigned, unsigned>
Default =
167 F,
"amdgpu-flat-work-group-size",
Default);
170 if (Requested.first > Requested.second)
187 std::pair<unsigned, unsigned> RequestedWavesPerEU,
188 std::pair<unsigned, unsigned> FlatWorkGroupSizes,
unsigned LDSBytes)
const {
193 std::pair<unsigned, unsigned>
Default = {
200 if (RequestedWavesPerEU.first <
Default.first ||
201 RequestedWavesPerEU.first >
Default.second ||
202 RequestedWavesPerEU.first > RequestedWavesPerEU.second ||
207 RequestedWavesPerEU.second =
208 std::min(RequestedWavesPerEU.second,
Default.second);
209 return RequestedWavesPerEU;
212std::pair<unsigned, unsigned>
224std::pair<unsigned, unsigned>
226 unsigned LDSBytes,
const Function &
F)
const {
231 std::pair<unsigned, unsigned> Requested =
236std::optional<unsigned>
238 unsigned Dim)
const {
240 if (
Node &&
Node->getNumOperands() == 3)
246 const Function &
F,
bool RequiresUniformYZ)
const {
247 auto *
Node =
F.getMetadata(
"reqd_work_group_size");
248 if (!
Node ||
Node->getNumOperands() != 3)
257 bool Is1D = YLen <= 1 && ZLen <= 1;
258 bool IsXLargeEnough =
260 return Is1D || IsXLargeEnough;
268 unsigned Dimension)
const {
271 return *ReqdSize - 1;
276 for (
int I = 0;
I < 3; ++
I) {
283 if (!Func.hasFnAttribute(
"amdgpu-no-wwm"))
291 unsigned MinSize = 0;
293 bool IdQuery =
false;
297 const Function *
F = CI->getCalledFunction();
299 unsigned Dim = UINT_MAX;
300 switch (
F->getIntrinsicID()) {
301 case Intrinsic::amdgcn_workitem_id_x:
302 case Intrinsic::r600_read_tidig_x:
305 case Intrinsic::r600_read_local_size_x:
308 case Intrinsic::amdgcn_workitem_id_y:
309 case Intrinsic::r600_read_tidig_y:
312 case Intrinsic::r600_read_local_size_y:
315 case Intrinsic::amdgcn_workitem_id_z:
316 case Intrinsic::r600_read_tidig_z:
319 case Intrinsic::r600_read_local_size_z:
329 MinSize = MaxSize = *ReqdSize;
348 CI->addRangeRetAttr(
Range);
352 I->setMetadata(LLVMContext::MD_range, MaxWorkGroupSizeRange);
361 if (
F.hasFnAttribute(
"amdgpu-no-implicitarg-ptr"))
368 const Module *M =
F.getParent();
371 return F.getFnAttributeAsParsedInteger(
"amdgpu-implicitarg-num-bytes",
376 Align &MaxAlign)
const {
381 uint64_t ExplicitArgBytes = 0;
385 if (Arg.hasAttribute(
"amdgpu-hidden-argument"))
388 const bool IsByRef = Arg.hasByRefAttr();
389 Type *ArgTy = IsByRef ? Arg.getParamByRefType() : Arg.getType();
390 Align Alignment =
DL.getValueOrABITypeAlignment(
391 IsByRef ? Arg.getParamAlign() : std::nullopt, ArgTy);
392 uint64_t AllocSize =
DL.getTypeAllocSize(ArgTy);
393 ExplicitArgBytes =
alignTo(ExplicitArgBytes, Alignment) + AllocSize;
394 MaxAlign = std::max(MaxAlign, Alignment);
397 return ExplicitArgBytes;
401 Align &MaxAlign)
const {
410 uint64_t TotalSize = ExplicitOffset + ExplicitArgBytes;
412 if (ImplicitBytes != 0) {
414 TotalSize =
alignTo(ExplicitArgBytes, Alignment) + ImplicitBytes;
415 MaxAlign = std::max(MaxAlign, Alignment);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file describes how to lower LLVM calls to machine code calls.
This file declares the targeting of the InstructionSelector class for AMDGPU.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
Base class for AMDGPU specific classes of TargetSubtarget.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
AMDGPU R600 specific subclass of TargetSubtarget.
std::pair< unsigned, unsigned > getDefaultFlatWorkGroupSize(CallingConv::ID CC) const
std::optional< unsigned > getReqdWorkGroupSize(const Function &F, unsigned Dim) const
Align getAlignmentForImplicitArgPtr() const
bool isMesaKernel(const Function &F) const
std::pair< unsigned, unsigned > getWavesPerEU(const Function &F) const
std::pair< unsigned, unsigned > getOccupancyWithWorkGroupSizes(uint32_t LDSBytes, const Function &F) const
Subtarget's minimum/maximum occupancy, in number of waves per EU, that can be achieved when the only ...
std::pair< unsigned, unsigned > getFlatWorkGroupSizes(const Function &F) const
bool makeLIDRangeMetadata(Instruction *I) const
Creates value range metadata on an workitemid.* intrinsic call or load.
unsigned getMaxWorkitemID(const Function &Kernel, unsigned Dimension) const
Return the maximum workitem ID value in the function, for the given (0, 1, 2) dimension.
unsigned getImplicitArgNumBytes(const Function &F) const
unsigned getLocalMemorySize() const
Return the maximum number of bytes of LDS available for all workgroups running on the same WGP or CU.
unsigned getAddressableLocalMemorySize() const
Return the maximum number of bytes of LDS that can be allocated to a single workgroup.
virtual unsigned getWavesPerEUForWorkGroup(unsigned FlatWorkGroupSize) const =0
virtual unsigned getMaxWorkGroupsPerCU(unsigned FlatWorkGroupSize) const =0
unsigned getKernArgSegmentSize(const Function &F, Align &MaxAlign) const
unsigned getNumWorkGroupSIMDs() const
AMDGPUSubtarget(const Triple &TT)
AMDGPUDwarfFlavour getAMDGPUDwarfFlavour() const
unsigned getMaxLocalMemSizeWithWaveCount(unsigned WaveCount, const Function &) const
Return the amount of LDS that can be used that will not restrict the occupancy lower than WaveCount.
virtual unsigned getMaxFlatWorkGroupSize() const =0
unsigned getExplicitKernelArgOffset() const
Returns the offset in bytes from the start of the input buffer of the first explicit kernel argument.
unsigned getMaxWavesPerEU() const
uint64_t getExplicitKernArgSize(const Function &F, Align &MaxAlign) const
bool isSingleLaneExecution(const Function &Kernel) const
Return true if only a single workitem can be active in a wave.
static const AMDGPUSubtarget & get(const MachineFunction &MF)
unsigned getWavefrontSize() const
virtual unsigned getMinFlatWorkGroupSize() const =0
std::pair< unsigned, unsigned > getEffectiveWavesPerEU(std::pair< unsigned, unsigned > RequestedWavesPerEU, std::pair< unsigned, unsigned > FlatWorkGroupSizes, unsigned LDSBytes) const
Returns the target minimum/maximum number of waves per EU.
bool isSingleWavefrontWorkgroup(const Function &F) const
bool hasWavefrontsEvenlySplittingXDim(const Function &F, bool RequiresUniformYZ=false) const
unsigned LDSAllocationGranularity
Class for arbitrary precision integers.
This class represents an incoming formal argument to a Function.
This class represents a range of values.
A parsed version of the target data layout string in and methods for querying it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
A Module instance is used to store all the information related to an LLVM module.
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
Primary interface to the complete machine description for the target machine.
const Triple & getTargetTriple() const
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
bool isAMDGCN() const
Tests whether the target is AMDGCN.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_READNONE constexpr bool isShader(CallingConv::ID CC)
unsigned getAMDHSACodeObjectVersion(const Module &M)
std::pair< unsigned, unsigned > getIntegerPairAttribute(const Function &F, StringRef Name, std::pair< unsigned, unsigned > Default, bool OnlyFirstRequired)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ 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 * > extract(Y &&MD)
Extract a Value from Metadata.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.