Move the last uses of RetainFunc etc. over to using getRetainCallee() etc.

so that a declaration for objc_retain is created when needed if it doesn't
already exist. rdar://9825114.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135821 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2011-07-22 22:29:21 +00:00
parent 1608637bbd
commit 4428069f10
2 changed files with 77 additions and 29 deletions

View File

@ -1406,15 +1406,11 @@ namespace {
/// Run - A flag indicating whether this optimization pass should run.
bool Run;
/// RetainFunc, RelaseFunc - Declarations for objc_retain,
/// objc_retainBlock, and objc_release.
Function *RetainFunc, *RetainBlockFunc, *RetainRVFunc, *ReleaseFunc;
/// RetainRVCallee, etc. - Declarations for ObjC runtime
/// functions, for use in creating calls to them. These are initialized
/// lazily to avoid cluttering up the Module with unused declarations.
Constant *RetainRVCallee, *AutoreleaseRVCallee, *ReleaseCallee,
*RetainCallee, *AutoreleaseCallee;
*RetainCallee, *RetainBlockCallee, *AutoreleaseCallee;
/// UsedInThisFunciton - Flags which determine whether each of the
/// interesting runtine functions is in fact used in the current function.
@ -1428,6 +1424,7 @@ namespace {
Constant *getAutoreleaseRVCallee(Module *M);
Constant *getReleaseCallee(Module *M);
Constant *getRetainCallee(Module *M);
Constant *getRetainBlockCallee(Module *M);
Constant *getAutoreleaseCallee(Module *M);
void OptimizeRetainCall(Function &F, Instruction *Retain);
@ -1452,11 +1449,13 @@ namespace {
void MoveCalls(Value *Arg, RRInfo &RetainsToMove, RRInfo &ReleasesToMove,
MapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases,
SmallVectorImpl<Instruction *> &DeadInsts);
SmallVectorImpl<Instruction *> &DeadInsts,
Module *M);
bool PerformCodePlacement(DenseMap<const BasicBlock *, BBState> &BBStates,
MapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases);
DenseMap<Value *, RRInfo> &Releases,
Module *M);
void OptimizeWeakCalls(Function &F);
@ -1561,6 +1560,22 @@ Constant *ObjCARCOpt::getRetainCallee(Module *M) {
return RetainCallee;
}
Constant *ObjCARCOpt::getRetainBlockCallee(Module *M) {
if (!RetainBlockCallee) {
LLVMContext &C = M->getContext();
std::vector<Type *> Params;
Params.push_back(PointerType::getUnqual(Type::getInt8Ty(C)));
AttrListPtr Attributes;
Attributes.addAttr(~0u, Attribute::NoUnwind);
RetainBlockCallee =
M->getOrInsertFunction(
"objc_retainBlock",
FunctionType::get(Params[0], Params, /*isVarArg=*/false),
Attributes);
}
return RetainBlockCallee;
}
Constant *ObjCARCOpt::getAutoreleaseCallee(Module *M) {
if (!AutoreleaseCallee) {
LLVMContext &C = M->getContext();
@ -2565,12 +2580,10 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
RRInfo &ReleasesToMove,
MapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases,
SmallVectorImpl<Instruction *> &DeadInsts) {
SmallVectorImpl<Instruction *> &DeadInsts,
Module *M) {
Type *ArgTy = Arg->getType();
Type *ParamTy =
(RetainRVFunc ? RetainRVFunc :
RetainFunc ? RetainFunc :
RetainBlockFunc)->arg_begin()->getType();
Type *ParamTy = PointerType::getUnqual(Type::getInt8Ty(ArgTy->getContext()));
// Insert the new retain and release calls.
for (SmallPtrSet<Instruction *, 2>::const_iterator
@ -2581,7 +2594,7 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
new BitCastInst(Arg, ParamTy, "", InsertPt);
CallInst *Call =
CallInst::Create(RetainsToMove.IsRetainBlock ?
RetainBlockFunc : RetainFunc,
getRetainBlockCallee(M) : getRetainCallee(M),
MyArg, "", InsertPt);
Call->setDoesNotThrow();
if (!RetainsToMove.IsRetainBlock)
@ -2609,7 +2622,8 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
Instruction *InsertPt = *I;
Value *MyArg = ArgTy == ParamTy ? Arg :
new BitCastInst(Arg, ParamTy, "", InsertPt);
CallInst *Call = CallInst::Create(ReleaseFunc, MyArg, "", InsertPt);
CallInst *Call = CallInst::Create(getReleaseCallee(M), MyArg,
"", InsertPt);
// Attach a clang.imprecise_release metadata tag, if appropriate.
if (MDNode *M = ReleasesToMove.ReleaseMetadata)
Call->setMetadata(ImpreciseReleaseMDKind, M);
@ -2640,7 +2654,8 @@ bool
ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
&BBStates,
MapVector<Value *, RRInfo> &Retains,
DenseMap<Value *, RRInfo> &Releases) {
DenseMap<Value *, RRInfo> &Releases,
Module *M) {
bool AnyPairsCompletelyEliminated = false;
RRInfo RetainsToMove;
RRInfo ReleasesToMove;
@ -2814,7 +2829,8 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
Changed = true;
AnyPairsCompletelyEliminated = NewCount == 0;
NumRRs += OldCount - NewCount;
MoveCalls(Arg, RetainsToMove, ReleasesToMove, Retains, Releases, DeadInsts);
MoveCalls(Arg, RetainsToMove, ReleasesToMove,
Retains, Releases, DeadInsts, M);
next_retain:
NewReleases.clear();
@ -2993,7 +3009,8 @@ bool ObjCARCOpt::OptimizeSequences(Function &F) {
bool NestingDetected = Visit(F, BBStates, Retains, Releases);
// Transform.
return PerformCodePlacement(BBStates, Retains, Releases) && NestingDetected;
return PerformCodePlacement(BBStates, Retains, Releases, F.getParent()) &&
NestingDetected;
}
/// OptimizeReturns - Look for this pattern:
@ -3117,12 +3134,6 @@ bool ObjCARCOpt::doInitialization(Module &M) {
ImpreciseReleaseMDKind =
M.getContext().getMDKindID("clang.imprecise_release");
// Identify the declarations for objc_retain and friends.
RetainFunc = M.getFunction("objc_retain");
RetainBlockFunc = M.getFunction("objc_retainBlock");
RetainRVFunc = M.getFunction("objc_retainAutoreleasedReturnValue");
ReleaseFunc = M.getFunction("objc_release");
// Intuitively, objc_retain and others are nocapture, however in practice
// they are not, because they return their argument value. And objc_release
// calls finalizers.
@ -3132,6 +3143,7 @@ bool ObjCARCOpt::doInitialization(Module &M) {
AutoreleaseRVCallee = 0;
ReleaseCallee = 0;
RetainCallee = 0;
RetainBlockCallee = 0;
AutoreleaseCallee = 0;
return false;

View File

@ -1,21 +1,23 @@
; RUN: opt -S -objc-arc -objc-arc-contract < %s | FileCheck %s
; Test that the optimizer can create an objc_retainAutoreleaseReturnValue
; declaration even if no objc_retain declaration exists.
; rdar://9401303
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"
declare i8* @objc_unretainedObject(i8*)
declare i8* @objc_retainAutoreleasedReturnValue(i8*)
declare i8* @objc_autoreleaseReturnValue(i8*)
declare i8* @objc_msgSend(i8*, i8*, ...)
declare void @objc_release(i8*)
; CHECK: define i8* @foo(i8* %p) {
; Test that the optimizer can create an objc_retainAutoreleaseReturnValue
; declaration even if no objc_retain declaration exists.
; rdar://9401303
; CHECK: define i8* @test0(i8* %p) {
; CHECK-NEXT: entry:
; CHECK-NEXT: %0 = tail call i8* @objc_retainAutoreleaseReturnValue(i8* %p) nounwind
; CHECK-NEXT: ret i8* %0
; CHECK-NEXT: }
define i8* @foo(i8* %p) {
define i8* @test0(i8* %p) {
entry:
%call = tail call i8* @objc_unretainedObject(i8* %p)
%0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
@ -23,3 +25,37 @@ entry:
ret i8* %1
}
; Properly create the @objc_retain declaration when it doesn't already exist.
; rdar://9825114
; CHECK: @test1(
; CHECK: @objc_retain(
; CHECK: @objc_retain(
; CHECK: @objc_release(
; CHECK: @objc_release(
; CHECK: }
define void @test1(i8* %call88) nounwind {
entry:
%tmp1 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call88) nounwind
%call94 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*)*)(i8* %tmp1)
to label %invoke.cont93 unwind label %lpad91
invoke.cont93: ; preds = %entry
%tmp2 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call94) nounwind
call void @objc_release(i8* %tmp1) nounwind
invoke void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*)*)(i8* %tmp2)
to label %invoke.cont102 unwind label %lpad100
invoke.cont102: ; preds = %invoke.cont93
call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
unreachable
lpad91: ; preds = %entry
unreachable
lpad100: ; preds = %invoke.cont93
call void @objc_release(i8* %tmp2) nounwind, !clang.imprecise_release !0
unreachable
}
!0 = metadata !{}