diff options
author | Dan Gohman <gohman@apple.com> | 2011-07-22 22:29:21 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2011-07-22 22:29:21 +0000 |
commit | 4428069f10ac6e7efb55826437c82428d4bbe03e (patch) | |
tree | fced350a562033348810a1bb78df681b7c406f01 | |
parent | 1608637bbd327fe1fbc82e0e0639224b124de720 (diff) |
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
-rw-r--r-- | lib/Transforms/Scalar/ObjCARC.cpp | 58 | ||||
-rw-r--r-- | test/Transforms/ObjCARC/retain-not-declared.ll | 48 |
2 files changed, 77 insertions, 29 deletions
diff --git a/lib/Transforms/Scalar/ObjCARC.cpp b/lib/Transforms/Scalar/ObjCARC.cpp index f2e5ff9ac9..91233d69d2 100644 --- a/lib/Transforms/Scalar/ObjCARC.cpp +++ b/lib/Transforms/Scalar/ObjCARC.cpp @@ -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; diff --git a/test/Transforms/ObjCARC/retain-not-declared.ll b/test/Transforms/ObjCARC/retain-not-declared.ll index e1fe117063..80ac828a08 100644 --- a/test/Transforms/ObjCARC/retain-not-declared.ll +++ b/test/Transforms/ObjCARC/retain-not-declared.ll @@ -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*) + +; Test that the optimizer can create an objc_retainAutoreleaseReturnValue +; declaration even if no objc_retain declaration exists. +; rdar://9401303 -; CHECK: define i8* @foo(i8* %p) { +; 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 !{} |