LLVM 23.0.0git
MemoryTaggingSupport.cpp
Go to the documentation of this file.
1//== MemoryTaggingSupport.cpp - helpers for memory tagging implementations ===//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7//
8// This file declares common infrastructure for HWAddressSanitizer and
9// Aarch64StackTagging.
10//
11//===----------------------------------------------------------------------===//
12
14
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/Analysis/CFG.h"
21#include "llvm/IR/BasicBlock.h"
22#include "llvm/IR/IRBuilder.h"
26
27namespace llvm {
28namespace memtag {
29namespace {
30bool maybeReachableFromEachOther(const SmallVectorImpl<IntrinsicInst *> &Insts,
31 const DominatorTree *DT, const LoopInfo *LI,
32 size_t MaxLifetimes) {
33 // If we have too many lifetime ends, give up, as the algorithm below is N^2.
34 if (Insts.size() > MaxLifetimes)
35 return true;
36 for (size_t I = 0; I < Insts.size(); ++I) {
37 for (size_t J = 0; J < Insts.size(); ++J) {
38 if (I == J)
39 continue;
40 if (isPotentiallyReachable(Insts[I], Insts[J], nullptr, DT, LI))
41 return true;
42 }
43 }
44 return false;
45}
46} // namespace
47
49 const LoopInfo &LI, const AllocaInfo &AInfo,
51 llvm::function_ref<void(Instruction *)> Callback) {
52 if (AInfo.LifetimeEnd.size() == 1 && AInfo.LifetimeStart.size() == 1 &&
53 PDT.dominates(AInfo.LifetimeEnd[0], AInfo.LifetimeStart[0])) {
54 Callback(AInfo.LifetimeEnd[0]);
55 return true;
56 }
59 for (const auto &[BB, ID] : AInfo.LastBBLifetime) {
60 if (ID == Intrinsic::lifetime_end)
61 EndBlocks.insert(BB);
62 else
63 StartBlocks.push_back(BB);
64 }
65 bool UncoveredRets = false;
66
67 if (!StartBlocks.empty()) {
68 for (auto *RI : RetVec) {
69 auto WL = StartBlocks;
70 // If the block with the return is an EndBlock (i.e. a block where the
71 // last relevant lifetime intrinsic is an end), we don't have to run a
72 // complicated algorithm to know that the RetInst is never reachable
73 // without going through an end.
74 if (!EndBlocks.contains(RI->getParent()) &&
75 isPotentiallyReachableFromMany(WL, RI->getParent(), &EndBlocks, &DT,
76 &LI)) {
77 Callback(RI);
78 UncoveredRets = true;
79 }
80 }
81 }
82 for_each(AInfo.LifetimeEnd, Callback);
83 // We may have inserted untag outside of the lifetime interval.
84 // Signal the caller to remove the lifetime end call for this alloca.
85 return !UncoveredRets;
86}
87
89 const SmallVectorImpl<IntrinsicInst *> &LifetimeEnd,
90 const DominatorTree *DT, const LoopInfo *LI,
91 size_t MaxLifetimes) {
92 // An alloca that has exactly one start and end in every possible execution.
93 // If it has multiple ends, they have to be unreachable from each other, so
94 // at most one of them is actually used for each execution of the function.
95 return LifetimeStart.size() > 0 &&
96 (LifetimeEnd.size() == 1 ||
97 (LifetimeEnd.size() > 0 &&
98 !maybeReachableFromEachOther(LifetimeEnd, DT, LI, MaxLifetimes)));
99}
100
102 if (isa<ReturnInst>(Inst)) {
103 if (CallInst *CI = Inst.getParent()->getTerminatingMustTailCall())
104 return CI;
105 return &Inst;
106 }
108 return &Inst;
109 }
110 return nullptr;
111}
112
114 Instruction &Inst) {
115 // Visit non-intrinsic debug-info records attached to Inst.
117 auto AddIfInteresting = [&](Value *V) {
118 if (auto *AI = dyn_cast_or_null<AllocaInst>(V)) {
119 if (getAllocaInterestingness(*AI) !=
121 return;
122 AllocaInfo &AInfo = Info.AllocasToInstrument[AI];
123 auto &DVRVec = AInfo.DbgVariableRecords;
124 if (DVRVec.empty() || DVRVec.back() != &DVR)
125 DVRVec.push_back(&DVR);
126 }
127 };
128
129 for_each(DVR.location_ops(), AddIfInteresting);
130 if (DVR.isDbgAssign())
131 AddIfInteresting(DVR.getAddress());
132 }
133
134 if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
135 if (CI->canReturnTwice()) {
136 Info.CallsReturnTwice = true;
137 }
138 }
139 if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
140 switch (getAllocaInterestingness(*AI)) {
142 Info.AllocasToInstrument[AI].AI = AI;
143 ORE.emit([&]() {
144 return OptimizationRemarkMissed(DebugType, "safeAlloca", &Inst);
145 });
146 break;
148 ORE.emit(
149 [&]() { return OptimizationRemark(DebugType, "safeAlloca", &Inst); });
150 break;
152 break;
153 }
154 return;
155 }
156 if (auto *II = dyn_cast<LifetimeIntrinsic>(&Inst)) {
157 AllocaInst *AI = dyn_cast<AllocaInst>(II->getArgOperand(0));
158 if (!AI ||
160 return;
161 if (II->getIntrinsicID() == Intrinsic::lifetime_start)
162 Info.AllocasToInstrument[AI].LifetimeStart.push_back(II);
163 else
164 Info.AllocasToInstrument[AI].LifetimeEnd.push_back(II);
165 Info.AllocasToInstrument[AI].LastBBLifetime[II->getParent()] =
166 II->getIntrinsicID();
167 return;
168 }
169
171 if (ExitUntag)
172 Info.RetVec.push_back(ExitUntag);
173}
174
177 std::optional<TypeSize> Size = AI.getAllocationSize(AI.getDataLayout());
178 if (Size &&
179 // FIXME: support vscale.
180 !Size->isScalable() &&
181 // FIXME: instrument dynamic allocas, too
182 AI.isStaticAlloca() &&
183 // alloca() may be called with 0 size, ignore it.
184 !Size->isZero() &&
185 // We are only interested in allocas not promotable to registers.
186 // Promotable allocas are common under -O0.
187 !isAllocaPromotable(&AI) &&
188 // inalloca allocas are not treated as static, and we don't want
189 // dynamic alloca instrumentation for them as well.
190 !AI.isUsedWithInAlloca() &&
191 // swifterror allocas are register promoted by ISel
192 !AI.isSwiftError()) {
193 if (!(SSI && SSI->isSafe(AI))) {
195 }
196 // safe allocas are not interesting
198 }
200}
201
203 auto DL = AI.getDataLayout();
204 return *AI.getAllocationSize(DL);
205}
206
208 const Align NewAlignment = std::max(Info.AI->getAlign(), Alignment);
209 Info.AI->setAlignment(NewAlignment);
210 auto &Ctx = Info.AI->getFunction()->getContext();
211
213 uint64_t AlignedSize = alignTo(Size, Alignment);
214 if (Size == AlignedSize)
215 return;
216
217 // Add padding to the alloca.
218 Type *AllocatedType =
219 Info.AI->isArrayAllocation()
221 Info.AI->getAllocatedType(),
222 cast<ConstantInt>(Info.AI->getArraySize())->getZExtValue())
223 : Info.AI->getAllocatedType();
224 Type *PaddingType = ArrayType::get(Type::getInt8Ty(Ctx), AlignedSize - Size);
225 Type *TypeWithPadding = StructType::get(AllocatedType, PaddingType);
226 auto *NewAI = new AllocaInst(TypeWithPadding, Info.AI->getAddressSpace(),
227 nullptr, "", Info.AI->getIterator());
228 NewAI->takeName(Info.AI);
229 NewAI->setAlignment(Info.AI->getAlign());
230 NewAI->setUsedWithInAlloca(Info.AI->isUsedWithInAlloca());
231 NewAI->setSwiftError(Info.AI->isSwiftError());
232 NewAI->copyMetadata(*Info.AI);
233
234 Info.AI->replaceAllUsesWith(NewAI);
235 Info.AI->eraseFromParent();
236 Info.AI = NewAI;
237}
238
240 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
241 MDNode *MD =
242 MDNode::get(M->getContext(), {MDString::get(M->getContext(), Name)});
243 Value *Args[] = {MetadataAsValue::get(M->getContext(), MD)};
244 return IRB.CreateIntrinsic(Intrinsic::read_register,
245 IRB.getIntPtrTy(M->getDataLayout()), Args);
246}
247
248Value *getPC(const Triple &TargetTriple, IRBuilder<> &IRB) {
249 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
250 if (TargetTriple.getArch() == Triple::aarch64)
251 return memtag::readRegister(IRB, "pc");
252 return IRB.CreatePtrToInt(IRB.GetInsertBlock()->getParent(),
253 IRB.getIntPtrTy(M->getDataLayout()));
254}
255
258 Module *M = F->getParent();
259 return IRB.CreatePtrToInt(
260 IRB.CreateIntrinsic(Intrinsic::frameaddress,
261 IRB.getPtrTy(M->getDataLayout().getAllocaAddrSpace()),
262 {Constant::getNullValue(IRB.getInt32Ty())}),
263 IRB.getIntPtrTy(M->getDataLayout()));
264}
265
267 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
268 // FIXME: This should use the thread_pointer intrinsic. However, the
269 // intrinsic is not currently implemented on Darwin correctly. The
270 // TPIDRRO_EL0 register became part of the ABI to access TSD on recent
271 // versions of OS and so it is safe to use here
272 // Darwin provides a fixed slot for sanitizers at offset 231.
273 MDNode *MD = MDNode::get(M->getContext(),
274 {MDString::get(M->getContext(), "TPIDRRO_EL0")});
275 Value *Args[] = {MetadataAsValue::get(M->getContext(), MD)};
276 return IRB.CreateConstGEP1_32(
277 IRB.getInt8Ty(),
278 IRB.CreateIntToPtr(
279 IRB.CreateIntrinsic(Intrinsic::read_register,
280 {IRB.getIntPtrTy(M->getDataLayout())}, Args),
281 IRB.getPtrTy()),
282 8 * Slot);
283}
284
286 Module *M = IRB.GetInsertBlock()->getParent()->getParent();
287 // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER
288 // in Bionic's libc/private/bionic_tls.h.
289 Function *ThreadPointerFunc = Intrinsic::getOrInsertDeclaration(
290 M, Intrinsic::thread_pointer,
291 IRB.getPtrTy(M->getDataLayout().getDefaultGlobalsAddressSpace()));
292 return IRB.CreateConstGEP1_32(IRB.getInt8Ty(),
293 IRB.CreateCall(ThreadPointerFunc), 8 * Slot);
294}
295
297 return DVR->isDbgAssign() ? DVR : nullptr;
298}
299
300void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag) {
301 auto AnnotateDbgRecord = [&](DbgVariableRecord *DPtr) {
302 // Prepend "tag_offset, N" to the dwarf expression.
303 // Tag offset logically applies to the alloca pointer, and it makes sense
304 // to put it at the beginning of the expression.
306 for (size_t LocNo = 0; LocNo < DPtr->getNumVariableLocationOps(); ++LocNo)
307 if (DPtr->getVariableLocationOp(LocNo) == Info.AI)
308 DPtr->setExpression(
309 DIExpression::appendOpsToArg(DPtr->getExpression(), NewOps, LocNo));
310 if (auto *DAI = DynCastToDbgAssign(DPtr)) {
311 if (DAI->getAddress() == Info.AI)
312 DAI->setAddressExpression(
313 DIExpression::prependOpcodes(DAI->getAddressExpression(), NewOps));
314 }
315 };
316
317 llvm::for_each(Info.DbgVariableRecords, AnnotateDbgRecord);
318}
319
321 unsigned int Inc, bool IsMemtagDarwin) {
322 // Update the ring buffer. Top byte of ThreadLong defines the size of the
323 // buffer in pages, it must be a power of two, and the start of the buffer
324 // must be aligned by twice that much. Therefore wrap around of the ring
325 // buffer is simply Addr &= ~((ThreadLong >> 56) << 12).
326 // The use of AShr instead of LShr is due to
327 // https://bugs.llvm.org/show_bug.cgi?id=39030
328 // Runtime library makes sure not to use the highest bit.
329 //
330 // Mechanical proof of this address calculation can be found at:
331 // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/prove_hwasanwrap.smt2
332 //
333 // Example of the wrap case for N = 1
334 // Pointer: 0x01AAAAAAAAAAAFF8
335 // +
336 // 0x0000000000000008
337 // =
338 // 0x01AAAAAAAAAAB000
339 // &
340 // WrapMask: 0xFFFFFFFFFFFFF000
341 // =
342 // 0x01AAAAAAAAAAA000
343 //
344 // Then the WrapMask will be a no-op until the next wrap case.
345 //
346 // Darwin relies on bit 60-62 to store the size of the buffer in pages. This
347 // limits N to [0,2] while the rest of the proof remains unchanged. Bits
348 // 56-59 are avoided in order to prevent MTE Canonical Tag Faults while
349 // accessing the ring buffer. Bit 63 is avoided to prevent unintentional
350 // signed extension by AShr.
351 assert((4096 % Inc) == 0);
352 Value *WrapMask = IRB.CreateXor(
353 IRB.CreateShl(IRB.CreateAShr(ThreadLong, IsMemtagDarwin ? 60 : 56), 12,
354 "", true, true),
355 ConstantInt::get(ThreadLong->getType(), (uint64_t)-1));
356 return IRB.CreateAnd(
357 IRB.CreateAdd(ThreadLong, ConstantInt::get(ThreadLong->getType(), Inc)),
358 WrapMask);
359}
360
361} // namespace memtag
362} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains constants used for implementing Dwarf debug support.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
This file contains some templates that are useful if you are working with the STL at all.
an instruction to allocate memory on the stack
bool isSwiftError() const
Return true if this alloca is used as a swifterror argument to a call.
LLVM_ABI bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
bool isUsedWithInAlloca() const
Return true if this alloca is used as an inalloca argument to a call.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
static LLVM_ABI DIExpression * prependOpcodes(const DIExpression *Expr, SmallVectorImpl< uint64_t > &Ops, bool StackValue=false, bool EntryValue=false)
Prepend DIExpr with the given opcodes and optionally turn it into a stack value.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:164
Module * getParent()
Get the module that this global value is contained inside of...
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Definition IRBuilder.h:1958
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2172
IntegerType * getIntPtrTy(const DataLayout &DL, unsigned AddrSpace=0)
Fetch the type of an integer with size at least as big as that of a pointer in the given address spac...
Definition IRBuilder.h:611
BasicBlock * GetInsertBlock() const
Definition IRBuilder.h:201
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1496
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1555
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1407
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2167
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2481
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Definition IRBuilder.h:605
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1536
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1603
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Definition IRBuilder.h:552
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2776
iterator_range< simple_ilist< DbgRecord >::iterator > getDbgRecordRange() const
Return a range over the DbgRecords attached to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Metadata node.
Definition Metadata.h:1080
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1572
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:110
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for missed-optimization remarks.
Diagnostic information for applied optimization remarks.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
LLVM_ABI bool dominates(const Instruction *I1, const Instruction *I2) const
Return true if I1 dominates I2.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:413
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition Triple.h:418
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:294
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
void visit(OptimizationRemarkEmitter &ORE, Instruction &Inst)
AllocaInterestingness getAllocaInterestingness(const AllocaInst &AI)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
@ DW_OP_LLVM_tag_offset
Only used in LLVM metadata.
Definition Dwarf.h:146
Value * getFP(IRBuilder<> &IRB)
bool isStandardLifetime(const SmallVectorImpl< IntrinsicInst * > &LifetimeStart, const SmallVectorImpl< IntrinsicInst * > &LifetimeEnd, const DominatorTree *DT, const LoopInfo *LI, size_t MaxLifetimes)
uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
Value * getDarwinSlotPtr(IRBuilder<> &IRB, int Slot)
Value * getAndroidSlotPtr(IRBuilder<> &IRB, int Slot)
static DbgVariableRecord * DynCastToDbgAssign(DbgVariableRecord *DVR)
Value * readRegister(IRBuilder<> &IRB, StringRef Name)
void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)
Instruction * getUntagLocationIfFunctionExit(Instruction &Inst)
void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)
Value * incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, unsigned int Inc, bool IsMemtagDarwin=false)
bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const AllocaInfo &AInfo, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1730
LLVM_ABI bool isPotentiallyReachableFromMany(SmallVectorImpl< BasicBlock * > &Worklist, const BasicBlock *StopBB, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether there is at least one path from a block in 'Worklist' to 'StopBB' without passing t...
Definition CFG.cpp:240
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
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
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
Definition CFG.cpp:282
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
SmallVector< DbgVariableRecord *, 2 > DbgVariableRecords
SmallVector< IntrinsicInst *, 2 > LifetimeEnd
SmallVector< IntrinsicInst *, 2 > LifetimeStart
MapVector< BasicBlock *, Intrinsic::ID > LastBBLifetime