LLVM 20.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 all_of(Solver.getStructLatticeValueFor(U),
80 [](const ValueLatticeElement &LV) {
81 return !SCCPSolver::isOverdefined(LV);
82 });
83 }
84
85 // We don't consider assume-like intrinsics to be actual address
86 // captures.
87 if (auto *II = dyn_cast<IntrinsicInst>(U)) {
88 if (II->isAssumeLikeIntrinsic())
89 return true;
90 }
91
93 }) &&
94 "We can only zap functions where all live users have a concrete value");
95
96 for (BasicBlock &BB : F) {
97 if (CallInst *CI = BB.getTerminatingMustTailCall()) {
98 LLVM_DEBUG(dbgs() << "Can't zap return of the block due to present "
99 << "musttail call : " << *CI << "\n");
100 (void)CI;
101 return;
102 }
103
104 if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
105 if (!isa<UndefValue>(RI->getOperand(0)))
106 ReturnsToZap.push_back(RI);
107 }
108}
109
110static bool runIPSCCP(
112 std::function<const TargetLibraryInfo &(Function &)> GetTLI,
113 std::function<TargetTransformInfo &(Function &)> GetTTI,
114 std::function<AssumptionCache &(Function &)> GetAC,
115 std::function<DominatorTree &(Function &)> GetDT,
116 std::function<BlockFrequencyInfo &(Function &)> GetBFI,
117 bool IsFuncSpecEnabled) {
118 SCCPSolver Solver(DL, GetTLI, M.getContext());
119 FunctionSpecializer Specializer(Solver, M, FAM, GetBFI, GetTLI, GetTTI,
120 GetAC);
121
122 // Loop over all functions, marking arguments to those with their addresses
123 // taken or that are external as overdefined.
124 for (Function &F : M) {
125 if (F.isDeclaration())
126 continue;
127
128 DominatorTree &DT = GetDT(F);
129 AssumptionCache &AC = GetAC(F);
130 Solver.addPredicateInfo(F, DT, AC);
131
132 // Determine if we can track the function's return values. If so, add the
133 // function to the solver's set of return-tracked functions.
135 Solver.addTrackedFunction(&F);
136
137 // Determine if we can track the function's arguments. If so, add the
138 // function to the solver's set of argument-tracked functions.
141 continue;
142 }
143
144 // Assume the function is called.
145 Solver.markBlockExecutable(&F.front());
146
147 for (Argument &AI : F.args())
148 Solver.trackValueOfArgument(&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->getFirstNonPHIOrDbg(),
239 /*PreserveLCSSA=*/false, &DTU);
240 }
241 if (!Solver.isBlockExecutable(&F.front()))
242 NumInstRemoved += changeToUnreachable(F.front().getFirstNonPHIOrDbg(),
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 // attribute to the return value.
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 // Do not touch existing attribute for now.
293 // TODO: We should be able to take the intersection of the existing
294 // attribute and the inferred range.
295 if (F->hasRetAttribute(Attribute::Range))
296 continue;
297 auto &CR = ReturnValue.getConstantRange();
298 F->addRangeRetAttr(CR);
299 continue;
300 }
301 if (F->getReturnType()->isVoidTy())
302 continue;
303 if (SCCPSolver::isConstant(ReturnValue) || ReturnValue.isUnknownOrUndef())
304 findReturnsToZap(*F, ReturnsToZap, Solver);
305 }
306
307 for (auto *F : Solver.getMRVFunctionsTracked()) {
308 assert(F->getReturnType()->isStructTy() &&
309 "The return type should be a struct");
310 StructType *STy = cast<StructType>(F->getReturnType());
311 if (Solver.isStructLatticeConstant(F, STy))
312 findReturnsToZap(*F, ReturnsToZap, Solver);
313 }
314
315 // Zap all returns which we've identified as zap to change.
316 SmallSetVector<Function *, 8> FuncZappedReturn;
317 for (ReturnInst *RI : ReturnsToZap) {
318 Function *F = RI->getParent()->getParent();
319 RI->setOperand(0, PoisonValue::get(F->getReturnType()));
320 // Record all functions that are zapped.
321 FuncZappedReturn.insert(F);
322 }
323
324 // Remove the returned attribute for zapped functions and the
325 // corresponding call sites.
326 // Also remove any attributes that convert an undef return value into
327 // immediate undefined behavior
328 AttributeMask UBImplyingAttributes =
330 for (Function *F : FuncZappedReturn) {
331 for (Argument &A : F->args())
332 F->removeParamAttr(A.getArgNo(), Attribute::Returned);
333 F->removeRetAttrs(UBImplyingAttributes);
334 for (Use &U : F->uses()) {
335 CallBase *CB = dyn_cast<CallBase>(U.getUser());
336 if (!CB) {
337 assert(isa<BlockAddress>(U.getUser()) ||
338 (isa<Constant>(U.getUser()) &&
339 all_of(U.getUser()->users(), [](const User *UserUser) {
340 return cast<IntrinsicInst>(UserUser)->isAssumeLikeIntrinsic();
341 })));
342 continue;
343 }
344
345 for (Use &Arg : CB->args())
346 CB->removeParamAttr(CB->getArgOperandNo(&Arg), Attribute::Returned);
347 CB->removeRetAttrs(UBImplyingAttributes);
348 }
349 }
350
351 // If we inferred constant or undef values for globals variables, we can
352 // delete the global and any stores that remain to it.
353 for (const auto &I : make_early_inc_range(Solver.getTrackedGlobals())) {
354 GlobalVariable *GV = I.first;
355 if (SCCPSolver::isOverdefined(I.second))
356 continue;
357 LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName()
358 << "' is constant!\n");
359 while (!GV->use_empty()) {
360 StoreInst *SI = cast<StoreInst>(GV->user_back());
361 SI->eraseFromParent();
362 }
363
364 // Try to create a debug constant expression for the global variable
365 // initializer value.
367 GV->getDebugInfo(GVEs);
368 if (GVEs.size() == 1) {
369 DIBuilder DIB(M);
371 DIB, *GV->getInitializer(), *GV->getValueType()))
372 GVEs[0]->replaceOperandWith(1, InitExpr);
373 }
374
375 MadeChanges = true;
376 M.eraseGlobalVariable(GV);
377 ++NumGlobalConst;
378 }
379
380 return MadeChanges;
381}
382
384 const DataLayout &DL = M.getDataLayout();
385 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
386 auto GetTLI = [&FAM](Function &F) -> const TargetLibraryInfo & {
388 };
389 auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
391 };
392 auto GetAC = [&FAM](Function &F) -> AssumptionCache & {
394 };
395 auto GetDT = [&FAM](Function &F) -> DominatorTree & {
397 };
398 auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
400 };
401
402
403 if (!runIPSCCP(M, DL, &FAM, GetTLI, GetTTI, GetAC, GetDT, GetBFI,
405 return PreservedAnalyses::all();
406
411 return PA;
412}
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: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:110
#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)
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:166
This pass exposes codegen information to IR-level passes.
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
Definition: PassManager.h:424
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:405
This class represents an incoming formal argument to a Function.
Definition: Argument.h:31
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:280
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
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:1236
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Removes the attribute from the given argument.
Definition: InstrTypes.h:1641
void removeRetAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the return value.
Definition: InstrTypes.h:1636
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
Definition: InstrTypes.h:1401
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:1441
This class represents a function call, abstracting a target machine's calling convention.
bool isSingleElement() const
Return true if this set contains exactly one member.
DWARF expression.
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:63
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:162
bool run()
Attempt to specialize functions in the module to enable constant propagation across function boundari...
Type * getValueType() const
Definition: GlobalValue.h:296
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
void getDebugInfo(SmallVectorImpl< DIGlobalVariableExpression * > &GVs) const
Fill the vector with all debug info attachements.
Definition: Metadata.cpp:1854
bool isFuncSpecEnabled() const
Definition: SCCP.h:58
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition: SCCP.cpp:383
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Definition: PassManager.h:563
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
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1852
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:111
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
void preserve()
Mark an analysis as preserved.
Definition: Analysis.h:131
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:68
bool isStructLatticeConstant(Function *F, StructType *STy)
void addPredicateInfo(Function &F, DominatorTree &DT, AssumptionCache &AC)
void trackValueOfArgument(Argument *V)
trackValueOfArgument - Mark the specified argument overdefined unless it have range attribute.
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:237
const ValueLatticeElement & getLatticeValueFor(Value *V) const
bool removeNonFeasibleEdges(BasicBlock *BB, DomTreeUpdater &DTU, BasicBlock *&NewUnreachableBB) const
Definition: SCCPSolver.cpp:261
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:47
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:52
bool isArgumentTrackedFunction(Function *F)
Returns true if the given function is in the solver's set of argument-tracked functions.
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:502
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:370
size_t size() const
Definition: SmallVector.h:91
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
An instruction for storing to memory.
Definition: Instructions.h:290
Class to represent struct types.
Definition: DerivedTypes.h:216
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:43
This class represents lattice values for constants.
Definition: ValueLattice.h:26
bool isConstantRangeIncludingUndef() const
Definition: ValueLattice.h:239
const ConstantRange & getConstantRange(bool UndefAllowed=true) const
Returns the constant range for this value.
Definition: ValueLattice.h:266
bool isConstantRange(bool UndefAllowed=true) const
Returns true if this value is a constant range.
Definition: ValueLattice.h:246
bool isUnknownOrUndef() const
Definition: ValueLattice.h:236
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:443
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:1722
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:656
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
DIExpression * getExpressionForConstant(DIBuilder &DIB, const Constant &C, Type &Ty)
Given a constant, create a debug information expression.
Definition: Local.cpp:3688
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:2871
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.