aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis')
-rw-r--r--lib/Analysis/IPA/Andersens.cpp4
-rw-r--r--lib/Analysis/IPA/GlobalsModRef.cpp7
-rw-r--r--lib/Analysis/MallocHelper.cpp26
-rw-r--r--lib/Analysis/MemoryDependenceAnalysis.cpp8
4 files changed, 40 insertions, 5 deletions
diff --git a/lib/Analysis/IPA/Andersens.cpp b/lib/Analysis/IPA/Andersens.cpp
index b5129a7d3b..e37a9dbb7a 100644
--- a/lib/Analysis/IPA/Andersens.cpp
+++ b/lib/Analysis/IPA/Andersens.cpp
@@ -1017,6 +1017,8 @@ bool Andersens::AnalyzeUsesOfFunction(Value *V) {
}
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(*UI)) {
if (AnalyzeUsesOfFunction(GEP)) return true;
+ } else if (isa<FreeInst>(*UI) || isFreeCall(*UI)) {
+ return false;
} else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
// Make sure that this is just the function being called, not that it is
// passing into the function.
@@ -1038,8 +1040,6 @@ bool Andersens::AnalyzeUsesOfFunction(Value *V) {
} else if (ICmpInst *ICI = dyn_cast<ICmpInst>(*UI)) {
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
return true; // Allow comparison against null.
- } else if (isa<FreeInst>(*UI)) {
- return false;
} else {
return true;
}
diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp
index 7949288340..d83ea48080 100644
--- a/lib/Analysis/IPA/GlobalsModRef.cpp
+++ b/lib/Analysis/IPA/GlobalsModRef.cpp
@@ -240,6 +240,8 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
} else if (BitCastInst *BCI = dyn_cast<BitCastInst>(*UI)) {
if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest))
return true;
+ } else if (isa<FreeInst>(*UI) || isFreeCall(*UI)) {
+ Writers.push_back(cast<Instruction>(*UI)->getParent()->getParent());
} else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
// Make sure that this is just the function being called, not that it is
// passing into the function.
@@ -261,8 +263,6 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
} else if (ICmpInst *ICI = dyn_cast<ICmpInst>(*UI)) {
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
return true; // Allow comparison against null.
- } else if (FreeInst *F = dyn_cast<FreeInst>(*UI)) {
- Writers.push_back(F->getParent()->getParent());
} else {
return true;
}
@@ -439,7 +439,8 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
if (cast<StoreInst>(*II).isVolatile())
// Treat volatile stores as reading memory somewhere.
FunctionEffect |= Ref;
- } else if (isMalloc(&cast<Instruction>(*II)) || isa<FreeInst>(*II)) {
+ } else if (isMalloc(&cast<Instruction>(*II)) || isa<FreeInst>(*II) ||
+ isFreeCall(&cast<Instruction>(*II))) {
FunctionEffect |= ModRef;
}
diff --git a/lib/Analysis/MallocHelper.cpp b/lib/Analysis/MallocHelper.cpp
index e7bb41eeec..511de9d6a5 100644
--- a/lib/Analysis/MallocHelper.cpp
+++ b/lib/Analysis/MallocHelper.cpp
@@ -263,3 +263,29 @@ Value* llvm::getMallocArraySize(CallInst* CI, LLVMContext &Context,
assert(BO && "getMallocArraySize not constant but not multiplication either");
return BO->getOperand(0);
}
+
+/// isFreeCall - Returns true if the the value is a call to the builtin free()
+bool llvm::isFreeCall(const Value* I) {
+ const CallInst *CI = dyn_cast<CallInst>(I);
+ if (!CI)
+ return false;
+
+ const Module* M = CI->getParent()->getParent()->getParent();
+ Function *FreeFunc = M->getFunction("free");
+
+ if (CI->getOperand(0) != FreeFunc)
+ return false;
+
+ // Check free prototype.
+ // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
+ // attribute will exist.
+ const FunctionType *FTy = FreeFunc->getFunctionType();
+ if (FTy->getReturnType() != Type::getVoidTy(M->getContext()))
+ return false;
+ if (FTy->getNumParams() != 1)
+ return false;
+ if (FTy->param_begin()->get() != Type::getInt8PtrTy(M->getContext()))
+ return false;
+
+ return true;
+}
diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp
index c3aa5bc930..ce7674003f 100644
--- a/lib/Analysis/MemoryDependenceAnalysis.cpp
+++ b/lib/Analysis/MemoryDependenceAnalysis.cpp
@@ -118,6 +118,10 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall,
// FreeInsts erase the entire structure
PointerSize = ~0ULL;
+ } else if (isFreeCall(Inst)) {
+ Pointer = Inst->getOperand(0);
+ // calls to free() erase the entire structure
+ PointerSize = ~0ULL;
} else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
// Debug intrinsics don't cause dependences.
if (isa<DbgInfoIntrinsic>(Inst)) continue;
@@ -314,6 +318,10 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) {
MemPtr = LI->getPointerOperand();
MemSize = AA->getTypeStoreSize(LI->getType());
}
+ } else if (isFreeCall(QueryInst)) {
+ MemPtr = QueryInst->getOperand(0);
+ // calls to free() erase the entire structure, not just a field.
+ MemSize = ~0UL;
} else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst)) {
CallSite QueryCS = CallSite::get(QueryInst);
bool isReadOnly = AA->onlyReadsMemory(QueryCS);