forked from OSchip/llvm-project
[objc-arc] Treat memcpy, memove, memset as just using pointers, not decrementing them.
This will be tested in the next commit (which required it). The commit is going to update a bunch of tests at the same time. llvm-svn: 232350
This commit is contained in:
parent
6779217ec5
commit
7a26d8fa54
|
@ -168,6 +168,60 @@ ARCInstKind llvm::objcarc::GetFunctionClass(const Function *F) {
|
||||||
return ARCInstKind::CallOrUser;
|
return ARCInstKind::CallOrUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A whitelist of intrinsics that we know do not use objc pointers or decrement
|
||||||
|
// ref counts.
|
||||||
|
static bool isInertIntrinsic(unsigned ID) {
|
||||||
|
// TODO: Make this into a covered switch.
|
||||||
|
switch (ID) {
|
||||||
|
case Intrinsic::returnaddress:
|
||||||
|
case Intrinsic::frameaddress:
|
||||||
|
case Intrinsic::stacksave:
|
||||||
|
case Intrinsic::stackrestore:
|
||||||
|
case Intrinsic::vastart:
|
||||||
|
case Intrinsic::vacopy:
|
||||||
|
case Intrinsic::vaend:
|
||||||
|
case Intrinsic::objectsize:
|
||||||
|
case Intrinsic::prefetch:
|
||||||
|
case Intrinsic::stackprotector:
|
||||||
|
case Intrinsic::eh_return_i32:
|
||||||
|
case Intrinsic::eh_return_i64:
|
||||||
|
case Intrinsic::eh_typeid_for:
|
||||||
|
case Intrinsic::eh_dwarf_cfa:
|
||||||
|
case Intrinsic::eh_sjlj_lsda:
|
||||||
|
case Intrinsic::eh_sjlj_functioncontext:
|
||||||
|
case Intrinsic::init_trampoline:
|
||||||
|
case Intrinsic::adjust_trampoline:
|
||||||
|
case Intrinsic::lifetime_start:
|
||||||
|
case Intrinsic::lifetime_end:
|
||||||
|
case Intrinsic::invariant_start:
|
||||||
|
case Intrinsic::invariant_end:
|
||||||
|
// Don't let dbg info affect our results.
|
||||||
|
case Intrinsic::dbg_declare:
|
||||||
|
case Intrinsic::dbg_value:
|
||||||
|
// Short cut: Some intrinsics obviously don't use ObjC pointers.
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A whitelist of intrinsics that we know do not use objc pointers or decrement
|
||||||
|
// ref counts.
|
||||||
|
static bool isUseOnlyIntrinsic(unsigned ID) {
|
||||||
|
// We are conservative and even though intrinsics are unlikely to touch
|
||||||
|
// reference counts, we white list them for safety.
|
||||||
|
//
|
||||||
|
// TODO: Expand this into a covered switch. There is a lot more here.
|
||||||
|
switch (ID) {
|
||||||
|
case Intrinsic::memcpy:
|
||||||
|
case Intrinsic::memmove:
|
||||||
|
case Intrinsic::memset:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Determine what kind of construct V is.
|
/// \brief Determine what kind of construct V is.
|
||||||
ARCInstKind llvm::objcarc::GetARCInstKind(const Value *V) {
|
ARCInstKind llvm::objcarc::GetARCInstKind(const Value *V) {
|
||||||
if (const Instruction *I = dyn_cast<Instruction>(V)) {
|
if (const Instruction *I = dyn_cast<Instruction>(V)) {
|
||||||
|
@ -180,49 +234,23 @@ ARCInstKind llvm::objcarc::GetARCInstKind(const Value *V) {
|
||||||
switch (I->getOpcode()) {
|
switch (I->getOpcode()) {
|
||||||
case Instruction::Call: {
|
case Instruction::Call: {
|
||||||
const CallInst *CI = cast<CallInst>(I);
|
const CallInst *CI = cast<CallInst>(I);
|
||||||
// Check for calls to special functions.
|
// See if we have a function that we know something about.
|
||||||
if (const Function *F = CI->getCalledFunction()) {
|
if (const Function *F = CI->getCalledFunction()) {
|
||||||
ARCInstKind Class = GetFunctionClass(F);
|
ARCInstKind Class = GetFunctionClass(F);
|
||||||
if (Class != ARCInstKind::CallOrUser)
|
if (Class != ARCInstKind::CallOrUser)
|
||||||
return Class;
|
return Class;
|
||||||
|
unsigned ID = F->getIntrinsicID();
|
||||||
// None of the intrinsic functions do objc_release. For intrinsics, the
|
if (isInertIntrinsic(ID))
|
||||||
// only question is whether or not they may be users.
|
|
||||||
switch (F->getIntrinsicID()) {
|
|
||||||
case Intrinsic::returnaddress:
|
|
||||||
case Intrinsic::frameaddress:
|
|
||||||
case Intrinsic::stacksave:
|
|
||||||
case Intrinsic::stackrestore:
|
|
||||||
case Intrinsic::vastart:
|
|
||||||
case Intrinsic::vacopy:
|
|
||||||
case Intrinsic::vaend:
|
|
||||||
case Intrinsic::objectsize:
|
|
||||||
case Intrinsic::prefetch:
|
|
||||||
case Intrinsic::stackprotector:
|
|
||||||
case Intrinsic::eh_return_i32:
|
|
||||||
case Intrinsic::eh_return_i64:
|
|
||||||
case Intrinsic::eh_typeid_for:
|
|
||||||
case Intrinsic::eh_dwarf_cfa:
|
|
||||||
case Intrinsic::eh_sjlj_lsda:
|
|
||||||
case Intrinsic::eh_sjlj_functioncontext:
|
|
||||||
case Intrinsic::init_trampoline:
|
|
||||||
case Intrinsic::adjust_trampoline:
|
|
||||||
case Intrinsic::lifetime_start:
|
|
||||||
case Intrinsic::lifetime_end:
|
|
||||||
case Intrinsic::invariant_start:
|
|
||||||
case Intrinsic::invariant_end:
|
|
||||||
// Don't let dbg info affect our results.
|
|
||||||
case Intrinsic::dbg_declare:
|
|
||||||
case Intrinsic::dbg_value:
|
|
||||||
// Short cut: Some intrinsics obviously don't use ObjC pointers.
|
|
||||||
return ARCInstKind::None;
|
return ARCInstKind::None;
|
||||||
default:
|
if (isUseOnlyIntrinsic(ID))
|
||||||
break;
|
return ARCInstKind::User;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, be conservative.
|
||||||
return GetCallSiteClass(CI);
|
return GetCallSiteClass(CI);
|
||||||
}
|
}
|
||||||
case Instruction::Invoke:
|
case Instruction::Invoke:
|
||||||
|
// Otherwise, be conservative.
|
||||||
return GetCallSiteClass(cast<InvokeInst>(I));
|
return GetCallSiteClass(cast<InvokeInst>(I));
|
||||||
case Instruction::BitCast:
|
case Instruction::BitCast:
|
||||||
case Instruction::GetElementPtr:
|
case Instruction::GetElementPtr:
|
||||||
|
|
Loading…
Reference in New Issue