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 "IPOOptions.h"
15#include "llvm/ADT/SetVector.h"
25#include "llvm/IR/Constants.h"
26#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 SmallVector<ReturnInst *, 8> &ReturnsToZap,
48 SCCPSolver &Solver) {
49 // We can only do this if we know that nothing else can call the function.
50 if (!Solver.isArgumentTrackedFunction(&F))
51 return;
52
53 if (Solver.mustPreserveReturn(&F)) {
55 dbgs()
56 << "Can't zap returns of the function : " << F.getName()
57 << " due to present musttail or \"clang.arc.attachedcall\" call of "
58 "it\n");
59 return;
60 }
61
62 assert(
63 all_of(F.users(),
64 [&Solver](User *U) {
65 if (isa<Instruction>(U) &&
66 !Solver.isBlockExecutable(cast<Instruction>(U)->getParent()))
67 return true;
68 // Non-callsite uses are not impacted by zapping. Also, constant
69 // uses (like blockaddresses) could stuck around, without being
70 // used in the underlying IR, meaning we do not have lattice
71 // values for them.
72 if (!isa<CallBase>(U))
73 return true;
74 if (U->getType()->isStructTy()) {
75 return none_of(Solver.getStructLatticeValueFor(U),
76 SCCPSolver::isOverdefined);
77 }
78
79 // We don't consider assume-like intrinsics to be actual address
80 // captures.
81 if (auto *II = dyn_cast<IntrinsicInst>(U)) {
82 if (II->isAssumeLikeIntrinsic())
83 return true;
84 }
85
87 }) &&
88 "We can only zap functions where all live users have a concrete value");
89
90 for (BasicBlock &BB : F) {
91 if (CallInst *CI = BB.getTerminatingMustTailCall()) {
92 LLVM_DEBUG(dbgs() << "Can't zap return of the block due to present "
93 << "musttail call : " << *CI << "\n");
94 (void)CI;
95 return;
96 }
97
98 if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
99 if (!isa<UndefValue>(RI->getOperand(0)))
100 ReturnsToZap.push_back(RI);
101 }
102}
103
104static bool runIPSCCP(
106 std::function<const TargetLibraryInfo &(Function &)> GetTLI,
107 std::function<TargetTransformInfo &(Function &)> GetTTI,
108 std::function<AssumptionCache &(Function &)> GetAC,
109 std::function<DominatorTree &(Function &)> GetDT,
110 std::function<BlockFrequencyInfo &(Function &)> GetBFI,
111 bool IsFuncSpecEnabled) {
112 SCCPSolver Solver(DL, GetTLI, M.getContext());
113 FunctionSpecializer Specializer(Solver, M, FAM, GetBFI, GetTLI, GetTTI,
114 GetAC);
115
116 // Loop over all functions, marking arguments to those with their addresses
117 // taken or that are external as overdefined.
118 for (Function &F : M) {
119 if (F.isDeclaration())
120 continue;
121
122 DominatorTree &DT = GetDT(F);
123 AssumptionCache &AC = GetAC(F);
124 Solver.addPredicateInfo(F, DT, AC);
125
126 // Determine if we can track the function's return values. If so, add the
127 // function to the solver's set of return-tracked functions.
129 Solver.addTrackedFunction(&F);
130
131 // Determine if we can track the function's arguments. If so, add the
132 // function to the solver's set of argument-tracked functions.
135 continue;
136 }
137
138 // Assume the function is called.
139 Solver.markBlockExecutable(&F.front());
140
141 for (Argument &AI : F.args())
142 Solver.trackValueOfArgument(&AI);
143 }
144
145 // Determine if we can track any of the module's global variables. If so, add
146 // the global variables we can track to the solver's set of tracked global
147 // variables.
148 for (GlobalVariable &G : M.globals()) {
149 G.removeDeadConstantUsers();
152 }
153
154 // Solve for constants.
156
157 if (IsFuncSpecEnabled) {
158 unsigned MaxIters = getIPOOptions(M).funcspec_max_iters;
159 for (unsigned Iters = 0; Iters < MaxIters && Specializer.run(); ++Iters)
160 ;
161 }
162
163 // Iterate over all of the instructions in the module, replacing them with
164 // constants if we have found them to be of constant values.
165 bool MadeChanges = false;
166 for (Function &F : M) {
167 if (F.isDeclaration())
168 continue;
169 // Skip the dead functions marked by FunctionSpecializer, avoiding removing
170 // blocks in dead functions. Set MadeChanges if there is any dead function
171 // that will be removed later.
172 if (IsFuncSpecEnabled && Specializer.isDeadFunction(&F)) {
173 MadeChanges = true;
174 continue;
175 }
176
177 SmallVector<BasicBlock *, 512> BlocksToErase;
178
179 if (Solver.isBlockExecutable(&F.front())) {
180 bool ReplacedPointerArg = false;
181 for (Argument &Arg : F.args()) {
182 if (!Arg.use_empty() && Solver.tryToReplaceWithConstant(&Arg)) {
183 ReplacedPointerArg |= Arg.getType()->isPointerTy();
184 ++NumArgsElimed;
185 }
186 }
187
188 // If we replaced an argument, we may now also access a global (currently
189 // classified as "other" memory). Update memory attribute to reflect this.
190 if (ReplacedPointerArg) {
191 auto UpdateAttrs = [&](AttributeList AL) {
192 MemoryEffects ME = AL.getMemoryEffects();
193 if (ME == MemoryEffects::unknown())
194 return AL;
195
197 ME |= MemoryEffects(IRMemLocation::ErrnoMem, ArgMemMR);
198 ME |= MemoryEffects(IRMemLocation::Other, ArgMemMR);
199
200 return AL.addFnAttribute(
201 F.getContext(),
202 Attribute::getWithMemoryEffects(F.getContext(), ME));
203 };
204
205 F.setAttributes(UpdateAttrs(F.getAttributes()));
206 for (User *U : F.users()) {
207 auto *CB = dyn_cast<CallBase>(U);
208 if (!CB || CB->getCalledFunction() != &F)
209 continue;
210
211 CB->setAttributes(UpdateAttrs(CB->getAttributes()));
212 }
213 }
214 MadeChanges |= ReplacedPointerArg;
215 }
216
217 SmallPtrSet<Value *, 32> InsertedValues;
218 for (BasicBlock &BB : F) {
219 if (!Solver.isBlockExecutable(&BB)) {
220 LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
221 ++NumDeadBlocks;
222
223 MadeChanges = true;
224
225 if (&BB != &F.front())
226 BlocksToErase.push_back(&BB);
227 continue;
228 }
229
230 MadeChanges |= Solver.simplifyInstsInBlock(
231 BB, InsertedValues, NumInstRemoved, NumInstReplaced);
232 }
233
234 DominatorTree *DT = FAM->getCachedResult<DominatorTreeAnalysis>(F);
235 PostDominatorTree *PDT = FAM->getCachedResult<PostDominatorTreeAnalysis>(F);
236 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
237 // Change dead blocks to unreachable. We do it after replacing constants
238 // in all executable blocks, because changeToUnreachable may remove PHI
239 // nodes in executable blocks we found values for. The function's entry
240 // block is not part of BlocksToErase, so we have to handle it separately.
241 for (BasicBlock *BB : BlocksToErase) {
242 NumInstRemoved += changeToUnreachable(&*BB->getFirstNonPHIIt(),
243 /*PreserveLCSSA=*/false, &DTU);
244 }
245 if (!Solver.isBlockExecutable(&F.front()))
246 NumInstRemoved += changeToUnreachable(&*F.front().getFirstNonPHIIt(),
247 /*PreserveLCSSA=*/false, &DTU);
248
249 BasicBlock *NewUnreachableBB = nullptr;
250 for (BasicBlock &BB : F)
251 MadeChanges |= Solver.removeNonFeasibleEdges(&BB, DTU, NewUnreachableBB);
252
253 for (BasicBlock *DeadBB : BlocksToErase)
254 if (!DeadBB->hasAddressTaken())
255 DTU.deleteBB(DeadBB);
256
257 Solver.removeSSACopies(F);
258 }
259
260 // If we inferred constant or undef return values for a function, we replaced
261 // all call uses with the inferred value. This means we don't need to bother
262 // actually returning anything from the function. Replace all return
263 // instructions with return undef.
264 //
265 // Do this in two stages: first identify the functions we should process, then
266 // actually zap their returns. This is important because we can only do this
267 // if the address of the function isn't taken. In cases where a return is the
268 // last use of a function, the order of processing functions would affect
269 // whether other functions are optimizable.
270 SmallVector<ReturnInst*, 8> ReturnsToZap;
271
272 Solver.inferReturnAttributes();
273 Solver.inferArgAttributes();
274 for (const auto &[F, ReturnValue] : Solver.getTrackedRetVals()) {
275 assert(!F->getReturnType()->isVoidTy() &&
276 "should not track void functions");
277 if (SCCPSolver::isReplaceableConstant(ReturnValue) ||
278 ReturnValue.isUnknownOrUndef())
279 findReturnsToZap(*F, ReturnsToZap, Solver);
280 }
281
282 for (auto *F : Solver.getMRVFunctionsTracked()) {
283 assert(F->getReturnType()->isStructTy() &&
284 "The return type should be a struct");
285 StructType *STy = cast<StructType>(F->getReturnType());
286 if (Solver.isStructLatticeConstant(F, STy))
287 findReturnsToZap(*F, ReturnsToZap, Solver);
288 }
289
290 // Zap all returns which we've identified as zap to change.
291 SmallSetVector<Function *, 8> FuncZappedReturn;
292 for (ReturnInst *RI : ReturnsToZap) {
293 Function *F = RI->getParent()->getParent();
294 RI->setOperand(0, PoisonValue::get(F->getReturnType()));
295 // Record all functions that are zapped.
296 FuncZappedReturn.insert(F);
297 }
298
299 // Remove the returned attribute for zapped functions and the
300 // corresponding call sites.
301 // Also remove any attributes that convert an undef return value into
302 // immediate undefined behavior
303 AttributeMask UBImplyingAttributes =
304 AttributeFuncs::getUBImplyingAttributes();
305 for (Function *F : FuncZappedReturn) {
306 for (Argument &A : F->args())
307 F->removeParamAttr(A.getArgNo(), Attribute::Returned);
308 F->removeRetAttrs(UBImplyingAttributes);
309 for (Use &U : F->uses()) {
310 CallBase *CB = dyn_cast<CallBase>(U.getUser());
311 if (!CB) {
312 assert(isa<Constant>(U.getUser()) &&
313 all_of(U.getUser()->users(), [](const User *UserUser) {
314 return cast<IntrinsicInst>(UserUser)->isAssumeLikeIntrinsic();
315 }));
316 continue;
317 }
318
319 for (Use &Arg : CB->args())
320 CB->removeParamAttr(CB->getArgOperandNo(&Arg), Attribute::Returned);
321 CB->removeRetAttrs(UBImplyingAttributes);
322 }
323 }
324
325 // If we inferred constant or undef values for globals variables, we can
326 // delete the global and any stores that remain to it.
327 for (const auto &[GV, LV] : Solver.getTrackedGlobals()) {
328 // We may have inferred a constant that is not replaceable (e.g., due to
329 // different pointer provenance), so skip deleting the global in this case.
330 if (!SCCPSolver::isReplaceableConstant(LV) && !LV.isUnknownOrUndef())
331 continue;
332 LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName()
333 << "' is constant!\n");
334 for (User *U : make_early_inc_range(GV->users())) {
335 // We can remove LoadInst here. The LoadInsts in dead functions marked by
336 // FuncSpec are not simplified to constants, thus poison them.
338 "Only Store|Load Instruction can be user of GlobalVariable at "
339 "reaching here.");
341 if (isa<LoadInst>(I))
342 I->replaceAllUsesWith(PoisonValue::get(I->getType()));
343 I->eraseFromParent();
344 }
345
346 // Try to create a debug constant expression for the global variable
347 // initializer value.
349 GV->getDebugInfo(GVEs);
350 if (GVEs.size() == 1) {
351 DIBuilder DIB(M);
353 DIB, *GV->getInitializer(), *GV->getValueType()))
354 GVEs[0]->replaceOperandWith(1, InitExpr);
355 }
356
357 MadeChanges = true;
358 M.eraseGlobalVariable(GV);
359 ++NumGlobalConst;
360 }
361
362 return MadeChanges;
363}
364
366 const DataLayout &DL = M.getDataLayout();
367 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
368 auto GetTLI = [&FAM](Function &F) -> const TargetLibraryInfo & {
369 return FAM.getResult<TargetLibraryAnalysis>(F);
370 };
371 auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
372 return FAM.getResult<TargetIRAnalysis>(F);
373 };
374 auto GetAC = [&FAM](Function &F) -> AssumptionCache & {
375 return FAM.getResult<AssumptionAnalysis>(F);
376 };
377 auto GetDT = [&FAM](Function &F) -> DominatorTree & {
378 return FAM.getResult<DominatorTreeAnalysis>(F);
379 };
380 auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
381 return FAM.getResult<BlockFrequencyAnalysis>(F);
382 };
383
384
385 if (!runIPSCCP(M, DL, &FAM, GetTLI, GetTTI, GetAC, GetDT, GetBFI,
387 return PreservedAnalyses::all();
388
393 return PA;
394}
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:46
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:104
#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...
bool isFuncSpecEnabled() const
Definition SCCP.h:58
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition SCCP.cpp:365
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:68
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:346
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
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:1755
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:649
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
const IPOOptions & getIPOOptions(const LLVMContext &C)
Definition IPOOptions.h:36
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:3503
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:2592
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