LLVM 22.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::isConstant(ReturnValue) || ReturnValue.isUnknownOrUndef())
281 findReturnsToZap(*F, ReturnsToZap, Solver);
282 }
283
284 for (auto *F : Solver.getMRVFunctionsTracked()) {
285 assert(F->getReturnType()->isStructTy() &&
286 "The return type should be a struct");
287 StructType *STy = cast<StructType>(F->getReturnType());
288 if (Solver.isStructLatticeConstant(F, STy))
289 findReturnsToZap(*F, ReturnsToZap, Solver);
290 }
291
292 // Zap all returns which we've identified as zap to change.
293 SmallSetVector<Function *, 8> FuncZappedReturn;
294 for (ReturnInst *RI : ReturnsToZap) {
295 Function *F = RI->getParent()->getParent();
296 RI->setOperand(0, PoisonValue::get(F->getReturnType()));
297 // Record all functions that are zapped.
298 FuncZappedReturn.insert(F);
299 }
300
301 // Remove the returned attribute for zapped functions and the
302 // corresponding call sites.
303 // Also remove any attributes that convert an undef return value into
304 // immediate undefined behavior
305 AttributeMask UBImplyingAttributes =
306 AttributeFuncs::getUBImplyingAttributes();
307 for (Function *F : FuncZappedReturn) {
308 for (Argument &A : F->args())
309 F->removeParamAttr(A.getArgNo(), Attribute::Returned);
310 F->removeRetAttrs(UBImplyingAttributes);
311 for (Use &U : F->uses()) {
312 CallBase *CB = dyn_cast<CallBase>(U.getUser());
313 if (!CB) {
314 assert(isa<Constant>(U.getUser()) &&
315 all_of(U.getUser()->users(), [](const User *UserUser) {
316 return cast<IntrinsicInst>(UserUser)->isAssumeLikeIntrinsic();
317 }));
318 continue;
319 }
320
321 for (Use &Arg : CB->args())
322 CB->removeParamAttr(CB->getArgOperandNo(&Arg), Attribute::Returned);
323 CB->removeRetAttrs(UBImplyingAttributes);
324 }
325 }
326
327 // If we inferred constant or undef values for globals variables, we can
328 // delete the global and any stores that remain to it.
329 for (const auto &I : make_early_inc_range(Solver.getTrackedGlobals())) {
330 GlobalVariable *GV = I.first;
331 if (SCCPSolver::isOverdefined(I.second))
332 continue;
333 LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName()
334 << "' is constant!\n");
335 for (User *U : make_early_inc_range(GV->users())) {
336 // We can remove LoadInst here. The LoadInsts in dead functions marked by
337 // FuncSpec are not simplified to constants, thus poison them.
339 "Only Store|Load Instruction can be user of GlobalVariable at "
340 "reaching here.");
342 if (isa<LoadInst>(I))
343 I->replaceAllUsesWith(PoisonValue::get(I->getType()));
344 I->eraseFromParent();
345 }
346
347 // Try to create a debug constant expression for the global variable
348 // initializer value.
350 GV->getDebugInfo(GVEs);
351 if (GVEs.size() == 1) {
352 DIBuilder DIB(M);
354 DIB, *GV->getInitializer(), *GV->getValueType()))
355 GVEs[0]->replaceOperandWith(1, InitExpr);
356 }
357
358 MadeChanges = true;
359 M.eraseGlobalVariable(GV);
360 ++NumGlobalConst;
361 }
362
363 return MadeChanges;
364}
365
367 const DataLayout &DL = M.getDataLayout();
368 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
369 auto GetTLI = [&FAM](Function &F) -> const TargetLibraryInfo & {
370 return FAM.getResult<TargetLibraryAnalysis>(F);
371 };
372 auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
373 return FAM.getResult<TargetIRAnalysis>(F);
374 };
375 auto GetAC = [&FAM](Function &F) -> AssumptionCache & {
376 return FAM.getResult<AssumptionAnalysis>(F);
377 };
378 auto GetDT = [&FAM](Function &F) -> DominatorTree & {
379 return FAM.getResult<DominatorTreeAnalysis>(F);
380 };
381 auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
382 return FAM.getResult<BlockFrequencyAnalysis>(F);
383 };
384
385
386 if (!runIPSCCP(M, DL, &FAM, GetTLI, GetTTI, GetAC, GetDT, GetBFI,
388 return PreservedAnalyses::all();
389
394 return PA;
395}
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:55
#define I(x, y, z)
Definition MD5.cpp:58
#define G(x, y, z)
Definition MD5.cpp:56
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:114
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:63
Analysis pass which computes a DominatorTree.
Definition Dominators.h:284
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:165
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
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition SCCP.cpp:366
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition ModRef.h:188
static MemoryEffectsBase unknown()
Definition ModRef.h:115
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)
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 ...
static LLVM_ABI bool isConstant(const ValueLatticeElement &LV)
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:168
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:356
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:322
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:1705
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
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:634
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:296
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:3385
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
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:548
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:2513
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
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:565
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
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