LLVM 17.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(1), 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,
115 bool IsFuncSpecEnabled) {
116 SCCPSolver Solver(DL, GetTLI, M.getContext());
117 FunctionSpecializer Specializer(Solver, M, FAM, GetTLI, GetTTI, GetAC);
118
119 // Loop over all functions, marking arguments to those with their addresses
120 // taken or that are external as overdefined.
121 for (Function &F : M) {
122 if (F.isDeclaration())
123 continue;
124
125 Solver.addAnalysis(F, getAnalysis(F));
126
127 // Determine if we can track the function's return values. If so, add the
128 // function to the solver's set of return-tracked functions.
130 Solver.addTrackedFunction(&F);
131
132 // Determine if we can track the function's arguments. If so, add the
133 // function to the solver's set of argument-tracked functions.
136 continue;
137 }
138
139 // Assume the function is called.
140 Solver.markBlockExecutable(&F.front());
141
142 // Assume nothing about the incoming arguments.
143 for (Argument &AI : F.args())
144 Solver.markOverdefined(&AI);
145 }
146
147 // Determine if we can track any of the module's global variables. If so, add
148 // the global variables we can track to the solver's set of tracked global
149 // variables.
150 for (GlobalVariable &G : M.globals()) {
151 G.removeDeadConstantUsers();
154 }
155
156 // Solve for constants.
158
159 if (IsFuncSpecEnabled) {
160 unsigned Iters = 0;
161 while (Iters++ < FuncSpecMaxIters && Specializer.run());
162 }
163
164 // Iterate over all of the instructions in the module, replacing them with
165 // constants if we have found them to be of constant values.
166 bool MadeChanges = false;
167 for (Function &F : M) {
168 if (F.isDeclaration())
169 continue;
170
171 SmallVector<BasicBlock *, 512> BlocksToErase;
172
173 if (Solver.isBlockExecutable(&F.front())) {
174 bool ReplacedPointerArg = false;
175 for (Argument &Arg : F.args()) {
176 if (!Arg.use_empty() && Solver.tryToReplaceWithConstant(&Arg)) {
177 ReplacedPointerArg |= Arg.getType()->isPointerTy();
178 ++NumArgsElimed;
179 }
180 }
181
182 // If we replaced an argument, we may now also access a global (currently
183 // classified as "other" memory). Update memory attribute to reflect this.
184 if (ReplacedPointerArg) {
185 auto UpdateAttrs = [&](AttributeList AL) {
186 MemoryEffects ME = AL.getMemoryEffects();
187 if (ME == MemoryEffects::unknown())
188 return AL;
189
192 return AL.addFnAttribute(
193 F.getContext(),
194 Attribute::getWithMemoryEffects(F.getContext(), ME));
195 };
196
197 F.setAttributes(UpdateAttrs(F.getAttributes()));
198 for (User *U : F.users()) {
199 auto *CB = dyn_cast<CallBase>(U);
200 if (!CB || CB->getCalledFunction() != &F)
201 continue;
202
203 CB->setAttributes(UpdateAttrs(CB->getAttributes()));
204 }
205 }
206 MadeChanges |= ReplacedPointerArg;
207 }
208
209 SmallPtrSet<Value *, 32> InsertedValues;
210 for (BasicBlock &BB : F) {
211 if (!Solver.isBlockExecutable(&BB)) {
212 LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
213 ++NumDeadBlocks;
214
215 MadeChanges = true;
216
217 if (&BB != &F.front())
218 BlocksToErase.push_back(&BB);
219 continue;
220 }
221
222 MadeChanges |= Solver.simplifyInstsInBlock(
223 BB, InsertedValues, NumInstRemoved, NumInstReplaced);
224 }
225
226 DomTreeUpdater DTU = IsFuncSpecEnabled && Specializer.isClonedFunction(&F)
227 ? DomTreeUpdater(DomTreeUpdater::UpdateStrategy::Lazy)
228 : Solver.getDTU(F);
229
230 // Change dead blocks to unreachable. We do it after replacing constants
231 // in all executable blocks, because changeToUnreachable may remove PHI
232 // nodes in executable blocks we found values for. The function's entry
233 // block is not part of BlocksToErase, so we have to handle it separately.
234 for (BasicBlock *BB : BlocksToErase) {
235 NumInstRemoved += changeToUnreachable(BB->getFirstNonPHI(),
236 /*PreserveLCSSA=*/false, &DTU);
237 }
238 if (!Solver.isBlockExecutable(&F.front()))
239 NumInstRemoved += changeToUnreachable(F.front().getFirstNonPHI(),
240 /*PreserveLCSSA=*/false, &DTU);
241
242 BasicBlock *NewUnreachableBB = nullptr;
243 for (BasicBlock &BB : F)
244 MadeChanges |= Solver.removeNonFeasibleEdges(&BB, DTU, NewUnreachableBB);
245
246 for (BasicBlock *DeadBB : BlocksToErase)
247 if (!DeadBB->hasAddressTaken())
248 DTU.deleteBB(DeadBB);
249
250 for (BasicBlock &BB : F) {
251 for (Instruction &Inst : llvm::make_early_inc_range(BB)) {
252 if (Solver.getPredicateInfoFor(&Inst)) {
253 if (auto *II = dyn_cast<IntrinsicInst>(&Inst)) {
254 if (II->getIntrinsicID() == Intrinsic::ssa_copy) {
255 Value *Op = II->getOperand(0);
256 Inst.replaceAllUsesWith(Op);
257 Inst.eraseFromParent();
258 }
259 }
260 }
261 }
262 }
263 }
264
265 // If we inferred constant or undef return values for a function, we replaced
266 // all call uses with the inferred value. This means we don't need to bother
267 // actually returning anything from the function. Replace all return
268 // instructions with return undef.
269 //
270 // Do this in two stages: first identify the functions we should process, then
271 // actually zap their returns. This is important because we can only do this
272 // if the address of the function isn't taken. In cases where a return is the
273 // last use of a function, the order of processing functions would affect
274 // whether other functions are optimizable.
275 SmallVector<ReturnInst*, 8> ReturnsToZap;
276
277 for (const auto &I : Solver.getTrackedRetVals()) {
278 Function *F = I.first;
279 const ValueLatticeElement &ReturnValue = I.second;
280
281 // If there is a known constant range for the return value, add !range
282 // metadata to the function's call sites.
283 if (ReturnValue.isConstantRange() &&
284 !ReturnValue.getConstantRange().isSingleElement()) {
285 // Do not add range metadata if the return value may include undef.
286 if (ReturnValue.isConstantRangeIncludingUndef())
287 continue;
288
289 auto &CR = ReturnValue.getConstantRange();
290 for (User *User : F->users()) {
291 auto *CB = dyn_cast<CallBase>(User);
292 if (!CB || CB->getCalledFunction() != F)
293 continue;
294
295 // Do not touch existing metadata for now.
296 // TODO: We should be able to take the intersection of the existing
297 // metadata and the inferred range.
298 if (CB->getMetadata(LLVMContext::MD_range))
299 continue;
300
301 LLVMContext &Context = CB->getParent()->getContext();
302 Metadata *RangeMD[] = {
305 CB->setMetadata(LLVMContext::MD_range, MDNode::get(Context, RangeMD));
306 }
307 continue;
308 }
309 if (F->getReturnType()->isVoidTy())
310 continue;
311 if (SCCPSolver::isConstant(ReturnValue) || ReturnValue.isUnknownOrUndef())
312 findReturnsToZap(*F, ReturnsToZap, Solver);
313 }
314
315 for (auto *F : Solver.getMRVFunctionsTracked()) {
316 assert(F->getReturnType()->isStructTy() &&
317 "The return type should be a struct");
318 StructType *STy = cast<StructType>(F->getReturnType());
319 if (Solver.isStructLatticeConstant(F, STy))
320 findReturnsToZap(*F, ReturnsToZap, Solver);
321 }
322
323 // Zap all returns which we've identified as zap to change.
324 SmallSetVector<Function *, 8> FuncZappedReturn;
325 for (ReturnInst *RI : ReturnsToZap) {
326 Function *F = RI->getParent()->getParent();
327 RI->setOperand(0, UndefValue::get(F->getReturnType()));
328 // Record all functions that are zapped.
329 FuncZappedReturn.insert(F);
330 }
331
332 // Remove the returned attribute for zapped functions and the
333 // corresponding call sites.
334 // Also remove any attributes that convert an undef return value into
335 // immediate undefined behavior
336 AttributeMask UBImplyingAttributes =
338 for (Function *F : FuncZappedReturn) {
339 for (Argument &A : F->args())
340 F->removeParamAttr(A.getArgNo(), Attribute::Returned);
341 F->removeRetAttrs(UBImplyingAttributes);
342 for (Use &U : F->uses()) {
343 CallBase *CB = dyn_cast<CallBase>(U.getUser());
344 if (!CB) {
345 assert(isa<BlockAddress>(U.getUser()) ||
346 (isa<Constant>(U.getUser()) &&
347 all_of(U.getUser()->users(), [](const User *UserUser) {
348 return cast<IntrinsicInst>(UserUser)->isAssumeLikeIntrinsic();
349 })));
350 continue;
351 }
352
353 for (Use &Arg : CB->args())
354 CB->removeParamAttr(CB->getArgOperandNo(&Arg), Attribute::Returned);
355 CB->removeRetAttrs(UBImplyingAttributes);
356 }
357 }
358
359 // If we inferred constant or undef values for globals variables, we can
360 // delete the global and any stores that remain to it.
361 for (const auto &I : make_early_inc_range(Solver.getTrackedGlobals())) {
362 GlobalVariable *GV = I.first;
363 if (SCCPSolver::isOverdefined(I.second))
364 continue;
365 LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName()
366 << "' is constant!\n");
367 while (!GV->use_empty()) {
368 StoreInst *SI = cast<StoreInst>(GV->user_back());
369 SI->eraseFromParent();
370 MadeChanges = true;
371 }
372 M.eraseGlobalVariable(GV);
373 ++NumGlobalConst;
374 }
375
376 return MadeChanges;
377}
378
380 const DataLayout &DL = M.getDataLayout();
381 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
382 auto GetTLI = [&FAM](Function &F) -> const TargetLibraryInfo & {
384 };
385 auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
387 };
388 auto GetAC = [&FAM](Function &F) -> AssumptionCache & {
390 };
391 auto getAnalysis = [&FAM, this](Function &F) -> AnalysisResultsForFn {
393 return {
394 std::make_unique<PredicateInfo>(F, DT, FAM.getResult<AssumptionAnalysis>(F)),
396 isFuncSpecEnabled() ? &FAM.getResult<LoopAnalysis>(F) : nullptr };
397 };
398
399 if (!runIPSCCP(M, DL, &FAM, GetTLI, GetTTI, GetAC, getAnalysis,
401 return PreservedAnalyses::all();
402
407 return PA;
408}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
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(1), 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, function_ref< AnalysisResultsForFn(Function &)> getAnalysis, 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
@ SI
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:214
LLVM Basic Block Representation.
Definition: BasicBlock.h:56
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1186
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Removes the attribute from the given argument.
Definition: InstrTypes.h:1580
void removeRetAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the return value.
Definition: InstrTypes.h:1575
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
Definition: InstrTypes.h:1344
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:1384
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.
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:110
void deleteBB(BasicBlock *DelBB)
Delete DelBB.
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:379
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
Analysis pass that exposes the LoopInfo for a function.
Definition: LoopInfo.h:1268
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1399
Summary of how a function affects memory in the program.
Definition: ModRef.h:63
@ ArgMem
Access to memory via argument pointers.
Definition: ModRef.h:68
@ Other
Any other memory.
Definition: ModRef.h:72
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition: ModRef.h:164
static MemoryEffects unknown()
Create MemoryEffects that can read and write any memory.
Definition: ModRef.h:113
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.
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:75
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:75
bool isStructLatticeConstant(Function *F, StructType *STy)
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)
DomTreeUpdater getDTU(Function &F)
void addArgumentTrackedFunction(Function *F)
void addAnalysis(Function &F, AnalysisResultsForFn A)
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:230
const ValueLatticeElement & getLatticeValueFor(Value *V) const
bool removeNonFeasibleEdges(BasicBlock *BB, DomTreeUpdater &DTU, BasicBlock *&NewUnreachableBB) const
Definition: SCCPSolver.cpp:254
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:54
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:59
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:152
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:450
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:312
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:1731
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:308
An efficient, type-erasing, non-owning reference to a callable.
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:1819
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:748
bool canTrackGlobalVariableInterprocedurally(GlobalVariable *GV)
Determine if the value maintained in the given global variable can be tracked interprocedurally.
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:2243
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.
Helper struct for bundling up the analysis results per function for IPSCCP.
Definition: SCCPSolver.h:43