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