LLVM 24.0.0git
SCCP.cpp
Go to the documentation of this file.
1//===-- SCCP.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// This file implements Interprocedural Sparse Conditional Constant Propagation.
10//
11//===----------------------------------------------------------------------===//
12
14#include "llvm/ADT/SetVector.h"
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/DIBuilder.h"
28#include "llvm/Support/ModRef.h"
29#include "llvm/Transforms/IPO.h"
34
35using namespace llvm;
36
37#define DEBUG_TYPE "sccp"
38
39STATISTIC(NumInstRemoved, "Number of instructions removed");
40STATISTIC(NumArgsElimed ,"Number of arguments constant propagated");
41STATISTIC(NumGlobalConst, "Number of globals found to be constant");
42STATISTIC(NumDeadBlocks , "Number of basic blocks unreachable");
43STATISTIC(NumInstReplaced,
44 "Number of instructions replaced with (simpler) instruction");
45
47 "funcspec-max-iters", cl::init(10), cl::Hidden, cl::desc(
48 "The maximum number of iterations function specialization is run"));
49
51 SmallVector<ReturnInst *, 8> &ReturnsToZap,
52 SCCPSolver &Solver) {
53 // We can only do this if we know that nothing else can call the function.
54 if (!Solver.isArgumentTrackedFunction(&F))
55 return;
56
57 if (Solver.mustPreserveReturn(&F)) {
59 dbgs()
60 << "Can't zap returns of the function : " << F.getName()
61 << " due to present musttail or \"clang.arc.attachedcall\" call of "
62 "it\n");
63 return;
64 }
65
66 assert(
67 all_of(F.users(),
68 [&Solver](User *U) {
69 if (isa<Instruction>(U) &&
70 !Solver.isBlockExecutable(cast<Instruction>(U)->getParent()))
71 return true;
72 // Non-callsite uses are not impacted by zapping. Also, constant
73 // uses (like blockaddresses) could stuck around, without being
74 // used in the underlying IR, meaning we do not have lattice
75 // values for them.
76 if (!isa<CallBase>(U))
77 return true;
78 if (U->getType()->isStructTy()) {
79 return none_of(Solver.getStructLatticeValueFor(U),
80 SCCPSolver::isOverdefined);
81 }
82
83 // We don't consider assume-like intrinsics to be actual address
84 // captures.
85 if (auto *II = dyn_cast<IntrinsicInst>(U)) {
86 if (II->isAssumeLikeIntrinsic())
87 return true;
88 }
89
91 }) &&
92 "We can only zap functions where all live users have a concrete value");
93
94 for (BasicBlock &BB : F) {
95 if (CallInst *CI = BB.getTerminatingMustTailCall()) {
96 LLVM_DEBUG(dbgs() << "Can't zap return of the block due to present "
97 << "musttail call : " << *CI << "\n");
98 (void)CI;
99 return;
100 }
101
102 if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
103 if (!isa<UndefValue>(RI->getOperand(0)))
104 ReturnsToZap.push_back(RI);
105 }
106}
107
108static bool runIPSCCP(
110 std::function<const TargetLibraryInfo &(Function &)> GetTLI,
111 std::function<TargetTransformInfo &(Function &)> GetTTI,
112 std::function<AssumptionCache &(Function &)> GetAC,
113 std::function<DominatorTree &(Function &)> GetDT,
114 std::function<BlockFrequencyInfo &(Function &)> GetBFI,
115 bool IsFuncSpecEnabled) {
116 SCCPSolver Solver(DL, GetTLI, M.getContext());
117 FunctionSpecializer Specializer(Solver, M, FAM, GetBFI, GetTLI, GetTTI,
118 GetAC);
119
120 // Loop over all functions, marking arguments to those with their addresses
121 // taken or that are external as overdefined.
122 for (Function &F : M) {
123 if (F.isDeclaration())
124 continue;
125
126 DominatorTree &DT = GetDT(F);
127 AssumptionCache &AC = GetAC(F);
128 Solver.addPredicateInfo(F, DT, AC);
129
130 // Determine if we can track the function's return values. If so, add the
131 // function to the solver's set of return-tracked functions.
133 Solver.addTrackedFunction(&F);
134
135 // Determine if we can track the function's arguments. If so, add the
136 // function to the solver's set of argument-tracked functions.
139 continue;
140 }
141
142 // Assume the function is called.
143 Solver.markBlockExecutable(&F.front());
144
145 for (Argument &AI : F.args())
146 Solver.trackValueOfArgument(&AI);
147 }
148
149 // Determine if we can track any of the module's global variables. If so, add
150 // the global variables we can track to the solver's set of tracked global
151 // variables.
152 for (GlobalVariable &G : M.globals()) {
153 G.removeDeadConstantUsers();
156 }
157
158 // Solve for constants.
160
161 if (IsFuncSpecEnabled) {
162 unsigned Iters = 0;
163 while (Iters++ < FuncSpecMaxIters && Specializer.run());
164 }
165
166 // Iterate over all of the instructions in the module, replacing them with
167 // constants if we have found them to be of constant values.
168 bool MadeChanges = false;
169 for (Function &F : M) {
170 if (F.isDeclaration())
171 continue;
172 // Skip the dead functions marked by FunctionSpecializer, avoiding removing
173 // blocks in dead functions. Set MadeChanges if there is any dead function
174 // that will be removed later.
175 if (IsFuncSpecEnabled && Specializer.isDeadFunction(&F)) {
176 MadeChanges = true;
177 continue;
178 }
179
180 SmallVector<BasicBlock *, 512> BlocksToErase;
181
182 if (Solver.isBlockExecutable(&F.front())) {
183 bool ReplacedPointerArg = false;
184 for (Argument &Arg : F.args()) {
185 if (!Arg.use_empty() && Solver.tryToReplaceWithConstant(&Arg)) {
186 ReplacedPointerArg |= Arg.getType()->isPointerTy();
187 ++NumArgsElimed;
188 }
189 }
190
191 // If we replaced an argument, we may now also access a global (currently
192 // classified as "other" memory). Update memory attribute to reflect this.
193 if (ReplacedPointerArg) {
194 auto UpdateAttrs = [&](AttributeList AL) {
195 MemoryEffects ME = AL.getMemoryEffects();
196 if (ME == MemoryEffects::unknown())
197 return AL;
198
200 ME |= MemoryEffects(IRMemLocation::ErrnoMem, ArgMemMR);
201 ME |= MemoryEffects(IRMemLocation::Other, ArgMemMR);
202
203 return AL.addFnAttribute(
204 F.getContext(),
205 Attribute::getWithMemoryEffects(F.getContext(), ME));
206 };
207
208 F.setAttributes(UpdateAttrs(F.getAttributes()));
209 for (User *U : F.users()) {
210 auto *CB = dyn_cast<CallBase>(U);
211 if (!CB || CB->getCalledFunction() != &F)
212 continue;
213
214 CB->setAttributes(UpdateAttrs(CB->getAttributes()));
215 }
216 }
217 MadeChanges |= ReplacedPointerArg;
218 }
219
220 SmallPtrSet<Value *, 32> InsertedValues;
221 for (BasicBlock &BB : F) {
222 if (!Solver.isBlockExecutable(&BB)) {
223 LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
224 ++NumDeadBlocks;
225
226 MadeChanges = true;
227
228 if (&BB != &F.front())
229 BlocksToErase.push_back(&BB);
230 continue;
231 }
232
233 MadeChanges |= Solver.simplifyInstsInBlock(
234 BB, InsertedValues, NumInstRemoved, NumInstReplaced);
235 }
236
237 DominatorTree *DT = FAM->getCachedResult<DominatorTreeAnalysis>(F);
238 PostDominatorTree *PDT = FAM->getCachedResult<PostDominatorTreeAnalysis>(F);
239 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
240 // Change dead blocks to unreachable. We do it after replacing constants
241 // in all executable blocks, because changeToUnreachable may remove PHI
242 // nodes in executable blocks we found values for. The function's entry
243 // block is not part of BlocksToErase, so we have to handle it separately.
244 for (BasicBlock *BB : BlocksToErase) {
245 NumInstRemoved += changeToUnreachable(&*BB->getFirstNonPHIOrDbg(),
246 /*PreserveLCSSA=*/false, &DTU);
247 }
248 if (!Solver.isBlockExecutable(&F.front()))
249 NumInstRemoved += changeToUnreachable(&*F.front().getFirstNonPHIOrDbg(),
250 /*PreserveLCSSA=*/false, &DTU);
251
252 BasicBlock *NewUnreachableBB = nullptr;
253 for (BasicBlock &BB : F)
254 MadeChanges |= Solver.removeNonFeasibleEdges(&BB, DTU, NewUnreachableBB);
255
256 for (BasicBlock *DeadBB : BlocksToErase)
257 if (!DeadBB->hasAddressTaken())
258 DTU.deleteBB(DeadBB);
259
260 Solver.removeSSACopies(F);
261 }
262
263 // If we inferred constant or undef return values for a function, we replaced
264 // all call uses with the inferred value. This means we don't need to bother
265 // actually returning anything from the function. Replace all return
266 // instructions with return undef.
267 //
268 // Do this in two stages: first identify the functions we should process, then
269 // actually zap their returns. This is important because we can only do this
270 // if the address of the function isn't taken. In cases where a return is the
271 // last use of a function, the order of processing functions would affect
272 // whether other functions are optimizable.
273 SmallVector<ReturnInst*, 8> ReturnsToZap;
274
275 Solver.inferReturnAttributes();
276 Solver.inferArgAttributes();
277 for (const auto &[F, ReturnValue] : Solver.getTrackedRetVals()) {
278 assert(!F->getReturnType()->isVoidTy() &&
279 "should not track void functions");
280 if (SCCPSolver::isReplaceableConstant(ReturnValue) ||
281 ReturnValue.isUnknownOrUndef())
282 findReturnsToZap(*F, ReturnsToZap, Solver);
283 }
284
285 for (auto *F : Solver.getMRVFunctionsTracked()) {
286 assert(F->getReturnType()->isStructTy() &&
287 "The return type should be a struct");
288 StructType *STy = cast<StructType>(F->getReturnType());
289 if (Solver.isStructLatticeConstant(F, STy))
290 findReturnsToZap(*F, ReturnsToZap, Solver);
291 }
292
293 // Zap all returns which we've identified as zap to change.
294 SmallSetVector<Function *, 8> FuncZappedReturn;
295 for (ReturnInst *RI : ReturnsToZap) {
296 Function *F = RI->getParent()->getParent();
297 RI->setOperand(0, PoisonValue::get(F->getReturnType()));
298 // Record all functions that are zapped.
299 FuncZappedReturn.insert(F);
300 }
301
302 // Remove the returned attribute for zapped functions and the
303 // corresponding call sites.
304 // Also remove any attributes that convert an undef return value into
305 // immediate undefined behavior
306 AttributeMask UBImplyingAttributes =
307 AttributeFuncs::getUBImplyingAttributes();
308 for (Function *F : FuncZappedReturn) {
309 for (Argument &A : F->args())
310 F->removeParamAttr(A.getArgNo(), Attribute::Returned);
311 F->removeRetAttrs(UBImplyingAttributes);
312 for (Use &U : F->uses()) {
313 CallBase *CB = dyn_cast<CallBase>(U.getUser());
314 if (!CB) {
315 assert(isa<Constant>(U.getUser()) &&
316 all_of(U.getUser()->users(), [](const User *UserUser) {
317 return cast<IntrinsicInst>(UserUser)->isAssumeLikeIntrinsic();
318 }));
319 continue;
320 }
321
322 for (Use &Arg : CB->args())
323 CB->removeParamAttr(CB->getArgOperandNo(&Arg), Attribute::Returned);
324 CB->removeRetAttrs(UBImplyingAttributes);
325 }
326 }
327
328 // If we inferred constant or undef values for globals variables, we can
329 // delete the global and any stores that remain to it.
330 for (const auto &I : make_early_inc_range(Solver.getTrackedGlobals())) {
331 GlobalVariable *GV = I.first;
332 if (SCCPSolver::isOverdefined(I.second))
333 continue;
334 LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName()
335 << "' is constant!\n");
336 for (User *U : make_early_inc_range(GV->users())) {
337 // We can remove LoadInst here. The LoadInsts in dead functions marked by
338 // FuncSpec are not simplified to constants, thus poison them.
340 "Only Store|Load Instruction can be user of GlobalVariable at "
341 "reaching here.");
343 if (isa<LoadInst>(I))
344 I->replaceAllUsesWith(PoisonValue::get(I->getType()));
345 I->eraseFromParent();
346 }
347
348 // Try to create a debug constant expression for the global variable
349 // initializer value.
351 GV->getDebugInfo(GVEs);
352 if (GVEs.size() == 1) {
353 DIBuilder DIB(M);
355 DIB, *GV->getInitializer(), *GV->getValueType()))
356 GVEs[0]->replaceOperandWith(1, InitExpr);
357 }
358
359 MadeChanges = true;
360 M.eraseGlobalVariable(GV);
361 ++NumGlobalConst;
362 }
363
364 return MadeChanges;
365}
366
368 const DataLayout &DL = M.getDataLayout();
369 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
370 auto GetTLI = [&FAM](Function &F) -> const TargetLibraryInfo & {
371 return FAM.getResult<TargetLibraryAnalysis>(F);
372 };
373 auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
374 return FAM.getResult<TargetIRAnalysis>(F);
375 };
376 auto GetAC = [&FAM](Function &F) -> AssumptionCache & {
377 return FAM.getResult<AssumptionAnalysis>(F);
378 };
379 auto GetDT = [&FAM](Function &F) -> DominatorTree & {
380 return FAM.getResult<DominatorTreeAnalysis>(F);
381 };
382 auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
383 return FAM.getResult<BlockFrequencyAnalysis>(F);
384 };
385
386
387 if (!runIPSCCP(M, DL, &FAM, GetTLI, GetTTI, GetAC, GetDT, GetBFI,
389 return PreservedAnalyses::all();
390
395 return PA;
396}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void findReturnsToZap(Function &F, SmallVector< ReturnInst *, 8 > &ReturnsToZap, SCCPSolver &Solver)
Definition SCCP.cpp:50
static cl::opt< unsigned > FuncSpecMaxIters("funcspec-max-iters", cl::init(10), cl::Hidden, cl::desc("The maximum number of iterations function specialization is run"))
static bool runIPSCCP(Module &M, const DataLayout &DL, FunctionAnalysisManager *FAM, std::function< const TargetLibraryInfo &(Function &)> GetTLI, std::function< TargetTransformInfo &(Function &)> GetTTI, std::function< AssumptionCache &(Function &)> GetAC, std::function< DominatorTree &(Function &)> GetDT, std::function< BlockFrequencyInfo &(Function &)> GetBFI, bool IsFuncSpecEnabled)
Definition SCCP.cpp:108
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
if(PassOpts->AAPipeline)
This file implements a set that has insertion order iteration characteristics.
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
This pass exposes codegen information to IR-level passes.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
static LLVM_ABI Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
LLVM Basic Block Representation.
Definition BasicBlock.h:62
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Removes the attribute from the given argument.
void removeRetAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the return value.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
This class represents a function call, abstracting a target machine's calling convention.
DWARF expression.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
LLVM_ABI bool run()
Attempt to specialize functions in the module to enable constant propagation across function boundari...
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
LLVM_ABI void getDebugInfo(SmallVectorImpl< DIGlobalVariableExpression * > &GVs) const
Fill the vector with all debug info attachements.
bool isFuncSpecEnabled() const
Definition SCCP.h:58
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition SCCP.cpp:367
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition ModRef.h:219
static MemoryEffectsBase unknown()
Definition ModRef.h:123
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
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 & preserve()
Mark an analysis as preserved.
Definition Analysis.h:132
Return a value (possibly void), from a function.
SCCPSolver - This interface class is a general purpose solver for Sparse Conditional Constant Propaga...
Definition SCCPSolver.h:66
LLVM_ABI void trackValueOfGlobalVariable(GlobalVariable *GV)
trackValueOfGlobalVariable - Clients can use this method to inform the SCCPSolver that it should trac...
LLVM_ABI bool tryToReplaceWithConstant(Value *V)
LLVM_ABI void inferArgAttributes() const
LLVM_ABI bool isStructLatticeConstant(Function *F, StructType *STy)
LLVM_ABI void addPredicateInfo(Function &F, DominatorTree &DT, AssumptionCache &AC)
LLVM_ABI void trackValueOfArgument(Argument *V)
trackValueOfArgument - Mark the specified argument overdefined unless it have range attribute.
LLVM_ABI const DenseMap< GlobalVariable *, ValueLatticeElement > & getTrackedGlobals() const
getTrackedGlobals - Get and return the set of inferred initializers for global variables.
LLVM_ABI void addTrackedFunction(Function *F)
addTrackedFunction - If the SCCP solver is supposed to track calls into and out of the specified func...
LLVM_ABI void solveWhileResolvedUndefsIn(Module &M)
LLVM_ABI const SmallPtrSet< Function *, 16 > & getMRVFunctionsTracked() const
getMRVFunctionsTracked - Get the set of functions which return multiple values tracked by the pass.
LLVM_ABI void addArgumentTrackedFunction(Function *F)
static LLVM_ABI bool isReplaceableConstant(const ValueLatticeElement &LV)
LLVM_ABI bool simplifyInstsInBlock(BasicBlock &BB, SmallPtrSetImpl< Value * > &InsertedValues, Statistic &InstRemovedStat, Statistic &InstReplacedStat)
LLVM_ABI const ValueLatticeElement & getLatticeValueFor(Value *V) const
LLVM_ABI bool removeNonFeasibleEdges(BasicBlock *BB, DomTreeUpdater &DTU, BasicBlock *&NewUnreachableBB) const
LLVM_ABI bool isBlockExecutable(BasicBlock *BB) const
LLVM_ABI void inferReturnAttributes() const
LLVM_ABI bool markBlockExecutable(BasicBlock *BB)
markBlockExecutable - This method can be used by clients to mark all of the blocks that are known to ...
LLVM_ABI const MapVector< Function *, ValueLatticeElement > & getTrackedRetVals() const
getTrackedRetVals - Get the inferred return value map.
LLVM_ABI bool mustPreserveReturn(Function *F)
Returns true if the return of the given function cannot be modified.
static LLVM_ABI bool isOverdefined(const ValueLatticeElement &LV)
LLVM_ABI bool isArgumentTrackedFunction(Function *F)
Returns true if the given function is in the solver's set of argument-tracked functions.
LLVM_ABI void removeSSACopies(Function &F)
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:345
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Class to represent struct types.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
iterator_range< user_iterator > users()
Definition Value.h:426
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition ModRef.h:356
LLVM_ABI bool canTrackGlobalVariableInterprocedurally(GlobalVariable *GV)
Determine if the value maintained in the given global variable can be tracked interprocedurally.
LLVM_ABI DIExpression * getExpressionForConstant(DIBuilder &DIB, const Constant &C, Type &Ty)
Given a constant, create a debug information expression.
Definition Local.cpp:3456
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
Definition Local.cpp:2552
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
Definition ModRef.h:28
@ ErrnoMem
Errno memory.
Definition ModRef.h:66
@ ArgMem
Access to memory via argument pointers.
Definition ModRef.h:62
@ Other
Any other memory.
Definition ModRef.h:68
LLVM_ABI bool canTrackReturnsInterprocedurally(Function *F)
Determine if the values of the given function's returns can be tracked interprocedurally.
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 bool canTrackArgumentsInterprocedurally(Function *F)
Determine if the values of the given function's arguments can be tracked interprocedurally.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39