diff options
author | Victor Hernandez <vhernandez@apple.com> | 2009-10-24 04:23:03 +0000 |
---|---|---|
committer | Victor Hernandez <vhernandez@apple.com> | 2009-10-24 04:23:03 +0000 |
commit | 66284e063a1e46500acae48bdc0e4a00652021d1 (patch) | |
tree | 7326efcf20c334046c044082a205dc2eb1f17466 /lib/Analysis | |
parent | 5a850beb2e3032e6ff3474ce5317f5454060328c (diff) |
Auto-upgrade free instructions to calls to the builtin free function.
Update all analysis passes and transforms to treat free calls just like FreeInst.
Remove RaiseAllocations and all its tests since FreeInst no longer needs to be raised.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84987 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/IPA/Andersens.cpp | 4 | ||||
-rw-r--r-- | lib/Analysis/IPA/GlobalsModRef.cpp | 7 | ||||
-rw-r--r-- | lib/Analysis/MallocHelper.cpp | 26 | ||||
-rw-r--r-- | lib/Analysis/MemoryDependenceAnalysis.cpp | 8 |
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); |