mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-25 00:24:26 +00:00
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:
@ -31,28 +31,29 @@ class Type;
|
|||||||
class Value;
|
class Value;
|
||||||
|
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a library function that allocates or
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// reallocates memory (either malloc, calloc, realloc, or strdup like).
|
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
|
||||||
|
/// like).
|
||||||
bool isAllocationFn(const Value *V, bool LookThroughBitCast = false);
|
bool isAllocationFn(const Value *V, bool LookThroughBitCast = false);
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a function that returns a NoAlias
|
/// \brief Tests if a value is a call or invoke to a function that returns a
|
||||||
/// pointer (including malloc/calloc/strdup-like functions).
|
/// NoAlias pointer (including malloc/calloc/strdup-like functions).
|
||||||
bool isNoAliasFn(const Value *V, bool LookThroughBitCast = false);
|
bool isNoAliasFn(const Value *V, bool LookThroughBitCast = false);
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a library function that allocates
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// uninitialized memory (such as malloc).
|
/// allocates uninitialized memory (such as malloc).
|
||||||
bool isMallocLikeFn(const Value *V, bool LookThroughBitCast = false);
|
bool isMallocLikeFn(const Value *V, bool LookThroughBitCast = false);
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a library function that allocates
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// zero-filled memory (such as calloc).
|
/// allocates zero-filled memory (such as calloc).
|
||||||
bool isCallocLikeFn(const Value *V, bool LookThroughBitCast = false);
|
bool isCallocLikeFn(const Value *V, bool LookThroughBitCast = false);
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a library function that allocates
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// memory (either malloc, calloc, or strdup like).
|
/// allocates memory (either malloc, calloc, or strdup like).
|
||||||
bool isAllocLikeFn(const Value *V, bool LookThroughBitCast = false);
|
bool isAllocLikeFn(const Value *V, bool LookThroughBitCast = false);
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a library function that reallocates
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// memory (such as realloc).
|
/// reallocates memory (such as realloc).
|
||||||
bool isReallocLikeFn(const Value *V, bool LookThroughBitCast = false);
|
bool isReallocLikeFn(const Value *V, bool LookThroughBitCast = false);
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,11 +65,17 @@ static const AllocFnsTy AllocationFnData[] = {
|
|||||||
static Function *getCalledFunction(const Value *V, bool LookThroughBitCast) {
|
static Function *getCalledFunction(const Value *V, bool LookThroughBitCast) {
|
||||||
if (LookThroughBitCast)
|
if (LookThroughBitCast)
|
||||||
V = V->stripPointerCasts();
|
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;
|
return 0;
|
||||||
|
|
||||||
Function *Callee = CI->getCalledFunction();
|
Function *Callee = CS.getCalledFunction();
|
||||||
if (!Callee || !Callee->isDeclaration())
|
if (!Callee || !Callee->isDeclaration())
|
||||||
return 0;
|
return 0;
|
||||||
return Callee;
|
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
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// reallocates memory (either malloc, calloc, realloc, or strdup like).
|
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
|
||||||
|
/// like).
|
||||||
bool llvm::isAllocationFn(const Value *V, bool LookThroughBitCast) {
|
bool llvm::isAllocationFn(const Value *V, bool LookThroughBitCast) {
|
||||||
return getAllocationData(V, AnyAlloc, LookThroughBitCast);
|
return getAllocationData(V, AnyAlloc, LookThroughBitCast);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a function that returns a NoAlias
|
/// \brief Tests if a value is a call or invoke to a function that returns a
|
||||||
/// pointer (including malloc/calloc/strdup-like functions).
|
/// NoAlias pointer (including malloc/calloc/strdup-like functions).
|
||||||
bool llvm::isNoAliasFn(const Value *V, bool LookThroughBitCast) {
|
bool llvm::isNoAliasFn(const Value *V, bool LookThroughBitCast) {
|
||||||
return isAllocLikeFn(V, LookThroughBitCast) ||
|
return isAllocLikeFn(V, LookThroughBitCast) ||
|
||||||
hasNoAliasAttr(V, LookThroughBitCast);
|
hasNoAliasAttr(V, LookThroughBitCast);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a library function that allocates
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// uninitialized memory (such as malloc).
|
/// allocates uninitialized memory (such as malloc).
|
||||||
bool llvm::isMallocLikeFn(const Value *V, bool LookThroughBitCast) {
|
bool llvm::isMallocLikeFn(const Value *V, bool LookThroughBitCast) {
|
||||||
return getAllocationData(V, MallocLike, LookThroughBitCast);
|
return getAllocationData(V, MallocLike, LookThroughBitCast);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a library function that allocates
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// zero-filled memory (such as calloc).
|
/// allocates zero-filled memory (such as calloc).
|
||||||
bool llvm::isCallocLikeFn(const Value *V, bool LookThroughBitCast) {
|
bool llvm::isCallocLikeFn(const Value *V, bool LookThroughBitCast) {
|
||||||
return getAllocationData(V, CallocLike, LookThroughBitCast);
|
return getAllocationData(V, CallocLike, LookThroughBitCast);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a library function that allocates
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// memory (either malloc, calloc, or strdup like).
|
/// allocates memory (either malloc, calloc, or strdup like).
|
||||||
bool llvm::isAllocLikeFn(const Value *V, bool LookThroughBitCast) {
|
bool llvm::isAllocLikeFn(const Value *V, bool LookThroughBitCast) {
|
||||||
return getAllocationData(V, AllocLike, LookThroughBitCast);
|
return getAllocationData(V, AllocLike, LookThroughBitCast);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Tests if a value is a call to a library function that reallocates
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
/// memory (such as realloc).
|
/// reallocates memory (such as realloc).
|
||||||
bool llvm::isReallocLikeFn(const Value *V, bool LookThroughBitCast) {
|
bool llvm::isReallocLikeFn(const Value *V, bool LookThroughBitCast) {
|
||||||
return getAllocationData(V, ReallocLike, LookThroughBitCast);
|
return getAllocationData(V, ReallocLike, LookThroughBitCast);
|
||||||
}
|
}
|
||||||
|
@ -172,8 +172,6 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) {
|
|||||||
Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
||||||
if (isFreeCall(&CI))
|
if (isFreeCall(&CI))
|
||||||
return visitFree(CI);
|
return visitFree(CI);
|
||||||
if (isAllocLikeFn(&CI))
|
|
||||||
return visitMalloc(CI);
|
|
||||||
|
|
||||||
// If the caller function is nounwind, mark the call as nounwind, even if the
|
// If the caller function is nounwind, mark the call as nounwind, even if the
|
||||||
// callee isn't.
|
// callee isn't.
|
||||||
@ -881,6 +879,9 @@ static IntrinsicInst *FindInitTrampoline(Value *Callee) {
|
|||||||
// visitCallSite - Improvements for call and invoke instructions.
|
// visitCallSite - Improvements for call and invoke instructions.
|
||||||
//
|
//
|
||||||
Instruction *InstCombiner::visitCallSite(CallSite CS) {
|
Instruction *InstCombiner::visitCallSite(CallSite CS) {
|
||||||
|
if (isAllocLikeFn(CS.getInstruction()))
|
||||||
|
return visitMalloc(*CS.getInstruction());
|
||||||
|
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
// If the callee is a pointer to a function, attempt to move any casts to the
|
// If the callee is a pointer to a function, attempt to move any casts to the
|
||||||
|
@ -1167,6 +1167,10 @@ Instruction *InstCombiner::visitMalloc(Instruction &MI) {
|
|||||||
}
|
}
|
||||||
EraseInstFromFunction(*I);
|
EraseInstFromFunction(*I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (InvokeInst *II = dyn_cast<InvokeInst>(&MI)) {
|
||||||
|
BranchInst::Create(II->getNormalDest(), II->getParent());
|
||||||
|
}
|
||||||
return EraseInstFromFunction(MI);
|
return EraseInstFromFunction(MI);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -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"
|
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* @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
|
declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readonly
|
||||||
|
|
||||||
; CHECK: @f1
|
; CHECK: @f1
|
||||||
@ -11,3 +14,24 @@ define i64 @f1() {
|
|||||||
; CHECK-NEXT: ret i64 4
|
; CHECK-NEXT: ret i64 4
|
||||||
ret i64 %size
|
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
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user