LLVM 24.0.0git
AMDGPUSubtarget.cpp
Go to the documentation of this file.
1//===-- AMDGPUSubtarget.cpp - AMDGPU Subtarget Information ----------------===//
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/// \file
10/// Implements the AMDGPU specific subclass of TargetSubtarget.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPUSubtarget.h"
15#include "AMDGPUCallLowering.h"
17#include "AMDGPULegalizerInfo.h"
19#include "R600Subtarget.h"
25#include "llvm/IR/IntrinsicsAMDGPU.h"
26#include "llvm/IR/IntrinsicsR600.h"
27#include "llvm/IR/MDBuilder.h"
28#include <algorithm>
29
30using namespace llvm;
31
32#define DEBUG_TYPE "amdgpu-subtarget"
33
34// Returns the maximum per-workgroup LDS allocation size (in bytes) that still
35// allows the given function to achieve an occupancy of NWaves waves per
36// SIMD / EU, taking into account only the function's *maximum* workgroup size.
37unsigned
39 const Function &F) const {
40 const unsigned WaveSize = getWavefrontSize();
41 const unsigned WorkGroupSize = getFlatWorkGroupSizes(F).second;
42 const unsigned WavesPerWorkgroup =
43 std::max(1u, (WorkGroupSize + WaveSize - 1) / WaveSize);
44
45 const unsigned WorkGroupsPerCU =
46 std::max(1u, (NWaves * getNumWorkGroupSIMDs()) / WavesPerWorkgroup);
47
48 const unsigned Granularity = std::max(LDSAllocationGranularity, 1u);
49 return alignDown(std::min(getLocalMemorySize() / WorkGroupsPerCU,
51 Granularity);
52}
53
55 uint32_t LDSBytes, std::pair<unsigned, unsigned> FlatWorkGroupSizes) const {
56
57 // LDS granularity accounted for by aligning the queried LDS size to the
58 // allocation block size.
59 const unsigned Granularity = std::max(LDSAllocationGranularity, 1u);
60 LDSBytes = alignTo(LDSBytes, Granularity);
61 const unsigned MaxWGsLDS = getLocalMemorySize() / std::max(LDSBytes, 1u);
62
63 // Queried LDS size may be larger than available on a CU, in which case we
64 // consider the only achievable occupancy to be 1, in line with what we
65 // consider the occupancy to be when the number of requested registers in a
66 // particular bank is higher than the number of available ones in that bank.
67 if (!MaxWGsLDS)
68 return {1, 1};
69
70 const unsigned WaveSize = getWavefrontSize(), WavesPerEU = getMaxWavesPerEU();
71
72 auto PropsFromWGSize = [=](unsigned WGSize)
73 -> std::tuple<const unsigned, const unsigned, unsigned> {
74 unsigned WavesPerWG = divideCeil(WGSize, WaveSize);
75 unsigned WGsPerCU = std::min(getMaxWorkGroupsPerCU(WGSize), MaxWGsLDS);
76 return {WavesPerWG, WGsPerCU, WavesPerWG * WGsPerCU};
77 };
78
79 // The maximum group size will generally yield the minimum number of
80 // workgroups, maximum number of waves, and minimum occupancy. The opposite is
81 // generally true for the minimum group size. LDS or barrier ressource
82 // limitations can flip those minimums/maximums.
83 const auto [MinWGSize, MaxWGSize] = FlatWorkGroupSizes;
84 auto [MinWavesPerWG, MaxWGsPerCU, MaxWavesPerCU] = PropsFromWGSize(MinWGSize);
85 auto [MaxWavesPerWG, MinWGsPerCU, MinWavesPerCU] = PropsFromWGSize(MaxWGSize);
86
87 // It is possible that we end up with flipped minimum and maximum number of
88 // waves per CU when the number of minimum/maximum concurrent groups on the CU
89 // is limited by LDS usage or barrier resources.
90 if (MinWavesPerCU >= MaxWavesPerCU) {
91 std::swap(MinWavesPerCU, MaxWavesPerCU);
92 } else {
93 const unsigned WaveSlotsPerCU = WavesPerEU * getNumWorkGroupSIMDs();
94
95 // Look for a potential smaller group size than the maximum which decreases
96 // the concurrent number of waves on the CU for the same number of
97 // concurrent workgroups on the CU.
98 unsigned MinWavesPerCUForWGSize =
99 divideCeil(WaveSlotsPerCU, MinWGsPerCU + 1) * MinWGsPerCU;
100 if (MinWavesPerCU > MinWavesPerCUForWGSize) {
101 unsigned ExcessSlots = MinWavesPerCU - MinWavesPerCUForWGSize;
102 if (unsigned ExcessSlotsPerWG = ExcessSlots / MinWGsPerCU) {
103 // There may exist a smaller group size than the maximum that achieves
104 // the minimum number of waves per CU. This group size is the largest
105 // possible size that requires MaxWavesPerWG - E waves where E is
106 // maximized under the following constraints.
107 // 1. 0 <= E <= ExcessSlotsPerWG
108 // 2. (MaxWavesPerWG - E) * WaveSize >= MinWGSize
109 MinWavesPerCU -= MinWGsPerCU * std::min(ExcessSlotsPerWG,
110 MaxWavesPerWG - MinWavesPerWG);
111 }
112 }
113
114 // Look for a potential larger group size than the minimum which increases
115 // the concurrent number of waves on the CU for the same number of
116 // concurrent workgroups on the CU.
117 unsigned LeftoverSlots = WaveSlotsPerCU - MaxWGsPerCU * MinWavesPerWG;
118 if (unsigned LeftoverSlotsPerWG = LeftoverSlots / MaxWGsPerCU) {
119 // There may exist a larger group size than the minimum that achieves the
120 // maximum number of waves per CU. This group size is the smallest
121 // possible size that requires MinWavesPerWG + L waves where L is
122 // maximized under the following constraints.
123 // 1. 0 <= L <= LeftoverSlotsPerWG
124 // 2. (MinWavesPerWG + L - 1) * WaveSize <= MaxWGSize
125 MaxWavesPerCU += MaxWGsPerCU * std::min(LeftoverSlotsPerWG,
126 ((MaxWGSize - 1) / WaveSize) + 1 -
127 MinWavesPerWG);
128 }
129 }
130
131 // Return the minimum/maximum number of waves on any EU, assuming that all
132 // wavefronts are spread across all EUs as evenly as possible.
133 return {std::clamp(MinWavesPerCU / getNumWorkGroupSIMDs(), 1U, WavesPerEU),
134 std::clamp(divideCeil(MaxWavesPerCU, getNumWorkGroupSIMDs()), 1U,
135 WavesPerEU)};
136}
137
139 const MachineFunction &MF) const {
140 const auto *MFI = MF.getInfo<SIMachineFunctionInfo>();
141 return getOccupancyWithWorkGroupSizes(MFI->getLDSSize(), MF.getFunction());
142}
143
144std::pair<unsigned, unsigned>
146 switch (CC) {
153 return std::pair(1, getWavefrontSize());
154 default:
155 return std::pair(1u, getMaxFlatWorkGroupSize());
156 }
157}
158
159std::pair<unsigned, unsigned> AMDGPUSubtarget::getFlatWorkGroupSizes(
160 const Function &F) const {
161 // Default minimum/maximum flat work group sizes.
162 std::pair<unsigned, unsigned> Default =
163 getDefaultFlatWorkGroupSize(F.getCallingConv());
164
165 // Requested minimum/maximum flat work group sizes.
166 std::pair<unsigned, unsigned> Requested = AMDGPU::getIntegerPairAttribute(
167 F, "amdgpu-flat-work-group-size", Default);
168
169 // Make sure requested minimum is less than requested maximum.
170 if (Requested.first > Requested.second)
171 return Default;
172
173 // Make sure requested values do not violate subtarget's specifications.
174 if (Requested.first < getMinFlatWorkGroupSize())
175 return Default;
176 if (Requested.second > getMaxFlatWorkGroupSize())
177 return Default;
178
179 return Requested;
180}
181
185
186std::pair<unsigned, unsigned> AMDGPUSubtarget::getEffectiveWavesPerEU(
187 std::pair<unsigned, unsigned> RequestedWavesPerEU,
188 std::pair<unsigned, unsigned> FlatWorkGroupSizes, unsigned LDSBytes) const {
189 // Default minimum/maximum number of waves per EU. The range of flat workgroup
190 // sizes limits the achievable maximum, and we aim to support enough waves per
191 // EU so that we can concurrently execute all waves of a single workgroup of
192 // maximum size on a CU.
193 std::pair<unsigned, unsigned> Default = {
194 getWavesPerEUForWorkGroup(FlatWorkGroupSizes.second),
195 getOccupancyWithWorkGroupSizes(LDSBytes, FlatWorkGroupSizes).second};
196 Default.first = std::min(Default.first, Default.second);
197
198 // Make sure requested minimum is within the default range and lower than the
199 // requested maximum. The latter must not violate target specification.
200 if (RequestedWavesPerEU.first < Default.first ||
201 RequestedWavesPerEU.first > Default.second ||
202 RequestedWavesPerEU.first > RequestedWavesPerEU.second ||
203 RequestedWavesPerEU.second > getMaxWavesPerEU())
204 return Default;
205
206 // We cannot exceed maximum occupancy implied by flat workgroup size and LDS.
207 RequestedWavesPerEU.second =
208 std::min(RequestedWavesPerEU.second, Default.second);
209 return RequestedWavesPerEU;
210}
211
212std::pair<unsigned, unsigned>
214 // Default/requested minimum/maximum flat work group sizes.
215 std::pair<unsigned, unsigned> FlatWorkGroupSizes = getFlatWorkGroupSizes(F);
216 // Minimum number of bytes allocated in the LDS.
217 unsigned LDSBytes =
218 AMDGPU::getIntegerPairAttribute(F, "amdgpu-lds-size", {0, UINT32_MAX},
219 /*OnlyFirstRequired=*/true)
220 .first;
221 return getWavesPerEU(FlatWorkGroupSizes, LDSBytes, F);
222}
223
224std::pair<unsigned, unsigned>
225AMDGPUSubtarget::getWavesPerEU(std::pair<unsigned, unsigned> FlatWorkGroupSizes,
226 unsigned LDSBytes, const Function &F) const {
227 // Default minimum/maximum number of waves per execution unit.
228 std::pair<unsigned, unsigned> Default(1, getMaxWavesPerEU());
229
230 // Requested minimum/maximum number of waves per execution unit.
231 std::pair<unsigned, unsigned> Requested =
232 AMDGPU::getIntegerPairAttribute(F, "amdgpu-waves-per-eu", Default, true);
233 return getEffectiveWavesPerEU(Requested, FlatWorkGroupSizes, LDSBytes);
234}
235
236std::optional<unsigned>
238 unsigned Dim) const {
239 auto *Node = Kernel.getMetadata("reqd_work_group_size");
240 if (Node && Node->getNumOperands() == 3)
241 return static_cast<unsigned>(
242 mdconst::extract<ConstantInt>(Node->getOperand(Dim))->getZExtValue());
243 return std::nullopt;
244}
245
247 const Function &F, bool RequiresUniformYZ) const {
248 auto *Node = F.getMetadata("reqd_work_group_size");
249 if (!Node || Node->getNumOperands() != 3)
250 return false;
251 uint64_t XLen =
252 mdconst::extract<ConstantInt>(Node->getOperand(0))->getZExtValue();
253 uint64_t YLen =
254 mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue();
255 uint64_t ZLen =
256 mdconst::extract<ConstantInt>(Node->getOperand(2))->getZExtValue();
257
258 bool Is1D = YLen <= 1 && ZLen <= 1;
259 bool IsXLargeEnough =
260 isPowerOf2_64(XLen) && (!RequiresUniformYZ || XLen >= getWavefrontSize());
261 return Is1D || IsXLargeEnough;
262}
263
265 return isMesa3DOS() && !AMDGPU::isShader(F.getCallingConv());
266}
267
269 unsigned Dimension) const {
270 std::optional<unsigned> ReqdSize = getReqdWorkGroupSize(Kernel, Dimension);
271 if (ReqdSize)
272 return *ReqdSize - 1;
273 return getFlatWorkGroupSizes(Kernel).second - 1;
274}
275
277 for (int I = 0; I < 3; ++I) {
278 if (getMaxWorkitemID(Func, I) > 0)
279 return false;
280 }
281
282 // If the function may call the WWM intrinsic, just return false as
283 // all threads will be active at some point
284 if (!Func.hasFnAttribute("amdgpu-no-wwm"))
285 return false;
286
287 return true;
288}
289
291 Function *Kernel = I->getFunction();
292 unsigned MinSize = 0;
293 unsigned MaxSize = getFlatWorkGroupSizes(*Kernel).second;
294 bool IdQuery = false;
295
296 // If reqd_work_group_size is present it narrows value down.
297 if (auto *CI = dyn_cast<CallInst>(I)) {
298 const Function *F = CI->getCalledFunction();
299 if (F) {
300 unsigned Dim = UINT_MAX;
301 switch (F->getIntrinsicID()) {
302 case Intrinsic::amdgcn_workitem_id_x:
303 case Intrinsic::r600_read_tidig_x:
304 IdQuery = true;
305 [[fallthrough]];
306 case Intrinsic::r600_read_local_size_x:
307 Dim = 0;
308 break;
309 case Intrinsic::amdgcn_workitem_id_y:
310 case Intrinsic::r600_read_tidig_y:
311 IdQuery = true;
312 [[fallthrough]];
313 case Intrinsic::r600_read_local_size_y:
314 Dim = 1;
315 break;
316 case Intrinsic::amdgcn_workitem_id_z:
317 case Intrinsic::r600_read_tidig_z:
318 IdQuery = true;
319 [[fallthrough]];
320 case Intrinsic::r600_read_local_size_z:
321 Dim = 2;
322 break;
323 default:
324 break;
325 }
326
327 if (Dim <= 3) {
328 std::optional<unsigned> ReqdSize = getReqdWorkGroupSize(*Kernel, Dim);
329 if (ReqdSize)
330 MinSize = MaxSize = *ReqdSize;
331 }
332 }
333 }
334
335 if (!MaxSize)
336 return false;
337
338 // Range metadata is [Lo, Hi). For ID query we need to pass max size
339 // as Hi. For size query we need to pass Hi + 1.
340 if (IdQuery)
341 MinSize = 0;
342 else
343 ++MaxSize;
344
345 APInt Lower{32, MinSize};
346 APInt Upper{32, MaxSize};
347 if (auto *CI = dyn_cast<CallBase>(I)) {
349 CI->addRangeRetAttr(Range);
350 } else {
351 MDBuilder MDB(I->getContext());
352 MDNode *MaxWorkGroupSizeRange = MDB.createRange(Lower, Upper);
353 I->setMetadata(LLVMContext::MD_range, MaxWorkGroupSizeRange);
354 }
355 return true;
356}
357
359
360 // We don't allocate the segment if we know the implicit arguments weren't
361 // used, even if the ABI implies we need them.
362 if (F.hasFnAttribute("amdgpu-no-implicitarg-ptr"))
363 return 0;
364
365 if (isMesaKernel(F))
366 return 16;
367
368 // Assume all implicit inputs are used by default
369 const Module *M = F.getParent();
370 unsigned NBytes =
372 return static_cast<unsigned>(
373 F.getFnAttributeAsParsedInteger("amdgpu-implicitarg-num-bytes", NBytes));
374}
375
377 Align &MaxAlign) const {
378 assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
379 F.getCallingConv() == CallingConv::SPIR_KERNEL);
380
381 const DataLayout &DL = F.getDataLayout();
382 uint64_t ExplicitArgBytes = 0;
383 MaxAlign = Align(1);
384
385 for (const Argument &Arg : F.args()) {
386 if (Arg.hasAttribute("amdgpu-hidden-argument"))
387 continue;
388
389 const bool IsByRef = Arg.hasByRefAttr();
390 Type *ArgTy = IsByRef ? Arg.getParamByRefType() : Arg.getType();
391 Align Alignment = DL.getValueOrABITypeAlignment(
392 IsByRef ? Arg.getParamAlign() : std::nullopt, ArgTy);
393 uint64_t AllocSize = DL.getTypeAllocSize(ArgTy);
394 ExplicitArgBytes = alignTo(ExplicitArgBytes, Alignment) + AllocSize;
395 MaxAlign = std::max(MaxAlign, Alignment);
396 }
397
398 return ExplicitArgBytes;
399}
400
402 Align &MaxAlign) const {
403 if (F.getCallingConv() != CallingConv::AMDGPU_KERNEL &&
404 F.getCallingConv() != CallingConv::SPIR_KERNEL)
405 return 0;
406
407 uint64_t ExplicitArgBytes = getExplicitKernArgSize(F, MaxAlign);
408
409 unsigned ExplicitOffset = getExplicitKernelArgOffset();
410
411 uint64_t TotalSize = ExplicitOffset + ExplicitArgBytes;
412 unsigned ImplicitBytes = getImplicitArgNumBytes(F);
413 if (ImplicitBytes != 0) {
414 const Align Alignment = getAlignmentForImplicitArgPtr();
415 TotalSize = alignTo(ExplicitArgBytes, Alignment) + ImplicitBytes;
416 MaxAlign = std::max(MaxAlign, Alignment);
417 }
418
419 // Being able to dereference past the end is useful for emitting scalar loads.
420 return static_cast<unsigned>(alignTo(TotalSize, 4));
421}
422
427
430 return static_cast<const AMDGPUSubtarget&>(MF.getSubtarget<GCNSubtarget>());
431 return static_cast<const AMDGPUSubtarget &>(MF.getSubtarget<R600Subtarget>());
432}
433
435 if (TM.getTargetTriple().isAMDGCN())
436 return static_cast<const AMDGPUSubtarget&>(TM.getSubtarget<GCNSubtarget>(F));
437 return static_cast<const AMDGPUSubtarget &>(
439}
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
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
AMDGPU R600 specific subclass of TargetSubtarget.
RISCVCC::CondCode CC
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
Class for arbitrary precision integers.
Definition APInt.h:78
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
This class represents a range of values.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
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).
Definition MDBuilder.cpp:92
Metadata node.
Definition Metadata.h:1081
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.
Definition Module.h:68
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.
Definition Triple.h:996
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
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.
Definition CallingConv.h:24
@ 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.
Definition Metadata.h:679
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.
Definition Casting.h:643
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.
Definition MathExtras.h:546
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39