LLVM 18.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"
27#include "llvm/Support/ModRef.h"
28#include "llvm/Transforms/IPO.h"
33
34using namespace llvm;
35
36#define DEBUG_TYPE "sccp"
37
38STATISTIC(NumInstRemoved, "Number of instructions removed");
39STATISTIC(NumArgsElimed ,"Number of arguments constant propagated");
40STATISTIC(NumGlobalConst, "Number of globals found to be constant");
41STATISTIC(NumDeadBlocks , "Number of basic blocks unreachable");
42STATISTIC(NumInstReplaced,
43 "Number of instructions replaced with (simpler) instruction");
44
46 "funcspec-max-iters", cl::init(10), cl::Hidden, cl::desc(
47 "The maximum number of iterations function specialization is run"));
48
50 SmallVector<ReturnInst *, 8> &ReturnsToZap,
51 SCCPSolver &Solver) {
52 // We can only do this if we know that nothing else can call the function.
53 if (!Solver.isArgumentTrackedFunction(&F))
54 return;
55
56 if (Solver.mustPreserveReturn(&F)) {
58 dbgs()
59 << "Can't zap returns of the function : " << F.getName()
60 << " due to present musttail or \"clang.arc.attachedcall\" call of "
61 "it\n");
62 return;
63 }
64
65 assert(
66 all_of(F.users(),
67 [&Solver](User *U) {
68 if (isa<Instruction>(U) &&
69 !Solver.isBlockExecutable(cast<Instruction>(U)->getParent()))
70 return true;
71 // Non-callsite uses are not impacted by zapping. Also, constant
72 // uses (like blockaddresses) could stuck around, without being
73 // used in the underlying IR, meaning we do not have lattice
74 // values for them.
75 if (!isa<CallBase>(U))
76 return true;
77 if (U->getType()->isStructTy()) {
78 return all_of(Solver.getStructLatticeValueFor(U),
79 [](const ValueLatticeElement &LV) {
80 return !SCCPSolver::isOverdefined(LV);
81 });
82 }
83
84 // We don't consider assume-like intrinsics to be actual address
85 // captures.
86 if (auto *II = dyn_cast<IntrinsicInst>(U)) {
87 if (II->isAssumeLikeIntrinsic())
88 return true;
89 }
90
92 }) &&
93 "We can only zap functions where all live users have a concrete value");
94
95 for (BasicBlock &BB : F) {
96 if (CallInst *CI = BB.getTerminatingMustTailCall()) {
97 LLVM_DEBUG(dbgs() << "Can't zap return of the block due to present "
98 << "musttail call : " << *CI << "\n");
99 (void)CI;
100 return;
101 }
102
103 if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
104 if (!isa<UndefValue>(RI->getOperand(0)))
105 ReturnsToZap.push_back(RI);
106 }
107}
108
109static bool runIPSCCP(
111 std::function<const TargetLibraryInfo &(Function &)> GetTLI,
112 std::function<TargetTransformInfo &(Function &)> GetTTI,
113 std::function<AssumptionCache &(Function &)> GetAC,
114 std::function<DominatorTree &(Function &)> GetDT,
115 std::function<BlockFrequencyInfo &(Function &)> GetBFI,
116 bool IsFuncSpecEnabled) {
117 SCCPSolver Solver(DL, GetTLI, M.getContext());
118 FunctionSpecializer Specializer(Solver, M, FAM, GetBFI, GetTLI, GetTTI,
119 GetAC);
120
121 // Loop over all functions, marking arguments to those with their addresses
122 // taken or that are external as overdefined.
123 for (Function &F : M) {
124 if (F.isDeclaration())
125 continue;
126
127 DominatorTree &DT = GetDT(F);
128 AssumptionCache &AC = GetAC(F);
129 Solver.addPredicateInfo(F, DT, AC);
130
131 // Determine if we can track the function's return values. If so, add the
132 // function to the solver's set of return-tracked functions.
134 Solver.addTrackedFunction(&F);
135
136 // Determine if we can track the function's arguments. If so, add the
137 // function to the solver's set of argument-tracked functions.
140 continue;
141 }
142
143 // Assume the function is called.
144 Solver.markBlockExecutable(&F.front());
145
146 // Assume nothing about the incoming arguments.
147 for (Argument &AI : F.args())
148 Solver.markOverdefined(&AI);
149 }
150
151 // Determine if we can track any of the module's global variables. If so, add
152 // the global variables we can track to the solver's set of tracked global
153 // variables.
154 for (GlobalVariable &G : M.globals()) {
155 G.removeDeadConstantUsers();
158 }
159
160 // Solve for constants.
162
163 if (IsFuncSpecEnabled) {
164 unsigned Iters = 0;
165 while (Iters++ < FuncSpecMaxIters && Specializer.run());
166 }
167
168 // Iterate over all of the instructions in the module, replacing them with
169 // constants if we have found them to be of constant values.
170 bool MadeChanges = false;
171 for (Function &F : M) {
172 if (F.isDeclaration())
173 continue;
174
175 SmallVector<BasicBlock *, 512> BlocksToErase;
176
177 if (Solver.isBlockExecutable(&F.front())) {
178 bool ReplacedPointerArg = false;
179 for (Argument &Arg : F.args()) {
180 if (!Arg.use_empty() && Solver.tryToReplaceWithConstant(&Arg)) {
181 ReplacedPointerArg |= Arg.getType()->isPointerTy();
182 ++NumArgsElimed;
183 }
184 }
185
186 // If we replaced an argument, we may now also access a global (currently
187 // classified as "other" memory). Update memory attribute to reflect this.
188 if (ReplacedPointerArg) {
189 auto UpdateAttrs = [&](AttributeList AL) {
190 MemoryEffects ME = AL.getMemoryEffects();
191 if (ME == MemoryEffects::unknown())
192 return AL;
193
194 ME |= MemoryEffects(IRMemLocation::Other,
195 ME.getModRef(IRMemLocation::ArgMem));
196 return AL.addFnAttribute(
197 F.getContext(),
198 Attribute::getWithMemoryEffects(F.getContext(), ME));
199 };
200
201 F.setAttributes(UpdateAttrs(F.getAttributes()));
202 for (User *U : F.users()) {
203 auto *CB = dyn_cast<CallBase>(U);
204 if (!CB || CB->getCalledFunction() != &F)
205 continue;
206
207 CB->setAttributes(UpdateAttrs(CB->getAttributes()));
208 }
209 }
210 MadeChanges |= ReplacedPointerArg;
211 }
212
213 SmallPtrSet<Value *, 32> InsertedValues;
214 for (BasicBlock &BB : F) {
215 if (!Solver.isBlockExecutable(&BB)) {
216 LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
217 ++NumDeadBlocks;
218
219 MadeChanges = true;
220
221 if (&BB != &F.front())
222 BlocksToErase.push_back(&BB);
223 continue;
224 }
225
226 MadeChanges |= Solver.simplifyInstsInBlock(
227 BB, InsertedValues, NumInstRemoved, NumInstReplaced);
228 }
229
232 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
233 // Change dead blocks to unreachable. We do it after replacing constants
234 // in all executable blocks, because changeToUnreachable may remove PHI
235 // nodes in executable blocks we found values for. The function's entry
236 // block is not part of BlocksToErase, so we have to handle it separately.
237 for (BasicBlock *BB : BlocksToErase) {
238 NumInstRemoved += changeToUnreachable(BB->getFirstNonPHI(),
239 /*PreserveLCSSA=*/false, &DTU);
240 }
241 if (!Solver.isBlockExecutable(&F.front()))
242 NumInstRemoved += changeToUnreachable(F.front().getFirstNonPHI(),
243 /*PreserveLCSSA=*/false, &DTU);
244
245 BasicBlock *NewUnreachableBB = nullptr;
246 for (BasicBlock &BB : F)
247 MadeChanges |= Solver.removeNonFeasibleEdges(&BB, DTU, NewUnreachableBB);
248
249 for (BasicBlock *DeadBB : BlocksToErase)
250 if (!DeadBB->hasAddressTaken())
251 DTU.deleteBB(DeadBB);
252
253 for (BasicBlock &BB : F) {
254 for (Instruction &Inst : llvm::make_early_inc_range(BB)) {
255 if (Solver.getPredicateInfoFor(&Inst)) {
256 if (auto *II = dyn_cast<IntrinsicInst>(&Inst)) {
257 if (II->getIntrinsicID() == Intrinsic::ssa_copy) {
258 Value *Op = II->getOperand(0);
259 Inst.replaceAllUsesWith(Op);
260 Inst.eraseFromParent();
261 }
262 }
263 }
264 }
265 }
266 }
267
268 // If we inferred constant or undef return values for a function, we replaced
269 // all call uses with the inferred value. This means we don't need to bother
270 // actually returning anything from the function. Replace all return
271 // instructions with return undef.
272 //
273 // Do this in two stages: first identify the functions we should process, then
274 // actually zap their returns. This is important because we can only do this
275 // if the address of the function isn't taken. In cases where a return is the
276 // last use of a function, the order of processing functions would affect
277 // whether other functions are optimizable.
278 SmallVector<ReturnInst*, 8> ReturnsToZap;
279
280 for (const auto &I : Solver.getTrackedRetVals()) {
281 Function *F = I.first;
282 const ValueLatticeElement &ReturnValue = I.second;
283
284 // If there is a known constant range for the return value, add !range
285 // metadata to the function's call sites.
286 if (ReturnValue.isConstantRange() &&
287 !ReturnValue.getConstantRange().isSingleElement()) {
288 // Do not add range metadata if the return value may include undef.
289 if (ReturnValue.isConstantRangeIncludingUndef())
290 continue;
291
292 auto &CR = ReturnValue.getConstantRange();
293 for (User *User : F->users()) {
294 auto *CB = dyn_cast<CallBase>(User);
295 if (!CB || CB->getCalledFunction() != F)
296 continue;
297
298 // Do not touch existing metadata for now.
299 // TODO: We should be able to take the intersection of the existing
300 // metadata and the inferred range.
301 if (CB->getMetadata(LLVMContext::MD_range))
302 continue;
303
304 LLVMContext &Context = CB->getParent()->getContext();
305 Metadata *RangeMD[] = {
308 CB->setMetadata(LLVMContext::MD_range, MDNode::get(Context, RangeMD));
309 }
310 continue;
311 }
312 if (F->getReturnType()->isVoidTy())
313 continue;
314 if (SCCPSolver::isConstant(ReturnValue) || ReturnValue.isUnknownOrUndef())
315 findReturnsToZap(*F, ReturnsToZap, Solver);
316 }
317
318 for (auto *F : Solver.getMRVFunctionsTracked()) {
319 assert(F->getReturnType()->isStructTy() &&
320 "The return type should be a struct");
321 StructType *STy = cast<StructType>(F->getReturnType());
322 if (Solver.isStructLatticeConstant(F, STy))
323 findReturnsToZap(*F, ReturnsToZap, Solver);
324 }
325
326 // Zap all returns which we've identified as zap to change.
327 SmallSetVector<Function *, 8> FuncZappedReturn;
328 for (ReturnInst *RI : ReturnsToZap) {
329 Function *F = RI->getParent()->getParent();
330 RI->setOperand(0, UndefValue::get(F->getReturnType()));
331 // Record all functions that are zapped.
332 FuncZappedReturn.insert(F);
333 }
334
335 // Remove the returned attribute for zapped functions and the
336 // corresponding call sites.
337 // Also remove any attributes that convert an undef return value into
338 // immediate undefined behavior
339 AttributeMask UBImplyingAttributes =
341 for (Function *F : FuncZappedReturn) {
342 for (Argument &A : F->args())
343 F->removeParamAttr(A.getArgNo(), Attribute::Returned);
344 F->removeRetAttrs(UBImplyingAttributes);
345 for (Use &U : F->uses()) {
346 CallBase *CB = dyn_cast<CallBase>(U.getUser());
347 if (!CB) {
348 assert(isa<BlockAddress>(U.getUser()) ||
349 (isa<Constant>(U.getUser()) &&
350 all_of(U.getUser()->users(), [](const User *UserUser) {
351 return cast<IntrinsicInst>(UserUser)->isAssumeLikeIntrinsic();
352 })));
353 continue;
354 }
355
356 for (Use &Arg : CB->args())
357 CB->removeParamAttr(CB->getArgOperandNo(&Arg), Attribute::Returned);
358 CB->removeRetAttrs(UBImplyingAttributes);
359 }
360 }
361
362 // If we inferred constant or undef values for globals variables, we can
363 // delete the global and any stores that remain to it.
364 for (const auto &I : make_early_inc_range(Solver.getTrackedGlobals())) {
365 GlobalVariable *GV = I.first;
366 if (SCCPSolver::isOverdefined(I.second))
367 continue;
368 LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName()
369 << "' is constant!\n");
370 while (!GV->use_empty()) {
371 StoreInst *SI = cast<StoreInst>(GV->user_back());
372 SI->eraseFromParent();
373 }
374 MadeChanges = true;
375 M.eraseGlobalVariable(GV);
376 ++NumGlobalConst;
377 }
378
379 return MadeChanges;
380}
381
383 const DataLayout &DL = M.getDataLayout();
384 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
385 auto GetTLI = [&FAM](Function &F) -> const TargetLibraryInfo & {
387 };
388 auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
390 };
391 auto GetAC = [&FAM](Function &F) -> AssumptionCache & {
393 };
394 auto GetDT = [&FAM](Function &F) -> DominatorTree & {
396 };
397 auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
399 };
400
401
402 if (!runIPSCCP(M, DL, &FAM, GetTLI, GetTTI, GetAC, GetDT, GetBFI,
404 return PreservedAnalyses::all();
405
410 return PA;
411}
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...
#define LLVM_DEBUG(X)
Definition: Debug.h:101
static void findReturnsToZap(Function &F, SmallVector< ReturnInst *, 8 > &ReturnsToZap, SCCPSolver &Solver)
Definition: SCCP.cpp:49
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:109
#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
LLVMContext & Context
if(VerifyEach)
FunctionAnalysisManager FAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
This pass exposes codegen information to IR-level passes.
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:620
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
Definition: PassManager.h:793
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:774
This class represents an incoming formal argument to a Function.
Definition: Argument.h:28
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
static Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
Definition: Attributes.cpp:215
LLVM Basic Block Representation.
Definition: BasicBlock.h:56
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...
Definition: InstrTypes.h:1190
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Removes the attribute from the given argument.
Definition: InstrTypes.h:1588
void removeRetAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the return value.
Definition: InstrTypes.h:1583
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
Definition: InstrTypes.h:1348
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
Definition: InstrTypes.h:1388
This class represents a function call, abstracting a target machine's calling convention.
static ConstantAsMetadata * get(Constant *C)
Definition: Metadata.h:419
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:888
bool isSingleElement() const
Return true if this set contains exactly one member.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:110
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:279
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:166
bool run()
Attempt to specialize functions in the module to enable constant propagation across function boundari...
bool isFuncSpecEnabled() const
Definition: SCCP.h:58
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition: SCCP.cpp:382
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Definition: PassManager.h:933
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1416
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition: ModRef.h:165
static MemoryEffectsBase unknown()
Create MemoryEffectsBase that can read and write any memory.
Definition: ModRef.h:112
Root of the metadata hierarchy.
Definition: Metadata.h:61
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
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: PassManager.h:152
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:158
void preserve()
Mark an analysis as preserved.
Definition: PassManager.h:173
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:65
const DenseMap< GlobalVariable *, ValueLatticeElement > & getTrackedGlobals()
getTrackedGlobals - Get and return the set of inferred initializers for global variables.
void trackValueOfGlobalVariable(GlobalVariable *GV)
trackValueOfGlobalVariable - Clients can use this method to inform the SCCPSolver that it should trac...
bool tryToReplaceWithConstant(Value *V)
Definition: SCCPSolver.cpp:76
bool isStructLatticeConstant(Function *F, StructType *STy)
void addPredicateInfo(Function &F, DominatorTree &DT, AssumptionCache &AC)
void addTrackedFunction(Function *F)
addTrackedFunction - If the SCCP solver is supposed to track calls into and out of the specified func...
const MapVector< Function *, ValueLatticeElement > & getTrackedRetVals()
getTrackedRetVals - Get the inferred return value map.
void solveWhileResolvedUndefsIn(Module &M)
const PredicateBase * getPredicateInfoFor(Instruction *I)
void addArgumentTrackedFunction(Function *F)
const SmallPtrSet< Function *, 16 > getMRVFunctionsTracked()
getMRVFunctionsTracked - Get the set of functions which return multiple values tracked by the pass.
bool simplifyInstsInBlock(BasicBlock &BB, SmallPtrSetImpl< Value * > &InsertedValues, Statistic &InstRemovedStat, Statistic &InstReplacedStat)
Definition: SCCPSolver.cpp:210
const ValueLatticeElement & getLatticeValueFor(Value *V) const
bool removeNonFeasibleEdges(BasicBlock *BB, DomTreeUpdater &DTU, BasicBlock *&NewUnreachableBB) const
Definition: SCCPSolver.cpp:234
bool isBlockExecutable(BasicBlock *BB) const
bool markBlockExecutable(BasicBlock *BB)
markBlockExecutable - This method can be used by clients to mark all of the blocks that are known to ...
static bool isConstant(const ValueLatticeElement &LV)
Definition: SCCPSolver.cpp:55
bool mustPreserveReturn(Function *F)
Returns true if the return of the given function cannot be modified.
static bool isOverdefined(const ValueLatticeElement &LV)
Definition: SCCPSolver.cpp:60
bool isArgumentTrackedFunction(Function *F)
Returns true if the given function is in the solver's set of argument-tracked functions.
void markOverdefined(Value *V)
markOverdefined - Mark the specified value overdefined.
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:162
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:451
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:370
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
An instruction for storing to memory.
Definition: Instructions.h:301
Class to represent struct types.
Definition: DerivedTypes.h:213
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.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1724
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
This class represents lattice values for constants.
Definition: ValueLattice.h:29
bool isConstantRangeIncludingUndef() const
Definition: ValueLattice.h:245
const ConstantRange & getConstantRange(bool UndefAllowed=true) const
Returns the constant range for this value.
Definition: ValueLattice.h:272
bool isConstantRange(bool UndefAllowed=true) const
Returns true if this value is a constant range.
Definition: ValueLattice.h:252
bool isUnknownOrUndef() const
Definition: ValueLattice.h:242
LLVM Value Representation.
Definition: Value.h:74
User * user_back()
Definition: Value.h:407
bool use_empty() const
Definition: Value.h:344
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
AttributeMask getUBImplyingAttributes()
Get param/return attributes which imply immediate undefined behavior if an invalid value is passed.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:1727
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:666
bool canTrackGlobalVariableInterprocedurally(GlobalVariable *GV)
Determine if the value maintained in the given global variable can be tracked interprocedurally.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition: ModRef.h:268
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
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:2306
bool canTrackReturnsInterprocedurally(Function *F)
Determine if the values of the given function's returns can be tracked interprocedurally.
bool canTrackArgumentsInterprocedurally(Function *F)
Determine if the values of the given function's arguments can be tracked interprocedurally.