35 #define DEBUG_TYPE "globalsmodref-aa"
38 "Number of global vars without address taken");
39 STATISTIC(NumNonAddrTakenFunctions,
"Number of functions without address taken");
40 STATISTIC(NumNoMemFunctions,
"Number of functions that do not access memory");
41 STATISTIC(NumReadMemFunctions,
"Number of functions that only read memory");
42 STATISTIC(NumIndirectGlobalVars,
"Number of indirect global objects");
49 struct FunctionRecord {
53 std::map<const GlobalValue *, unsigned> GlobalInfo;
56 bool MayReadAnyGlobal;
58 unsigned getInfoForGlobal(
const GlobalValue *GV)
const {
60 std::map<const GlobalValue *, unsigned>::const_iterator
I =
62 if (I != GlobalInfo.end())
69 unsigned FunctionEffect;
71 FunctionRecord() : MayReadAnyGlobal(
false), FunctionEffect(0) {}
78 std::set<const GlobalValue *> NonAddressTakenGlobals;
82 std::set<const GlobalValue *> IndirectGlobals;
86 std::map<const Value *, const GlobalValue *> AllocsForIndirectGlobals;
90 std::map<const Function *, FunctionRecord> FunctionInfo;
98 bool runOnModule(
Module &M)
override {
105 AnalyzeCallGraph(getAnalysis<CallGraphWrapperPass>().getCallGraph(), M);
133 if (FunctionRecord *FR = getFunctionInfo(F)) {
134 if (FR->FunctionEffect == 0)
135 Min = DoesNotAccessMemory;
136 else if ((FR->FunctionEffect & Mod) == 0)
137 Min = OnlyReadsMemory;
150 if (FunctionRecord *FR = getFunctionInfo(F)) {
151 if (FR->FunctionEffect == 0)
152 Min = DoesNotAccessMemory;
153 else if ((FR->FunctionEffect & Mod) == 0)
154 Min = OnlyReadsMemory;
160 void deleteValue(
Value *V)
override;
161 void addEscapingUse(
Use &U)
override;
167 void *getAdjustedAnalysisPointer(
AnalysisID PI)
override {
176 FunctionRecord *getFunctionInfo(
const Function *F) {
177 std::map<const Function *, FunctionRecord>::iterator I =
178 FunctionInfo.find(F);
179 if (I != FunctionInfo.end())
184 void AnalyzeGlobals(
Module &M);
186 bool AnalyzeUsesOfPointer(
Value *V, std::vector<Function *> &Readers,
187 std::vector<Function *> &Writers,
195 "Simple mod/ref analysis for globals",
false,
true,
208 void GlobalsModRef::AnalyzeGlobals(
Module &M) {
209 std::vector<Function *> Readers, Writers;
211 if (I->hasLocalLinkage()) {
212 if (!AnalyzeUsesOfPointer(I, Readers, Writers)) {
214 NonAddressTakenGlobals.insert(I);
215 ++NumNonAddrTakenFunctions;
223 if (I->hasLocalLinkage()) {
224 if (!AnalyzeUsesOfPointer(I, Readers, Writers)) {
226 NonAddressTakenGlobals.insert(I);
228 for (
unsigned i = 0, e = Readers.size(); i != e; ++i)
229 FunctionInfo[Readers[i]].GlobalInfo[I] |= Ref;
231 if (!I->isConstant())
232 for (
unsigned i = 0, e = Writers.size(); i != e; ++i)
233 FunctionInfo[Writers[i]].GlobalInfo[I] |= Mod;
234 ++NumNonAddrTakenGlobalVars;
237 if (I->getType()->getElementType()->isPointerTy() &&
238 AnalyzeIndirectGlobalMemory(I))
239 ++NumIndirectGlobalVars;
252 bool GlobalsModRef::AnalyzeUsesOfPointer(
Value *V,
253 std::vector<Function *> &Readers,
254 std::vector<Function *> &Writers,
260 User *I = U.getUser();
261 if (
LoadInst *LI = dyn_cast<LoadInst>(I)) {
262 Readers.push_back(LI->getParent()->getParent());
263 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(I)) {
264 if (V ==
SI->getOperand(1)) {
265 Writers.push_back(
SI->getParent()->getParent());
266 }
else if (
SI->getOperand(1) != OkayStoreDest) {
270 if (AnalyzeUsesOfPointer(I, Readers, Writers))
273 if (AnalyzeUsesOfPointer(I, Readers, Writers, OkayStoreDest))
285 }
else if (
ICmpInst *ICI = dyn_cast<ICmpInst>(I)) {
286 if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
303 bool GlobalsModRef::AnalyzeIndirectGlobalMemory(
GlobalValue *GV) {
306 std::vector<Value *> AllocRelatedValues;
311 if (
LoadInst *LI = dyn_cast<LoadInst>(U)) {
315 std::vector<Function *> ReadersWriters;
316 if (AnalyzeUsesOfPointer(LI, ReadersWriters, ReadersWriters))
319 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
321 if (
SI->getOperand(0) == GV)
325 if (isa<ConstantPointerNull>(
SI->getOperand(0)))
337 std::vector<Function *> ReadersWriters;
338 if (AnalyzeUsesOfPointer(Ptr, ReadersWriters, ReadersWriters, GV))
342 AllocRelatedValues.push_back(Ptr);
351 while (!AllocRelatedValues.empty()) {
352 AllocsForIndirectGlobals[AllocRelatedValues.back()] = GV;
353 AllocRelatedValues.pop_back();
355 IndirectGlobals.insert(GV);
367 const std::vector<CallGraphNode *> &SCC = *
I;
368 assert(!SCC.empty() &&
"SCC with no functions?");
370 if (!SCC[0]->getFunction()) {
373 for (
unsigned i = 0, e = SCC.size(); i != e; ++i)
374 FunctionInfo.erase(SCC[i]->getFunction());
378 FunctionRecord &FR = FunctionInfo[SCC[0]->getFunction()];
380 bool KnowNothing =
false;
381 unsigned FunctionEffect = 0;
385 for (
unsigned i = 0, e = SCC.size(); i != e && !KnowNothing; ++i) {
386 Function *F = SCC[i]->getFunction();
397 FunctionEffect |= Ref;
401 FR.MayReadAnyGlobal =
true;
403 FunctionEffect |= ModRef;
412 CI != E && !KnowNothing; ++CI)
413 if (
Function *Callee = CI->second->getFunction()) {
414 if (FunctionRecord *CalleeFR = getFunctionInfo(Callee)) {
416 FunctionEffect |= CalleeFR->FunctionEffect;
419 for (
const auto &
G : CalleeFR->GlobalInfo)
420 FR.GlobalInfo[
G.first] |=
G.second;
421 FR.MayReadAnyGlobal |= CalleeFR->MayReadAnyGlobal;
426 if (std::find(SCC.begin(), SCC.end(), CalleeNode) == SCC.end())
437 for (
unsigned i = 0, e = SCC.size(); i != e; ++i)
438 FunctionInfo.erase(SCC[i]->getFunction());
443 for (
auto *Node : SCC) {
444 if (FunctionEffect == ModRef)
447 if (FunctionEffect == ModRef)
456 FunctionEffect |= ModRef;
459 if (Callee->isIntrinsic()) {
462 FunctionEffect |= (Behaviour & ModRef);
470 if (I.mayReadFromMemory())
471 FunctionEffect |= Ref;
472 if (I.mayWriteToMemory())
473 FunctionEffect |= Mod;
477 if ((FunctionEffect & Mod) == 0)
478 ++NumReadMemFunctions;
479 if (FunctionEffect == 0)
481 FR.FunctionEffect = FunctionEffect;
485 for (
unsigned i = 1, e = SCC.size(); i != e; ++i)
486 FunctionInfo[SCC[i]->getFunction()] = FR;
506 if (GV1 && !NonAddressTakenGlobals.count(GV1))
508 if (GV2 && !NonAddressTakenGlobals.count(GV2))
513 if ((GV1 || GV2) && GV1 != GV2)
524 if (
const LoadInst *LI = dyn_cast<LoadInst>(UV1))
525 if (
GlobalVariable *GV = dyn_cast<GlobalVariable>(LI->getOperand(0)))
526 if (IndirectGlobals.count(GV))
528 if (
const LoadInst *LI = dyn_cast<LoadInst>(UV2))
529 if (
const GlobalVariable *GV = dyn_cast<GlobalVariable>(LI->getOperand(0)))
530 if (IndirectGlobals.count(GV))
535 if (AllocsForIndirectGlobals.count(UV1))
536 GV1 = AllocsForIndirectGlobals[UV1];
537 if (AllocsForIndirectGlobals.count(UV2))
538 GV2 = AllocsForIndirectGlobals[UV2];
544 if ((GV1 || GV2) && GV1 != GV2)
552 unsigned Known = ModRef;
561 if (NonAddressTakenGlobals.count(GV))
562 if (
const FunctionRecord *FR = getFunctionInfo(F))
563 Known = FR->getInfoForGlobal(GV);
565 if (Known == NoModRef)
573 void GlobalsModRef::deleteValue(
Value *V) {
575 if (NonAddressTakenGlobals.erase(GV)) {
578 if (IndirectGlobals.erase(GV)) {
580 for (std::map<const Value *, const GlobalValue *>::iterator
581 I = AllocsForIndirectGlobals.begin(),
582 E = AllocsForIndirectGlobals.end();
584 if (I->second == GV) {
585 AllocsForIndirectGlobals.erase(I++);
596 AllocsForIndirectGlobals.erase(V);
601 void GlobalsModRef::addEscapingUse(
Use &U) {
Pass interface - Implemented by all 'passes'.
bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast=false)
Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
A parsed version of the target data layout string in and methods for querying it. ...
const_iterator end(StringRef path)
Get end iterator over path.
iterator_range< use_iterator > uses()
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
STATISTIC(NumFunctions,"Total number of functions")
bool onlyReadsMemory() const
Determine if the function does not access or only reads memory.
A Module instance is used to store all the information related to an LLVM module. ...
BBTy * getParent() const
Get the basic block containing the call site.
const_iterator begin(StringRef path)
Get begin iterator over path.
const Function * getParent() const
Return the enclosing method, or null if none.
The two locations do not alias at all.
FunTy * getCaller() const
getCaller - Return the caller function for this call site
LoadInst - an instruction for reading from memory.
A node in the call graph for a module.
const CallInst * isFreeCall(const Value *I, const TargetLibraryInfo *TLI)
isFreeCall - Returns non-null if the value is a call to the builtin free()
std::vector< CallRecord >::iterator iterator
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
A Use represents the edge between a Value definition and its users.
INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis,"globalsmodref-aa","Simple mod/ref analysis for globals", false, true, false) INITIALIZE_AG_PASS_END(GlobalsModRef
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
global_iterator global_begin()
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
Pass * createGlobalsModRefPass()
globalsmodref Simple mod ref analysis for globals
virtual void addEscapingUse(Use &U)
addEscapingUse - This method should be used whenever an escaping use is added to a pointer value...
StoreInst - an instruction for storing to memory.
void initializeGlobalsModRefPass(PassRegistry &)
bool doesNotAccessMemory() const
Determine if the function does not access memory.
The ModulePass which wraps up a CallGraph and the logic to build it.
FunTy * getCalledFunction() const
getCalledFunction - Return the function being called if this is a direct call, otherwise return null ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
AliasResult
The possible results of an alias query.
Represent the analysis usage information of a pass.
This instruction compares its operands according to the predicate given to the constructor.
for(unsigned i=0, e=MI->getNumOperands();i!=e;++i)
bool isPointerTy() const
isPointerTy - True if this is an instance of PointerType.
virtual void deleteValue(Value *V)
Methods that clients should call when they transform the program to allow alias analyses to update th...
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS)
getModRefBehavior - Return the behavior when calling the given call site.
Value * GetUnderlyingObject(Value *V, const DataLayout &DL, unsigned MaxLookup=6)
GetUnderlyingObject - This method strips off any GEP address adjustments and pointer casts from the s...
global_iterator global_end()
const Value * Ptr
The address of the start of the location.
Representation for a specific memory location.
globalsmodref Simple mod ref analysis for true
virtual AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
Alias Queries...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
ModRefResult getModRefInfo(const Instruction *I)
getModRefInfo - Return information about whether or not an instruction may read or write memory (with...
bool isCallee(Value::const_user_iterator UI) const
isCallee - Determine whether the passed iterator points to the callee operand's Use.
globalsmodref Simple mod ref analysis for false
void setPreservesAll()
Set by analyses that do not transform their input at all.
iterator_range< user_iterator > users()
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
The basic data container for the call graph of a Module of IR.
iterator_range< inst_iterator > inst_range(Function *F)
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
ImmutableCallSite - establish a view to a call site for examination.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast=false)
Tests if a value is a call or invoke to a library function that allocates memory (either malloc...
bool hasLocalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
ModRefResult
Simple mod/ref information...
virtual void getAnalysisUsage(AnalysisUsage &AU) const
getAnalysisUsage - All alias analysis implementations should invoke this directly (using AliasAnalysi...
#define INITIALIZE_AG_PASS_END(passName, agName, arg, n, cfg, analysis, def)
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.