Add support for invoke to the MemoryBuiltin analysid.

Update comments accordingly.

Make instcombine remove useless invokes to C++'s 'new' allocation function (test attached).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158937 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nuno Lopes 2012-06-21 21:25:05 +00:00
parent 54c5bc8799
commit 2b3e958053
5 changed files with 66 additions and 29 deletions

View File

@ -31,28 +31,29 @@ class Type;
class Value;
/// \brief Tests if a value is a call to a library function that allocates or
/// reallocates memory (either malloc, calloc, realloc, or strdup like).
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
/// like).
bool isAllocationFn(const Value *V, bool LookThroughBitCast = false);
/// \brief Tests if a value is a call to a function that returns a NoAlias
/// pointer (including malloc/calloc/strdup-like functions).
/// \brief Tests if a value is a call or invoke to a function that returns a
/// NoAlias pointer (including malloc/calloc/strdup-like functions).
bool isNoAliasFn(const Value *V, bool LookThroughBitCast = false);
/// \brief Tests if a value is a call to a library function that allocates
/// uninitialized memory (such as malloc).
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates uninitialized memory (such as malloc).
bool isMallocLikeFn(const Value *V, bool LookThroughBitCast = false);
/// \brief Tests if a value is a call to a library function that allocates
/// zero-filled memory (such as calloc).
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates zero-filled memory (such as calloc).
bool isCallocLikeFn(const Value *V, bool LookThroughBitCast = false);
/// \brief Tests if a value is a call to a library function that allocates
/// memory (either malloc, calloc, or strdup like).
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates memory (either malloc, calloc, or strdup like).
bool isAllocLikeFn(const Value *V, bool LookThroughBitCast = false);
/// \brief Tests if a value is a call to a library function that reallocates
/// memory (such as realloc).
/// \brief Tests if a value is a call or invoke to a library function that
/// reallocates memory (such as realloc).
bool isReallocLikeFn(const Value *V, bool LookThroughBitCast = false);

View File

@ -65,11 +65,17 @@ static const AllocFnsTy AllocationFnData[] = {
static Function *getCalledFunction(const Value *V, bool LookThroughBitCast) {
if (LookThroughBitCast)
V = V->stripPointerCasts();
const CallInst *CI = dyn_cast<CallInst>(V);
if (!CI)
Value *I = const_cast<Value*>(V);
CallSite CS;
if (CallInst *CI = dyn_cast<CallInst>(I))
CS = CallSite(CI);
else if (InvokeInst *II = dyn_cast<InvokeInst>(I))
CS = CallSite(II);
else
return 0;
Function *Callee = CI->getCalledFunction();
Function *Callee = CS.getCalledFunction();
if (!Callee || !Callee->isDeclaration())
return 0;
return Callee;
@ -122,39 +128,40 @@ static bool hasNoAliasAttr(const Value *V, bool LookThroughBitCast) {
}
/// \brief Tests if a value is a call to a library function that allocates or
/// reallocates memory (either malloc, calloc, realloc, or strdup like).
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
/// like).
bool llvm::isAllocationFn(const Value *V, bool LookThroughBitCast) {
return getAllocationData(V, AnyAlloc, LookThroughBitCast);
}
/// \brief Tests if a value is a call to a function that returns a NoAlias
/// pointer (including malloc/calloc/strdup-like functions).
/// \brief Tests if a value is a call or invoke to a function that returns a
/// NoAlias pointer (including malloc/calloc/strdup-like functions).
bool llvm::isNoAliasFn(const Value *V, bool LookThroughBitCast) {
return isAllocLikeFn(V, LookThroughBitCast) ||
hasNoAliasAttr(V, LookThroughBitCast);
}
/// \brief Tests if a value is a call to a library function that allocates
/// uninitialized memory (such as malloc).
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates uninitialized memory (such as malloc).
bool llvm::isMallocLikeFn(const Value *V, bool LookThroughBitCast) {
return getAllocationData(V, MallocLike, LookThroughBitCast);
}
/// \brief Tests if a value is a call to a library function that allocates
/// zero-filled memory (such as calloc).
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates zero-filled memory (such as calloc).
bool llvm::isCallocLikeFn(const Value *V, bool LookThroughBitCast) {
return getAllocationData(V, CallocLike, LookThroughBitCast);
}
/// \brief Tests if a value is a call to a library function that allocates
/// memory (either malloc, calloc, or strdup like).
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates memory (either malloc, calloc, or strdup like).
bool llvm::isAllocLikeFn(const Value *V, bool LookThroughBitCast) {
return getAllocationData(V, AllocLike, LookThroughBitCast);
}
/// \brief Tests if a value is a call to a library function that reallocates
/// memory (such as realloc).
/// \brief Tests if a value is a call or invoke to a library function that
/// reallocates memory (such as realloc).
bool llvm::isReallocLikeFn(const Value *V, bool LookThroughBitCast) {
return getAllocationData(V, ReallocLike, LookThroughBitCast);
}

View File

@ -172,8 +172,6 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) {
Instruction *InstCombiner::visitCallInst(CallInst &CI) {
if (isFreeCall(&CI))
return visitFree(CI);
if (isAllocLikeFn(&CI))
return visitMalloc(CI);
// If the caller function is nounwind, mark the call as nounwind, even if the
// callee isn't.
@ -881,6 +879,9 @@ static IntrinsicInst *FindInitTrampoline(Value *Callee) {
// visitCallSite - Improvements for call and invoke instructions.
//
Instruction *InstCombiner::visitCallSite(CallSite CS) {
if (isAllocLikeFn(CS.getInstruction()))
return visitMalloc(*CS.getInstruction());
bool Changed = false;
// If the callee is a pointer to a function, attempt to move any casts to the

View File

@ -1167,6 +1167,10 @@ Instruction *InstCombiner::visitMalloc(Instruction &MI) {
}
EraseInstFromFunction(*I);
}
if (InvokeInst *II = dyn_cast<InvokeInst>(&MI)) {
BranchInst::Create(II->getNormalDest(), II->getParent());
}
return EraseInstFromFunction(MI);
}
return 0;

View File

@ -2,6 +2,9 @@
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
declare noalias i8* @malloc(i32) nounwind
declare noalias i8* @_Znwm(i64) ; new(unsigned long)
declare i32 @__gxx_personality_v0(...)
declare void @__cxa_call_unexpected(i8*)
declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readonly
; CHECK: @f1
@ -11,3 +14,24 @@ define i64 @f1() {
; CHECK-NEXT: ret i64 4
ret i64 %size
}
; CHECK: @f2
define i64 @f2() nounwind uwtable ssp {
entry:
; CHECK: br label
%call = invoke noalias i8* @_Znwm(i64 13)
to label %invoke.cont unwind label %lpad
invoke.cont:
; CHECK: ret i64 13
%0 = tail call i64 @llvm.objectsize.i64(i8* %call, i1 false)
ret i64 %0
lpad:
%1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
filter [0 x i8*] zeroinitializer
%2 = extractvalue { i8*, i32 } %1, 0
tail call void @__cxa_call_unexpected(i8* %2) noreturn nounwind
unreachable
}