LLVM 24.0.0git
AMDGPULowerKernelArguments.cpp
Go to the documentation of this file.
1//===-- AMDGPULowerKernelArguments.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 replaces accesses to kernel arguments with loads from
10/// offsets from the kernarg base pointer.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPU.h"
15#include "GCNSubtarget.h"
21#include "llvm/IR/Argument.h"
22#include "llvm/IR/Attributes.h"
23#include "llvm/IR/Dominators.h"
24#include "llvm/IR/IRBuilder.h"
26#include "llvm/IR/Instruction.h"
28#include "llvm/IR/IntrinsicsAMDGPU.h"
29#include "llvm/IR/LLVMContext.h"
30#include "llvm/IR/MDBuilder.h"
32#include <optional>
33
34#define DEBUG_TYPE "amdgpu-lower-kernel-arguments"
35
36using namespace llvm;
37
38namespace {
39
40class AMDGPULowerKernelArguments : public FunctionPass {
41public:
42 static char ID;
43
44 AMDGPULowerKernelArguments() : FunctionPass(ID) {}
45
46 bool runOnFunction(Function &F) override;
47
48 void getAnalysisUsage(AnalysisUsage &AU) const override {
51 AU.setPreservesAll();
52 }
53};
54
55} // end anonymous namespace
56
57// skip allocas
60 for (BasicBlock::iterator E = BB.end(); InsPt != E; ++InsPt) {
61 AllocaInst *AI = dyn_cast<AllocaInst>(&*InsPt);
62
63 // If this is a dynamic alloca, the value may depend on the loaded kernargs,
64 // so loads will need to be inserted before it.
65 if (!AI || !AI->isStaticAlloca())
66 break;
67 }
68
69 return InsPt;
70}
71
73 DominatorTree &DT) {
74 // Collect noalias arguments.
76
77 for (Argument &Arg : F.args())
78 if (Arg.hasNoAliasAttr() && !Arg.use_empty())
79 NoAliasArgs.push_back(&Arg);
80
81 if (NoAliasArgs.empty())
82 return;
83
84 // Add alias scopes for each noalias argument.
85 MDBuilder MDB(F.getContext());
87 MDNode *NewDomain = MDB.createAnonymousAliasScopeDomain(F.getName());
88
89 for (unsigned I = 0u; I < NoAliasArgs.size(); ++I) {
90 const Argument *Arg = NoAliasArgs[I];
91 MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain, Arg->getName());
92 NewScopes.insert({Arg, NewScope});
93 }
94
95 // Iterate over all instructions.
96 for (inst_iterator Inst = inst_begin(F), InstEnd = inst_end(F);
97 Inst != InstEnd; ++Inst) {
98 // If instruction accesses memory, collect its pointer arguments.
99 Instruction *I = &(*Inst);
101
102 if (std::optional<MemoryLocation> MO = MemoryLocation::getOrNone(I))
103 PtrArgs.push_back(MO->Ptr);
104 else if (const CallBase *Call = dyn_cast<CallBase>(I)) {
105 if (Call->doesNotAccessMemory())
106 continue;
107
108 for (Value *Arg : Call->args()) {
109 if (!Arg->getType()->isPointerTy())
110 continue;
111
112 PtrArgs.push_back(Arg);
113 }
114 } else {
115 // Not a memory access and not a call — nothing to annotate.
116 continue;
117 }
118
119 // Collect underlying objects of pointer arguments.
123
124 if (!PtrArgs.empty()) {
125 // Trace pointer arguments back to underlying objects and decide which
126 // noalias scopes apply based on provenance and capture analysis.
127 for (const Value *Val : PtrArgs) {
129 getUnderlyingObjects(Val, Objects);
130 ObjSet.insert_range(Objects);
131 }
132
133 bool RequiresNoCaptureBefore = false;
134 bool UsesUnknownObject = false;
135 bool UsesAliasingPtr = false;
136
137 for (const Value *Val : ObjSet) {
138 if (isa<ConstantData>(Val))
139 continue;
140
141 if (const Argument *Arg = dyn_cast<Argument>(Val)) {
142 if (!Arg->hasAttribute(Attribute::NoAlias))
143 UsesAliasingPtr = true;
144 } else
145 UsesAliasingPtr = true;
146
147 if (isEscapeSource(Val))
148 RequiresNoCaptureBefore = true;
149 else if (!isa<Argument>(Val) && isIdentifiedObject(Val))
150 UsesUnknownObject = true;
151 }
152
153 if (UsesUnknownObject)
154 continue;
155
156 // Collect noalias scopes for instruction.
157 for (const Argument *Arg : NoAliasArgs) {
158 if (ObjSet.contains(Arg))
159 continue;
160
161 if (!RequiresNoCaptureBefore ||
163 Arg, false, I, &DT, false, CaptureComponents::Provenance)))
164 NoAliases.push_back(NewScopes[Arg]);
165 }
166
167 // Collect scopes for alias.scope metadata.
168 if (!UsesAliasingPtr)
169 for (const Argument *Arg : NoAliasArgs) {
170 if (ObjSet.count(Arg))
171 Scopes.push_back(NewScopes[Arg]);
172 }
173 } else {
174 // The instruction accesses memory but has no pointer arguments.
175 // Since none of its operands derive from any noalias kernel argument,
176 // it cannot possibly alias them. Mark it as !noalias w.r.t. every
177 // noalias scope so that ScopedNoAliasAA can prove non-aliasing when
178 // other instructions reference those scopes via !alias.scope.
179 for (const Argument *Arg : NoAliasArgs)
180 NoAliases.push_back(NewScopes[Arg]);
181 }
182
183 // Add noalias metadata to instruction.
184 if (!NoAliases.empty()) {
185 MDNode *NewMD =
186 MDNode::concatenate(Inst->getMetadata(LLVMContext::MD_noalias),
187 MDNode::get(F.getContext(), NoAliases));
188 Inst->setMetadata(LLVMContext::MD_noalias, NewMD);
189 }
190
191 // Add alias.scope metadata to instruction.
192 if (!Scopes.empty()) {
193 MDNode *NewMD =
194 MDNode::concatenate(Inst->getMetadata(LLVMContext::MD_alias_scope),
195 MDNode::get(F.getContext(), Scopes));
196 Inst->setMetadata(LLVMContext::MD_alias_scope, NewMD);
197 }
198 }
199}
200
202 DominatorTree &DT) {
203 CallingConv::ID CC = F.getCallingConv();
204 if (CC != CallingConv::AMDGPU_KERNEL || F.arg_empty())
205 return false;
206
207 const GCNSubtarget &ST = TM.getSubtarget<GCNSubtarget>(F);
208 LLVMContext &Ctx = F.getContext();
209 const DataLayout &DL = F.getDataLayout();
210 BasicBlock &EntryBlock = *F.begin();
211 IRBuilder<> Builder(&EntryBlock, getInsertPt(EntryBlock));
212
213 const Align KernArgBaseAlign(16); // FIXME: Increase if necessary
214 const uint64_t BaseOffset = ST.getExplicitKernelArgOffset();
215
216 Align MaxAlign;
217 // FIXME: Alignment is broken with explicit arg offset.;
218 const uint64_t TotalKernArgSize = ST.getKernArgSegmentSize(F, MaxAlign);
219 if (TotalKernArgSize == 0)
220 return false;
221
222 CallInst *KernArgSegment = Builder.CreateIntrinsicWithoutFolding(
223 Intrinsic::amdgcn_kernarg_segment_ptr, {}, nullptr,
224 F.getName() + ".kernarg.segment");
225 KernArgSegment->addRetAttr(Attribute::NonNull);
226 KernArgSegment->addRetAttr(
227 Attribute::getWithDereferenceableBytes(Ctx, TotalKernArgSize));
228
229 uint64_t ExplicitArgOffset = 0;
230
231 addAliasScopeMetadata(F, F.getParent()->getDataLayout(), DT);
232
233 for (Argument &Arg : F.args()) {
234 const bool IsByRef = Arg.hasByRefAttr();
235 Type *ArgTy = IsByRef ? Arg.getParamByRefType() : Arg.getType();
236 MaybeAlign ParamAlign = IsByRef ? Arg.getParamAlign() : std::nullopt;
237 Align ABITypeAlign = DL.getValueOrABITypeAlignment(ParamAlign, ArgTy);
238
239 uint64_t Size = DL.getTypeSizeInBits(ArgTy);
240 uint64_t AllocSize = DL.getTypeAllocSize(ArgTy);
241
242 uint64_t EltOffset = alignTo(ExplicitArgOffset, ABITypeAlign) + BaseOffset;
243 ExplicitArgOffset = alignTo(ExplicitArgOffset, ABITypeAlign) + AllocSize;
244
245 // Skip inreg arguments which should be preloaded.
246 if (Arg.use_empty() || Arg.hasInRegAttr())
247 continue;
248
249 // If this is byval, the loads are already explicit in the function. We just
250 // need to rewrite the pointer values.
251 if (IsByRef) {
252 Value *ArgOffsetPtr = Builder.CreateConstInBoundsGEP1_64(
253 Builder.getInt8Ty(), KernArgSegment, EltOffset,
254 Arg.getName() + ".byval.kernarg.offset");
255
256 Value *CastOffsetPtr =
257 Builder.CreateAddrSpaceCast(ArgOffsetPtr, Arg.getType());
258 Arg.replaceAllUsesWith(CastOffsetPtr);
259 continue;
260 }
261
262 if (PointerType *PT = dyn_cast<PointerType>(ArgTy)) {
263 // FIXME: Hack. We rely on AssertZext to be able to fold DS addressing
264 // modes on SI to know the high bits are 0 so pointer adds don't wrap. We
265 // can't represent this with range metadata because it's only allowed for
266 // integer types.
267 if ((PT->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS ||
268 PT->getAddressSpace() == AMDGPUAS::REGION_ADDRESS) &&
269 !ST.hasUsableDSOffset())
270 continue;
271 }
272
273 auto *VT = dyn_cast<FixedVectorType>(ArgTy);
274 bool IsV3 = VT && VT->getNumElements() == 3;
275 bool DoShiftOpt = Size < 32 && !ArgTy->isAggregateType();
276
277 VectorType *V4Ty = nullptr;
278
279 int64_t AlignDownOffset = alignDown(EltOffset, 4);
280 int64_t OffsetDiff = EltOffset - AlignDownOffset;
281 Align AdjustedAlign = commonAlignment(
282 KernArgBaseAlign, DoShiftOpt ? AlignDownOffset : EltOffset);
283
284 Value *ArgPtr;
285 Type *AdjustedArgTy;
286 if (DoShiftOpt) { // FIXME: Handle aggregate types
287 // Since we don't have sub-dword scalar loads, avoid doing an extload by
288 // loading earlier than the argument address, and extracting the relevant
289 // bits.
290 // TODO: Update this for GFX12 which does have scalar sub-dword loads.
291 //
292 // Additionally widen any sub-dword load to i32 even if suitably aligned,
293 // so that CSE between different argument loads works easily.
294 ArgPtr = Builder.CreateConstInBoundsGEP1_64(
295 Builder.getInt8Ty(), KernArgSegment, AlignDownOffset,
296 Arg.getName() + ".kernarg.offset.align.down");
297 AdjustedArgTy = Builder.getInt32Ty();
298 } else {
299 ArgPtr = Builder.CreateConstInBoundsGEP1_64(
300 Builder.getInt8Ty(), KernArgSegment, EltOffset,
301 Arg.getName() + ".kernarg.offset");
302 AdjustedArgTy = ArgTy;
303 }
304
305 if (IsV3 && Size >= 32) {
306 V4Ty = FixedVectorType::get(VT->getElementType(), 4);
307 // Use the hack that clang uses to avoid SelectionDAG ruining v3 loads
308 AdjustedArgTy = V4Ty;
309 }
310
311 LoadInst *Load =
312 Builder.CreateAlignedLoad(AdjustedArgTy, ArgPtr, AdjustedAlign);
313 Load->setMetadata(LLVMContext::MD_invariant_load, MDNode::get(Ctx, {}));
314
315 MDBuilder MDB(Ctx);
316
317 if (Arg.hasAttribute(Attribute::NoUndef) && AdjustedArgTy == ArgTy)
318 Load->setMetadata(LLVMContext::MD_noundef, MDNode::get(Ctx, {}));
319
320 if (Arg.hasAttribute(Attribute::Range) && AdjustedArgTy == ArgTy) {
321 const ConstantRange &Range =
322 Arg.getAttribute(Attribute::Range).getValueAsConstantRange();
323 Load->setMetadata(LLVMContext::MD_range,
324 MDB.createRange(Range.getLower(), Range.getUpper()));
325 }
326
327 if (Arg.hasAttribute(Attribute::NoFPClass) && AdjustedArgTy == ArgTy) {
328 FPClassTest Mask = Arg.getNoFPClass();
329 Load->setMetadata(
330 LLVMContext::MD_nofpclass,
332 ConstantInt::get(Type::getInt32Ty(Ctx), Mask))));
333 }
334
335 if (isa<PointerType>(ArgTy)) {
336 if (Arg.hasNonNullAttr())
337 Load->setMetadata(LLVMContext::MD_nonnull, MDNode::get(Ctx, {}));
338
339 uint64_t DerefBytes = Arg.getDereferenceableBytes();
340 if (DerefBytes != 0) {
341 Load->setMetadata(
342 LLVMContext::MD_dereferenceable,
343 MDNode::get(Ctx,
344 MDB.createConstant(
345 ConstantInt::get(Builder.getInt64Ty(), DerefBytes))));
346 }
347
348 uint64_t DerefOrNullBytes = Arg.getDereferenceableOrNullBytes();
349 if (DerefOrNullBytes != 0) {
350 Load->setMetadata(
351 LLVMContext::MD_dereferenceable_or_null,
352 MDNode::get(Ctx,
353 MDB.createConstant(ConstantInt::get(Builder.getInt64Ty(),
354 DerefOrNullBytes))));
355 }
356
357 if (MaybeAlign ParamAlign = Arg.getParamAlign()) {
358 Load->setMetadata(
359 LLVMContext::MD_align,
360 MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
361 Builder.getInt64Ty(), ParamAlign->value()))));
362 }
363 }
364
365 if (DoShiftOpt) {
366 Value *ExtractBits = OffsetDiff == 0 ?
367 Load : Builder.CreateLShr(Load, OffsetDiff * 8);
368
369 IntegerType *ArgIntTy = Builder.getIntNTy(Size);
370 Value *Trunc = Builder.CreateTrunc(ExtractBits, ArgIntTy);
371 Value *NewVal = Builder.CreateBitCast(Trunc, ArgTy,
372 Arg.getName() + ".load");
373 Arg.replaceAllUsesWith(NewVal);
374 } else if (IsV3) {
375 Value *Shuf = Builder.CreateShuffleVector(Load, ArrayRef<int>{0, 1, 2},
376 Arg.getName() + ".load");
377 Arg.replaceAllUsesWith(Shuf);
378 } else {
379 Load->setName(Arg.getName() + ".load");
380 Arg.replaceAllUsesWith(Load);
381 }
382 }
383
384 KernArgSegment->addRetAttr(
385 Attribute::getWithAlignment(Ctx, std::max(KernArgBaseAlign, MaxAlign)));
386
387 return true;
388}
389
390bool AMDGPULowerKernelArguments::runOnFunction(Function &F) {
391 auto &TPC = getAnalysis<TargetPassConfig>();
392 const TargetMachine &TM = TPC.getTM<TargetMachine>();
393 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
394 return lowerKernelArguments(F, TM, DT);
395}
396
397INITIALIZE_PASS_BEGIN(AMDGPULowerKernelArguments, DEBUG_TYPE,
398 "AMDGPU Lower Kernel Arguments", false, false)
399INITIALIZE_PASS_END(AMDGPULowerKernelArguments, DEBUG_TYPE, "AMDGPU Lower Kernel Arguments",
401
402char AMDGPULowerKernelArguments::ID = 0;
403
405 return new AMDGPULowerKernelArguments();
406}
407
411 bool Changed = lowerKernelArguments(F, TM, DT);
412 if (Changed) {
413 // TODO: Preserves a lot more.
416 return PA;
417 }
418
419 return PreservedAnalyses::all();
420}
unsigned uint64_t
static void addAliasScopeMetadata(Function &F, const DataLayout &DL, DominatorTree &DT)
static BasicBlock::iterator getInsertPt(BasicBlock &BB)
static bool lowerKernelArguments(Function &F, const TargetMachine &TM, DominatorTree &DT)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< bool > NoAliases("csky-no-aliases", cl::desc("Disable the emission of assembler pseudo instructions"), cl::init(false), cl::Hidden)
static bool runOnFunction(Function &F, bool PostInlining)
AMD GCN specific subclass of TargetSubtarget.
#define DEBUG_TYPE
#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
This is the interface for a metadata-based scoped no-alias analysis.
Target-Independent Code Generator Pass Configuration Options pass.
PreservedAnalyses run(Function &, FunctionAnalysisManager &)
an instruction to allocate memory on the stack
LLVM_ABI bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
static LLVM_ABI Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:459
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void addRetAttr(Attribute::AttrKind Kind)
Adds the attribute to the return value.
This class represents a function call, abstracting a target machine's calling convention.
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:537
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
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:284
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
Legacy analysis pass which computes a DominatorTree.
Definition Dominators.h:277
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:867
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2903
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
An instruction for reading from memory.
MDNode * createAnonymousAliasScope(MDNode *Domain, StringRef Name=StringRef())
Return metadata appropriate for an alias scope root node.
Definition MDBuilder.h:195
LLVM_ABI ConstantAsMetadata * createConstant(Constant *C)
Return the given constant as metadata.
Definition MDBuilder.cpp:25
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
Definition MDBuilder.cpp:96
MDNode * createAnonymousAliasScopeDomain(StringRef Name=StringRef())
Return metadata appropriate for an alias scope domain node.
Definition MDBuilder.h:188
Metadata node.
Definition Metadata.h:1069
static LLVM_ABI MDNode * concatenate(MDNode *A, MDNode *B)
Methods for metadata merging.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1567
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
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
void insert_range(Range &&R)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Primary interface to the complete machine description for the target machine.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
Target-Independent Code Generator Pass Configuration Options.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:319
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:313
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
CallInst * Call
Changed
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
This is an optimization pass for GlobalISel generic memory operations.
InstIterator< SymbolTableList< BasicBlock >, Function::iterator, BasicBlock::iterator, Instruction > inst_iterator
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).
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:541
inst_iterator inst_begin(Function *F)
LLVM_ABI bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, const Instruction *I, const DominatorTree *DT, bool IncludeI=false, unsigned MaxUsesToExplore=0, const LoopInfo *LI=nullptr)
PointerMayBeCapturedBefore - Return true if this pointer value may be captured by the enclosing funct...
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
FunctionPass * createAMDGPULowerKernelArgumentsPass()
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
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
inst_iterator inst_end(Function *F)
LLVM_ABI bool isEscapeSource(const Value *V)
Returns true if the pointer is one which would have been considered an escape by isNotCapturedBefore.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
bool capturesAnything(CaptureComponents CC)
Definition ModRef.h:379
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106