//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "globalsmodref-aa"
#include "llvm/Analysis/Passes.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/InstIterator.h"
#include <set>
using namespace llvm;
+#define DEBUG_TYPE "globalsmodref-aa"
+
STATISTIC(NumNonAddrTakenGlobalVars,
"Number of global vars without address taken");
STATISTIC(NumNonAddrTakenFunctions,"Number of functions without address taken");
initializeGlobalsModRefPass(*PassRegistry::getPassRegistry());
}
- bool runOnModule(Module &M) {
- InitializeAliasAnalysis(this); // set up super class
- AnalyzeGlobals(M); // find non-addr taken globals
- AnalyzeCallGraph(getAnalysis<CallGraph>(), M); // Propagate on CG
+ bool runOnModule(Module &M) override {
+ InitializeAliasAnalysis(this);
+
+ // Find non-addr taken globals.
+ AnalyzeGlobals(M);
+
+ // Propagate on CG.
+ AnalyzeCallGraph(getAnalysis<CallGraphWrapperPass>().getCallGraph(), M);
return false;
}
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AliasAnalysis::getAnalysisUsage(AU);
- AU.addRequired<CallGraph>();
+ AU.addRequired<CallGraphWrapperPass>();
AU.setPreservesAll(); // Does not transform code
}
//------------------------------------------------
// Implement the AliasAnalysis API
//
- AliasResult alias(const Location &LocA, const Location &LocB);
+ AliasResult alias(const Location &LocA, const Location &LocB) override;
ModRefResult getModRefInfo(ImmutableCallSite CS,
- const Location &Loc);
+ const Location &Loc) override;
ModRefResult getModRefInfo(ImmutableCallSite CS1,
- ImmutableCallSite CS2) {
+ ImmutableCallSite CS2) override {
return AliasAnalysis::getModRefInfo(CS1, CS2);
}
/// getModRefBehavior - Return the behavior of the specified function if
/// called from the specified call site. The call site may be null in which
/// case the most generic behavior of this function should be returned.
- ModRefBehavior getModRefBehavior(const Function *F) {
+ ModRefBehavior getModRefBehavior(const Function *F) override {
ModRefBehavior Min = UnknownModRefBehavior;
if (FunctionRecord *FR = getFunctionInfo(F)) {
/// getModRefBehavior - Return the behavior of the specified function if
/// called from the specified call site. The call site may be null in which
/// case the most generic behavior of this function should be returned.
- ModRefBehavior getModRefBehavior(ImmutableCallSite CS) {
+ ModRefBehavior getModRefBehavior(ImmutableCallSite CS) override {
ModRefBehavior Min = UnknownModRefBehavior;
if (const Function* F = CS.getCalledFunction())
return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
}
- virtual void deleteValue(Value *V);
- virtual void copyValue(Value *From, Value *To);
- virtual void addEscapingUse(Use &U);
+ void deleteValue(Value *V) override;
+ void copyValue(Value *From, Value *To) override;
+ void addEscapingUse(Use &U) override;
/// getAdjustedAnalysisPointer - This method is used when a pass implements
/// an analysis interface through multiple inheritance. If needed, it
/// should override this to adjust the this pointer as needed for the
/// specified pass info.
- virtual void *getAdjustedAnalysisPointer(AnalysisID PI) {
+ void *getAdjustedAnalysisPointer(AnalysisID PI) override {
if (PI == &AliasAnalysis::ID)
return (AliasAnalysis*)this;
return this;
FunctionInfo.find(F);
if (I != FunctionInfo.end())
return &I->second;
- return 0;
+ return nullptr;
}
void AnalyzeGlobals(Module &M);
void AnalyzeCallGraph(CallGraph &CG, Module &M);
bool AnalyzeUsesOfPointer(Value *V, std::vector<Function*> &Readers,
std::vector<Function*> &Writers,
- GlobalValue *OkayStoreDest = 0);
+ GlobalValue *OkayStoreDest = nullptr);
bool AnalyzeIndirectGlobalMemory(GlobalValue *GV);
};
}
INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis,
"globalsmodref-aa", "Simple mod/ref analysis for globals",
false, true, false)
-INITIALIZE_AG_DEPENDENCY(CallGraph)
+INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
INITIALIZE_AG_PASS_END(GlobalsModRef, AliasAnalysis,
"globalsmodref-aa", "Simple mod/ref analysis for globals",
false, true, false)
GlobalValue *OkayStoreDest) {
if (!V->getType()->isPointerTy()) return true;
- for (Value::use_iterator UI = V->use_begin(), E=V->use_end(); UI != E; ++UI) {
- User *U = *UI;
- if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
+ for (Use &U : V->uses()) {
+ User *I = U.getUser();
+ if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
Readers.push_back(LI->getParent()->getParent());
- } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
+ } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
if (V == SI->getOperand(1)) {
Writers.push_back(SI->getParent()->getParent());
} else if (SI->getOperand(1) != OkayStoreDest) {
return true; // Storing the pointer
}
- } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
- if (AnalyzeUsesOfPointer(GEP, Readers, Writers)) return true;
- } else if (BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
- if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest))
+ } else if (Operator::getOpcode(I) == Instruction::GetElementPtr) {
+ if (AnalyzeUsesOfPointer(I, Readers, Writers))
return true;
- } else if (isFreeCall(U, TLI)) {
- Writers.push_back(cast<Instruction>(U)->getParent()->getParent());
- } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
- // Make sure that this is just the function being called, not that it is
- // passing into the function.
- for (unsigned i = 0, e = CI->getNumArgOperands(); i != e; ++i)
- if (CI->getArgOperand(i) == V) return true;
- } else if (InvokeInst *II = dyn_cast<InvokeInst>(U)) {
+ } else if (Operator::getOpcode(I) == Instruction::BitCast) {
+ if (AnalyzeUsesOfPointer(I, Readers, Writers, OkayStoreDest))
+ return true;
+ } else if (CallSite CS = I) {
// Make sure that this is just the function being called, not that it is
// passing into the function.
- for (unsigned i = 0, e = II->getNumArgOperands(); i != e; ++i)
- if (II->getArgOperand(i) == V) return true;
- } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
- if (CE->getOpcode() == Instruction::GetElementPtr ||
- CE->getOpcode() == Instruction::BitCast) {
- if (AnalyzeUsesOfPointer(CE, Readers, Writers))
- return true;
- } else {
- return true;
+ if (!CS.isCallee(&U)) {
+ // Detect calls to free.
+ if (isFreeCall(I, TLI))
+ Writers.push_back(CS->getParent()->getParent());
+ else
+ return true; // Argument of an unknown call.
}
- } else if (ICmpInst *ICI = dyn_cast<ICmpInst>(U)) {
+ } else if (ICmpInst *ICI = dyn_cast<ICmpInst>(I)) {
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
return true; // Allow comparison against null.
} else {
// Walk the user list of the global. If we find anything other than a direct
// load or store, bail out.
- for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I){
- User *U = *I;
+ for (User *U : GV->users()) {
if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
// The pointer loaded from the global can only be used in simple ways:
// we allow addressing of it and loading storing to it. We do *not* allow
void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
// We do a bottom-up SCC traversal of the call graph. In other words, we
// visit all callees before callers (leaf-first).
- for (scc_iterator<CallGraph*> I = scc_begin(&CG), E = scc_end(&CG); I != E;
- ++I) {
- std::vector<CallGraphNode *> &SCC = *I;
+ for (scc_iterator<CallGraph*> I = scc_begin(&CG); !I.isAtEnd(); ++I) {
+ const std::vector<CallGraphNode *> &SCC = *I;
assert(!SCC.empty() && "SCC with no functions?");
if (!SCC[0]->getFunction()) {
if (GV1 || GV2) {
// If the global's address is taken, pretend we don't know it's a pointer to
// the global.
- if (GV1 && !NonAddressTakenGlobals.count(GV1)) GV1 = 0;
- if (GV2 && !NonAddressTakenGlobals.count(GV2)) GV2 = 0;
+ if (GV1 && !NonAddressTakenGlobals.count(GV1)) GV1 = nullptr;
+ if (GV2 && !NonAddressTakenGlobals.count(GV2)) GV2 = nullptr;
// If the two pointers are derived from two different non-addr-taken
// globals, or if one is and the other isn't, we know these can't alias.
// These pointers may be based on the memory owned by an indirect global. If
// so, we may be able to handle this. First check to see if the base pointer
// is a direct load from an indirect global.
- GV1 = GV2 = 0;
+ GV1 = GV2 = nullptr;
if (const LoadInst *LI = dyn_cast<LoadInst>(UV1))
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(LI->getOperand(0)))
if (IndirectGlobals.count(GV))