17 #define DEBUG_TYPE "globalsmodref-aa"
37 "Number of global vars without address taken");
38 STATISTIC(NumNonAddrTakenFunctions,
"Number of functions without address taken");
39 STATISTIC(NumNoMemFunctions,
"Number of functions that do not access memory");
40 STATISTIC(NumReadMemFunctions,
"Number of functions that only read memory");
41 STATISTIC(NumIndirectGlobalVars,
"Number of indirect global objects");
48 struct FunctionRecord {
52 std::map<const GlobalValue*, unsigned> GlobalInfo;
55 bool MayReadAnyGlobal;
57 unsigned getInfoForGlobal(
const GlobalValue *GV)
const {
59 std::map<const GlobalValue*, unsigned>::const_iterator
I =
61 if (I != GlobalInfo.end())
68 unsigned FunctionEffect;
70 FunctionRecord() : MayReadAnyGlobal (
false), FunctionEffect(0) {}
77 std::set<const GlobalValue*> NonAddressTakenGlobals;
81 std::set<const GlobalValue*> IndirectGlobals;
85 std::map<const Value*, const GlobalValue*> AllocsForIndirectGlobals;
89 std::map<const Function*, FunctionRecord> FunctionInfo;
97 bool runOnModule(
Module &M) {
98 InitializeAliasAnalysis(
this);
100 AnalyzeCallGraph(getAnalysis<CallGraph>(), M);
113 AliasResult alias(
const Location &LocA,
const Location &LocB);
115 const Location &Loc);
127 if (FunctionRecord *FR = getFunctionInfo(F)) {
128 if (FR->FunctionEffect == 0)
129 Min = DoesNotAccessMemory;
130 else if ((FR->FunctionEffect & Mod) == 0)
131 Min = OnlyReadsMemory;
144 if (FunctionRecord *FR = getFunctionInfo(F)) {
145 if (FR->FunctionEffect == 0)
146 Min = DoesNotAccessMemory;
147 else if ((FR->FunctionEffect & Mod) == 0)
148 Min = OnlyReadsMemory;
154 virtual void deleteValue(
Value *V);
155 virtual void copyValue(
Value *From,
Value *To);
156 virtual void addEscapingUse(
Use &U);
162 virtual void *getAdjustedAnalysisPointer(
AnalysisID PI) {
171 FunctionRecord *getFunctionInfo(
const Function *F) {
172 std::map<const Function*, FunctionRecord>::iterator I =
173 FunctionInfo.find(F);
174 if (I != FunctionInfo.end())
179 void AnalyzeGlobals(
Module &M);
181 bool AnalyzeUsesOfPointer(
Value *V, std::vector<Function*> &Readers,
182 std::vector<Function*> &Writers,
190 "globalsmodref-aa",
"Simple mod/ref analysis for globals",
194 "globalsmodref-
aa", "Simple mod/ref analysis
for globals",
203 void GlobalsModRef::AnalyzeGlobals(
Module &M) {
204 std::vector<Function*> Readers, Writers;
206 if (I->hasLocalLinkage()) {
207 if (!AnalyzeUsesOfPointer(I, Readers, Writers)) {
209 NonAddressTakenGlobals.insert(I);
210 ++NumNonAddrTakenFunctions;
212 Readers.clear(); Writers.clear();
217 if (I->hasLocalLinkage()) {
218 if (!AnalyzeUsesOfPointer(I, Readers, Writers)) {
220 NonAddressTakenGlobals.insert(I);
222 for (
unsigned i = 0, e = Readers.size(); i != e; ++i)
223 FunctionInfo[Readers[i]].GlobalInfo[I] |= Ref;
225 if (!I->isConstant())
226 for (
unsigned i = 0, e = Writers.size(); i != e; ++i)
227 FunctionInfo[Writers[i]].GlobalInfo[I] |= Mod;
228 ++NumNonAddrTakenGlobalVars;
231 if (I->getType()->getElementType()->isPointerTy() &&
232 AnalyzeIndirectGlobalMemory(I))
233 ++NumIndirectGlobalVars;
235 Readers.clear(); Writers.clear();
245 bool GlobalsModRef::AnalyzeUsesOfPointer(
Value *V,
246 std::vector<Function*> &Readers,
247 std::vector<Function*> &Writers,
254 Readers.push_back(
LI->getParent()->getParent());
255 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
256 if (V == SI->getOperand(1)) {
257 Writers.push_back(SI->getParent()->getParent());
258 }
else if (SI->getOperand(1) != OkayStoreDest) {
262 if (AnalyzeUsesOfPointer(GEP, Readers, Writers))
return true;
263 }
else if (
BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
264 if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest))
268 }
else if (
CallInst *CI = dyn_cast<CallInst>(U)) {
271 for (
unsigned i = 0, e = CI->getNumArgOperands(); i != e; ++i)
272 if (CI->getArgOperand(i) == V)
return true;
273 }
else if (
InvokeInst *II = dyn_cast<InvokeInst>(U)) {
276 for (
unsigned i = 0, e = II->getNumArgOperands(); i != e; ++i)
277 if (II->getArgOperand(i) == V)
return true;
278 }
else if (
ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
279 if (CE->getOpcode() == Instruction::GetElementPtr ||
280 CE->getOpcode() == Instruction::BitCast) {
281 if (AnalyzeUsesOfPointer(CE, Readers, Writers))
286 }
else if (
ICmpInst *ICI = dyn_cast<ICmpInst>(U)) {
287 if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
304 bool GlobalsModRef::AnalyzeIndirectGlobalMemory(
GlobalValue *GV) {
307 std::vector<Value*> AllocRelatedValues;
317 std::vector<Function*> ReadersWriters;
318 if (AnalyzeUsesOfPointer(
LI, ReadersWriters, ReadersWriters))
321 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
323 if (SI->getOperand(0) == GV)
return false;
326 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);
368 std::vector<CallGraphNode *> &SCC = *
I;
369 assert(!SCC.empty() &&
"SCC with no functions?");
371 if (!SCC[0]->getFunction()) {
374 for (
unsigned i = 0, e = SCC.size(); i != e; ++i)
375 FunctionInfo.erase(SCC[i]->getFunction());
379 FunctionRecord &FR = FunctionInfo[SCC[0]->getFunction()];
381 bool KnowNothing =
false;
382 unsigned FunctionEffect = 0;
386 for (
unsigned i = 0, e = SCC.size(); i != e && !KnowNothing; ++i) {
387 Function *F = SCC[i]->getFunction();
398 FunctionEffect |= Ref;
402 FR.MayReadAnyGlobal =
true;
404 FunctionEffect |= ModRef;
413 CI != E && !KnowNothing; ++CI)
414 if (
Function *Callee = CI->second->getFunction()) {
415 if (FunctionRecord *CalleeFR = getFunctionInfo(Callee)) {
417 FunctionEffect |= CalleeFR->FunctionEffect;
420 for (std::map<const GlobalValue*, unsigned>::iterator GI =
421 CalleeFR->GlobalInfo.begin(), E = CalleeFR->GlobalInfo.end();
423 FR.GlobalInfo[GI->first] |= GI->second;
424 FR.MayReadAnyGlobal |= CalleeFR->MayReadAnyGlobal;
429 if (std::find(SCC.begin(), SCC.end(), CalleeNode) == SCC.end())
440 for (
unsigned i = 0, e = SCC.size(); i != e; ++i)
441 FunctionInfo.erase(SCC[i]->getFunction());
446 for (
unsigned i = 0, e = SCC.size(); i != e && FunctionEffect != ModRef;++i)
448 E =
inst_end(SCC[i]->getFunction());
449 II != E && FunctionEffect != ModRef; ++II)
450 if (
LoadInst *
LI = dyn_cast<LoadInst>(&*II)) {
451 FunctionEffect |= Ref;
452 if (
LI->isVolatile())
455 FunctionEffect |= Mod;
456 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(&*II)) {
457 FunctionEffect |= Mod;
458 if (SI->isVolatile())
460 FunctionEffect |= Ref;
462 FunctionEffect |= ModRef;
463 }
else if (
IntrinsicInst *Intrinsic = dyn_cast<IntrinsicInst>(&*II)) {
465 Function *Callee = Intrinsic->getCalledFunction();
467 FunctionEffect |= (Behaviour & ModRef);
470 if ((FunctionEffect & Mod) == 0)
471 ++NumReadMemFunctions;
472 if (FunctionEffect == 0)
474 FR.FunctionEffect = FunctionEffect;
478 for (
unsigned i = 1, e = SCC.size(); i != e; ++i)
479 FunctionInfo[SCC[i]->getFunction()] = FR;
489 GlobalsModRef::alias(
const Location &LocA,
490 const Location &LocB) {
502 if (GV1 && !NonAddressTakenGlobals.count(GV1)) GV1 = 0;
503 if (GV2 && !NonAddressTakenGlobals.count(GV2)) GV2 = 0;
507 if ((GV1 || GV2) && GV1 != GV2)
518 if (
const LoadInst *
LI = dyn_cast<LoadInst>(UV1))
520 if (IndirectGlobals.count(GV))
522 if (
const LoadInst *
LI = dyn_cast<LoadInst>(UV2))
524 if (IndirectGlobals.count(GV))
529 if (AllocsForIndirectGlobals.count(UV1))
530 GV1 = AllocsForIndirectGlobals[UV1];
531 if (AllocsForIndirectGlobals.count(UV2))
532 GV2 = AllocsForIndirectGlobals[UV2];
538 if ((GV1 || GV2) && GV1 != GV2)
546 const Location &Loc) {
547 unsigned Known = ModRef;
555 if (NonAddressTakenGlobals.count(GV))
556 if (
const FunctionRecord *FR = getFunctionInfo(F))
557 Known = FR->getInfoForGlobal(GV);
559 if (Known == NoModRef)
568 void GlobalsModRef::deleteValue(
Value *V) {
570 if (NonAddressTakenGlobals.erase(GV)) {
573 if (IndirectGlobals.erase(GV)) {
575 for (std::map<const Value*, const GlobalValue*>::iterator
576 I = AllocsForIndirectGlobals.begin(),
577 E = AllocsForIndirectGlobals.end(); I != E; ) {
578 if (I->second == GV) {
579 AllocsForIndirectGlobals.erase(I++);
590 AllocsForIndirectGlobals.erase(V);
595 void GlobalsModRef::copyValue(
Value *From,
Value *To) {
599 void GlobalsModRef::addEscapingUse(
Use &U) {
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...
const_iterator end(StringRef path)
Get end iterator over path.
STATISTIC(NumNonAddrTakenGlobalVars,"Number of global vars without address taken")
static PassRegistry * getPassRegistry()
ModRefResult getModRefInfo(const Instruction *I, const Location &Loc)
bool onlyReadsMemory() const
Determine if the function does not access or only reads memory.
The main container class for the LLVM Intermediate Representation.
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
const_iterator begin(StringRef path)
Get begin iterator over path.
LoopInfoBase< BlockT, LoopT > * LI
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
Value * GetUnderlyingObject(Value *V, const DataLayout *TD=0, unsigned MaxLookup=6)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
inst_iterator inst_begin(Function *F)
INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis,"globalsmodref-aa","Simple mod/ref analysis for globals", false, true, false) INITIALIZE_AG_PASS_END(GlobalsModRef
ID
LLVM Calling Convention Representation.
virtual void copyValue(Value *From, Value *To)
scc_iterator< T > scc_begin(const T &G)
global_iterator global_begin()
Pass * createGlobalsModRefPass()
globalsmodref Simple mod ref analysis for globals
This class represents a no-op cast from one type to another.
virtual void addEscapingUse(Use &U)
void initializeGlobalsModRefPass(PassRegistry &)
bool doesNotAccessMemory() const
Determine if the function does not access memory.
scc_iterator< T > scc_end(const T &G)
virtual AliasResult alias(const Location &LocA, const Location &LocB)
Represent an integer comparison operator.
for(unsigned i=0, e=MI->getNumOperands();i!=e;++i)
virtual void deleteValue(Value *V)
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS)
getModRefBehavior - Return the behavior when calling the given call site.
global_iterator global_end()
globalsmodref Simple mod ref analysis for true
globalsmodref Simple mod ref analysis for false
bool isDeclaration() const
ImmutableCallSite - establish a view to a call site for examination.
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
LLVM Value Representation.
static const Function * getParent(const Value *V)
virtual void getAnalysisUsage(AnalysisUsage &AU) const
#define INITIALIZE_AG_PASS_END(passName, agName, arg, n, cfg, analysis, def)
inst_iterator inst_end(Function *F)
FunTy * getCalledFunction() const