LLVM 24.0.0git
AMDGPULowerKernelAttributes.cpp
Go to the documentation of this file.
1//===-- AMDGPULowerKernelAttributes.cpp------------------------------------===//
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 This pass does attempts to make use of reqd_work_group_size metadata
10/// to eliminate loads from the dispatch packet and to constant fold OpenCL
11/// get_local_size-like functions.
12//
13//===----------------------------------------------------------------------===//
14
15#include "AMDGPU.h"
19#include "llvm/CodeGen/Passes.h"
20#include "llvm/IR/Constants.h"
21#include "llvm/IR/Function.h"
22#include "llvm/IR/IRBuilder.h"
25#include "llvm/IR/IntrinsicsAMDGPU.h"
26#include "llvm/IR/MDBuilder.h"
28#include "llvm/Pass.h"
29
30#define DEBUG_TYPE "amdgpu-lower-kernel-attributes"
31
32using namespace llvm;
33
34namespace {
35
36// Field offsets in hsa_kernel_dispatch_packet_t.
37enum DispatchPackedOffsets {
38 WORKGROUP_SIZE_X = 4,
39 WORKGROUP_SIZE_Y = 6,
40 WORKGROUP_SIZE_Z = 8,
41
42 GRID_SIZE_X = 12,
43 GRID_SIZE_Y = 16,
44 GRID_SIZE_Z = 20
45};
46
47// Field offsets to implicit kernel argument pointer.
48enum ImplicitArgOffsets {
49 HIDDEN_BLOCK_COUNT_X = 0,
50 HIDDEN_BLOCK_COUNT_Y = 4,
51 HIDDEN_BLOCK_COUNT_Z = 8,
52
53 HIDDEN_GROUP_SIZE_X = 12,
54 HIDDEN_GROUP_SIZE_Y = 14,
55 HIDDEN_GROUP_SIZE_Z = 16,
56
57 HIDDEN_REMAINDER_X = 18,
58 HIDDEN_REMAINDER_Y = 20,
59 HIDDEN_REMAINDER_Z = 22,
60
61 GRID_DIMS = 64
62};
63
64class AMDGPULowerKernelAttributes : public ModulePass {
65public:
66 static char ID;
67
68 AMDGPULowerKernelAttributes() : ModulePass(ID) {}
69
70 bool runOnModule(Module &M) override;
71
72 StringRef getPassName() const override { return "AMDGPU Kernel Attributes"; }
73
74 void getAnalysisUsage(AnalysisUsage &AU) const override {
75 AU.setPreservesAll();
76 }
77};
78
79Function *getBasePtrIntrinsic(Module &M, bool IsV5OrAbove) {
80 auto IntrinsicId = IsV5OrAbove ? Intrinsic::amdgcn_implicitarg_ptr
81 : Intrinsic::amdgcn_dispatch_ptr;
82 return Intrinsic::getDeclarationIfExists(&M, IntrinsicId);
83}
84
85} // end anonymous namespace
86
88 uint32_t MaxNumGroups) {
89 if (MaxNumGroups == 0 || MaxNumGroups == std::numeric_limits<uint32_t>::max())
90 return false;
91
92 if (!Load->getType()->isIntegerTy(32))
93 return false;
94
95 // TODO: If there is existing range metadata, preserve it if it is stricter.
96 if (Load->hasMetadata(LLVMContext::MD_range))
97 return false;
98
99 MDBuilder MDB(Load->getContext());
100 MDNode *Range = MDB.createRange(APInt(32, 1), APInt(32, MaxNumGroups + 1));
101 Load->setMetadata(LLVMContext::MD_range, Range);
102 return true;
103}
104
105static bool annotateGroupSizeLoadWithRangeMD(LoadInst *Load, bool IsRemainder) {
106 if (!Load->getType()->isIntegerTy(16))
107 return false;
108
109 // TODO: If there is existing range metadata, preserve it if it is stricter.
110 if (Load->hasMetadata(LLVMContext::MD_range))
111 return false;
112
113 MDBuilder MDB(Load->getContext());
114 MDNode *Range = MDB.createRange(
115 APInt(16, !IsRemainder),
116 APInt(16, AMDGPU::IsaInfo::getMaxFlatWorkGroupSize() + 1 - IsRemainder));
117 Load->setMetadata(LLVMContext::MD_range, Range);
118 return true;
119}
120
122 unsigned KnownNumGridDims) {
123 IntegerType *Ty = dyn_cast<IntegerType>(Load->getType());
124 if (!Ty || Ty->getBitWidth() < 3)
125 return false;
126
127 if (KnownNumGridDims == 3) {
128 Load->replaceAllUsesWith(ConstantInt::get(Load->getType(), 3));
129 return true;
130 }
131
132 // TODO: If there is existing range metadata, preserve it if it is stricter.
133 if (Load->hasMetadata(LLVMContext::MD_range))
134 return false;
135
136 unsigned LowerBound = KnownNumGridDims == 2 ? 2 : 1;
137 MDBuilder MDB(Load->getContext());
138 MDNode *Range = MDB.createRange(APInt(Ty->getBitWidth(), LowerBound),
139 APInt(Ty->getBitWidth(), 4));
140 Load->setMetadata(LLVMContext::MD_range, Range);
141 return true;
142}
143
144/// Compute the known number of grid dimensions based on !reqd_work_group_size
145/// metadata. Returns 3 if the grid is known to be exactly 3-D, 2 if it is
146/// known to be at least 2-D, or 0 if nothing more than the default [1, 3]
147/// range can be deduced.
148static unsigned computeNumGridDims(const MDNode *ReqdWorkGroupSize) {
149 ConstantInt *KnownZ =
150 mdconst::extract<ConstantInt>(ReqdWorkGroupSize->getOperand(2));
151 if (KnownZ->getZExtValue() != 1)
152 return 3;
153
154 ConstantInt *KnownY =
155 mdconst::extract<ConstantInt>(ReqdWorkGroupSize->getOperand(1));
156 if (KnownY->getZExtValue() != 1)
157 return 2;
158
159 return 0;
160}
161
162static bool processUse(CallInst *CI, bool IsV5OrAbove) {
163 Function *F = CI->getFunction();
164
165 auto *MD = F->getMetadata("reqd_work_group_size");
166 const bool HasReqdWorkGroupSize = MD && MD->getNumOperands() == 3;
167
168 const bool HasUniformWorkGroupSize =
169 F->hasFnAttribute("uniform-work-group-size");
170
171 SmallVector<unsigned> MaxNumWorkgroups =
172 AMDGPU::getIntegerVecAttribute(*F, "amdgpu-max-num-workgroups",
173 /*Size=*/3, /*DefaultVal=*/0);
174
175 Value *BlockCounts[3] = {nullptr, nullptr, nullptr};
176 Value *GroupSizes[3] = {nullptr, nullptr, nullptr};
177 Value *Remainders[3] = {nullptr, nullptr, nullptr};
178 Value *GridSizes[3] = {nullptr, nullptr, nullptr};
179
180 const DataLayout &DL = F->getDataLayout();
181 bool MadeChange = false;
182
183 unsigned KnownNumGridDims = HasReqdWorkGroupSize ? computeNumGridDims(MD) : 0;
184
185 // We expect to see several GEP users, casted to the appropriate type and
186 // loaded.
187 for (User *U : CI->users()) {
188 if (!U->hasOneUse())
189 continue;
190
191 int64_t Offset = 0;
192 auto *Load = dyn_cast<LoadInst>(U); // Load from ImplicitArgPtr/DispatchPtr?
193 auto *BCI = dyn_cast<BitCastInst>(U);
194 if (!Load && !BCI) {
196 continue;
197 Load = dyn_cast<LoadInst>(*U->user_begin()); // Load from GEP?
198 BCI = dyn_cast<BitCastInst>(*U->user_begin());
199 }
200
201 if (BCI) {
202 if (!BCI->hasOneUse())
203 continue;
204 Load = dyn_cast<LoadInst>(*BCI->user_begin()); // Load from BCI?
205 }
206
207 if (!Load || !Load->isSimple())
208 continue;
209
210 unsigned LoadSize = DL.getTypeStoreSize(Load->getType());
211
212 // TODO: Handle merged loads.
213 if (IsV5OrAbove) { // Base is ImplicitArgPtr.
214 switch (Offset) {
215 case HIDDEN_BLOCK_COUNT_X:
216 if (LoadSize == 4) {
217 BlockCounts[0] = Load;
218 MadeChange |=
219 annotateGridSizeLoadWithRangeMD(Load, MaxNumWorkgroups[0]);
220 }
221 break;
222 case HIDDEN_BLOCK_COUNT_Y:
223 if (LoadSize == 4) {
224 BlockCounts[1] = Load;
225 MadeChange |=
226 annotateGridSizeLoadWithRangeMD(Load, MaxNumWorkgroups[1]);
227 }
228 break;
229 case HIDDEN_BLOCK_COUNT_Z:
230 if (LoadSize == 4) {
231 BlockCounts[2] = Load;
232 MadeChange |=
233 annotateGridSizeLoadWithRangeMD(Load, MaxNumWorkgroups[2]);
234 }
235 break;
236 case HIDDEN_GROUP_SIZE_X:
237 if (LoadSize == 2) {
238 GroupSizes[0] = Load;
239 MadeChange |= annotateGroupSizeLoadWithRangeMD(Load, false);
240 }
241 break;
242 case HIDDEN_GROUP_SIZE_Y:
243 if (LoadSize == 2) {
244 GroupSizes[1] = Load;
245 MadeChange |= annotateGroupSizeLoadWithRangeMD(Load, false);
246 }
247 break;
248 case HIDDEN_GROUP_SIZE_Z:
249 if (LoadSize == 2) {
250 GroupSizes[2] = Load;
251 MadeChange |= annotateGroupSizeLoadWithRangeMD(Load, false);
252 }
253 break;
254 case HIDDEN_REMAINDER_X:
255 if (LoadSize == 2) {
256 Remainders[0] = Load;
257 MadeChange |= annotateGroupSizeLoadWithRangeMD(Load, true);
258 }
259 break;
260 case HIDDEN_REMAINDER_Y:
261 if (LoadSize == 2) {
262 Remainders[1] = Load;
263 MadeChange |= annotateGroupSizeLoadWithRangeMD(Load, true);
264 }
265 break;
266 case HIDDEN_REMAINDER_Z:
267 if (LoadSize == 2) {
268 Remainders[2] = Load;
269 MadeChange |= annotateGroupSizeLoadWithRangeMD(Load, true);
270 }
271 break;
272
273 case GRID_DIMS:
274 if (LoadSize <= 2)
275 MadeChange |= annotateGridDimsLoadWithRangeMD(Load, KnownNumGridDims);
276 break;
277 default:
278 break;
279 }
280 } else { // Base is DispatchPtr.
281 switch (Offset) {
282 case WORKGROUP_SIZE_X:
283 if (LoadSize == 2)
284 GroupSizes[0] = Load;
285 break;
286 case WORKGROUP_SIZE_Y:
287 if (LoadSize == 2)
288 GroupSizes[1] = Load;
289 break;
290 case WORKGROUP_SIZE_Z:
291 if (LoadSize == 2)
292 GroupSizes[2] = Load;
293 break;
294 case GRID_SIZE_X:
295 if (LoadSize == 4)
296 GridSizes[0] = Load;
297 break;
298 case GRID_SIZE_Y:
299 if (LoadSize == 4)
300 GridSizes[1] = Load;
301 break;
302 case GRID_SIZE_Z:
303 if (LoadSize == 4)
304 GridSizes[2] = Load;
305 break;
306 default:
307 break;
308 }
309 }
310 }
311
312 if (IsV5OrAbove && HasUniformWorkGroupSize) {
313 // Under v5 __ockl_get_local_size returns the value computed by the
314 // expression:
315 //
316 // workgroup_id < hidden_block_count ? hidden_group_size :
317 // hidden_remainder
318 //
319 // For functions with the attribute uniform-work-group-size=true. we can
320 // evaluate workgroup_id < hidden_block_count as true, and thus
321 // hidden_group_size is returned for __ockl_get_local_size.
322 for (int I = 0; I < 3; ++I) {
323 Value *BlockCount = BlockCounts[I];
324 if (!BlockCount)
325 continue;
326
327 using namespace llvm::PatternMatch;
328 auto GroupIDIntrin =
332
333 for (User *ICmp : BlockCount->users()) {
334 if (match(ICmp, m_SpecificICmp(ICmpInst::ICMP_ULT, GroupIDIntrin,
335 m_Specific(BlockCount)))) {
336 ICmp->replaceAllUsesWith(llvm::ConstantInt::getTrue(ICmp->getType()));
337 MadeChange = true;
338 }
339 }
340 }
341
342 // All remainders should be 0 with uniform work group size.
343 for (Value *Remainder : Remainders) {
344 if (!Remainder)
345 continue;
346 Remainder->replaceAllUsesWith(
347 Constant::getNullValue(Remainder->getType()));
348 MadeChange = true;
349 }
350 } else if (HasUniformWorkGroupSize) { // Pre-V5.
351 // Pattern match the code used to handle partial workgroup dispatches in the
352 // library implementation of get_local_size, so the entire function can be
353 // constant folded with a known group size.
354 //
355 // uint r = grid_size - group_id * group_size;
356 // get_local_size = (r < group_size) ? r : group_size;
357 //
358 // If we have uniform-work-group-size (which is the default in OpenCL 1.2),
359 // the grid_size is required to be a multiple of group_size). In this case:
360 //
361 // grid_size - (group_id * group_size) < group_size
362 // ->
363 // grid_size < group_size + (group_id * group_size)
364 //
365 // (grid_size / group_size) < 1 + group_id
366 //
367 // grid_size / group_size is at least 1, so we can conclude the select
368 // condition is false (except for group_id == 0, where the select result is
369 // the same).
370 for (int I = 0; I < 3; ++I) {
371 Value *GroupSize = GroupSizes[I];
372 Value *GridSize = GridSizes[I];
373 if (!GroupSize || !GridSize)
374 continue;
375
376 using namespace llvm::PatternMatch;
377 auto GroupIDIntrin =
381
382 for (User *U : GroupSize->users()) {
383 auto *ZextGroupSize = dyn_cast<ZExtInst>(U);
384 if (!ZextGroupSize)
385 continue;
386
387 for (User *UMin : ZextGroupSize->users()) {
388 if (match(UMin, m_UMin(m_Sub(m_Specific(GridSize),
389 m_Mul(GroupIDIntrin,
390 m_Specific(ZextGroupSize))),
391 m_Specific(ZextGroupSize)))) {
392 if (HasReqdWorkGroupSize) {
393 ConstantInt *KnownSize =
394 mdconst::extract<ConstantInt>(MD->getOperand(I));
395 UMin->replaceAllUsesWith(ConstantFoldIntegerCast(
396 KnownSize, UMin->getType(), false, DL));
397 } else {
398 UMin->replaceAllUsesWith(ZextGroupSize);
399 }
400
401 MadeChange = true;
402 }
403 }
404 }
405 }
406 }
407
408 // Upgrade the old method of calculating the block size using the grid size.
409 // We pattern match any case where the implicit argument group size is the
410 // divisor to a dispatch packet grid size read of the same dimension.
411 if (IsV5OrAbove) {
412 for (int I = 0; I < 3; I++) {
413 Value *GroupSize = GroupSizes[I];
414 if (!GroupSize || !GroupSize->getType()->isIntegerTy(16))
415 continue;
416
417 for (User *U : GroupSize->users()) {
419 if (isa<ZExtInst>(Inst) && !Inst->use_empty())
420 Inst = cast<Instruction>(*Inst->user_begin());
421
422 using namespace llvm::PatternMatch;
423 if (!match(
424 Inst,
427 m_SpecificInt(GRID_SIZE_X + I * sizeof(uint32_t))))),
428 m_Value())))
429 continue;
430
431 IRBuilder<> Builder(Inst);
432
433 Value *GEP = Builder.CreateInBoundsGEP(
434 Builder.getInt8Ty(), CI,
435 {ConstantInt::get(Type::getInt64Ty(CI->getContext()),
436 HIDDEN_BLOCK_COUNT_X + I * sizeof(uint32_t))});
437 Instruction *BlockCount = Builder.CreateLoad(Builder.getInt32Ty(), GEP);
438 BlockCount->setMetadata(LLVMContext::MD_invariant_load,
439 MDNode::get(CI->getContext(), {}));
440 BlockCount->setMetadata(LLVMContext::MD_noundef,
441 MDNode::get(CI->getContext(), {}));
442
443 Value *BlockCountExt = Builder.CreateZExt(BlockCount, Inst->getType());
444 Inst->replaceAllUsesWith(BlockCountExt);
445 Inst->eraseFromParent();
446 MadeChange = true;
447 }
448 }
449 }
450
451 // If reqd_work_group_size is set, we can replace work group size with it.
452 if (!HasReqdWorkGroupSize)
453 return MadeChange;
454
455 for (int I = 0; I < 3; I++) {
456 Value *GroupSize = GroupSizes[I];
457 if (!GroupSize)
458 continue;
459
460 ConstantInt *KnownSize = mdconst::extract<ConstantInt>(MD->getOperand(I));
461 GroupSize->replaceAllUsesWith(
462 ConstantFoldIntegerCast(KnownSize, GroupSize->getType(), false, DL));
463 MadeChange = true;
464 }
465
466 return MadeChange;
467}
468
469// TODO: Move makeLIDRangeMetadata usage into here. Seem to not get
470// TargetPassConfig for subtarget.
471bool AMDGPULowerKernelAttributes::runOnModule(Module &M) {
472 bool MadeChange = false;
473 bool IsV5OrAbove =
475 Function *BasePtr = getBasePtrIntrinsic(M, IsV5OrAbove);
476
477 if (!BasePtr) // ImplicitArgPtr/DispatchPtr not used.
478 return false;
479
480 SmallPtrSet<Instruction *, 4> HandledUses;
481 for (auto *U : BasePtr->users()) {
482 CallInst *CI = cast<CallInst>(U);
483 if (HandledUses.insert(CI).second) {
484 if (processUse(CI, IsV5OrAbove))
485 MadeChange = true;
486 }
487 }
488
489 return MadeChange;
490}
491
492INITIALIZE_PASS_BEGIN(AMDGPULowerKernelAttributes, DEBUG_TYPE,
493 "AMDGPU Kernel Attributes", false, false)
494INITIALIZE_PASS_END(AMDGPULowerKernelAttributes, DEBUG_TYPE,
495 "AMDGPU Kernel Attributes", false, false)
496
497char AMDGPULowerKernelAttributes::ID = 0;
498
500 return new AMDGPULowerKernelAttributes();
501}
502
505 bool IsV5OrAbove =
507 Function *BasePtr = getBasePtrIntrinsic(*F.getParent(), IsV5OrAbove);
508
509 if (!BasePtr) // ImplicitArgPtr/DispatchPtr not used.
510 return PreservedAnalyses::all();
511
512 bool Changed = false;
513 for (Instruction &I : instructions(F)) {
514 if (CallInst *CI = dyn_cast<CallInst>(&I)) {
515 if (CI->getCalledFunction() == BasePtr)
516 Changed |= processUse(CI, IsV5OrAbove);
517 }
518 }
519
522}
static bool annotateGridSizeLoadWithRangeMD(LoadInst *Load, uint32_t MaxNumGroups)
static unsigned computeNumGridDims(const MDNode *ReqdWorkGroupSize)
Compute the known number of grid dimensions based on !reqd_work_group_size metadata.
static bool annotateGroupSizeLoadWithRangeMD(LoadInst *Load, bool IsRemainder)
static bool annotateGridDimsLoadWithRangeMD(LoadInst *Load, unsigned KnownNumGridDims)
static bool processUse(CallInst *CI, bool IsV5OrAbove)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define DEBUG_TYPE
Hexagon Common GEP
#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))
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
Class for arbitrary precision integers.
Definition APInt.h:78
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
This class represents a function call, abstracting a target machine's calling convention.
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
This is the shared class of boolean and integer constants.
Definition Constants.h:87
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
Class to represent integer types.
An instruction for reading from memory.
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
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1565
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
user_iterator user_begin()
Definition Value.h:402
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
iterator_range< user_iterator > users()
Definition Value.h:426
bool use_empty() const
Definition Value.h:346
Changed
constexpr unsigned getMaxFlatWorkGroupSize()
unsigned getAMDHSACodeObjectVersion(const Module &M)
SmallVector< unsigned > getIntegerVecAttribute(const Function &F, StringRef Name, unsigned Size, unsigned DefaultVal)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
match_combine_or< CastInst_match< OpTy, ZExtInst >, OpTy > m_ZExtOrSelf(const OpTy &Op)
LoadSimple_match< OpTy > m_LoadSimple(const OpTy &Op)
bool match(Val *V, const Pattern &P)
auto m_UMin(const Opnd0 &Op0, const Opnd1 &Op1)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
auto m_GEP(const OperandTypes &...Ops)
Matches GetElementPtrInst.
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::UDiv > m_UDiv(const LHS &L, const RHS &R)
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
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.
@ Offset
Definition DWP.cpp:578
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
ModulePass * createAMDGPULowerKernelAttributesPass()
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...
Definition Casting.h:547
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI Constant * ConstantFoldIntegerCast(Constant *C, Type *DestTy, bool IsSigned, const DataLayout &DL)
Constant fold a zext, sext or trunc, depending on IsSigned and whether the DestTy is wider or narrowe...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)