mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-31 09:32:11 +00:00
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:
parent
1608637bbd
commit
4428069f10
@ -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;
|
||||
|
@ -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 !{}
|
||||
|
Loading…
Reference in New Issue
Block a user