mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
Remove an optimization where we were changing an objc_autorelease into an objc_autoreleaseReturnValue.
The semantics of ARC implies that a pointer passed into an objc_autorelease must live until some point (potentially down the stack) where an autorelease pool is popped. On the other hand, an objc_autoreleaseReturnValue just signifies that the object must live until the end of the given function at least. Thus objc_autorelease is stronger than objc_autoreleaseReturnValue in terms of the semantics of ARC* implying that performing the given strength reduction without any knowledge of how this relates to the autorelease pool pop that is further up the stack violates the semantics of ARC. *Even though objc_autoreleaseReturnValue if you know that no RV optimization will occur is more computationally expensive. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178612 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
003d5f946d
commit
a67a20c95f
@ -1440,8 +1440,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
|
||||
break;
|
||||
}
|
||||
|
||||
// objc_autorelease(x), objc_autoreleaseRV -> objc_release(x) if x is
|
||||
// otherwise unused.
|
||||
// objc_autorelease(x) -> objc_release(x) if x is otherwise unused.
|
||||
if (IsAutorelease(Class) && Inst->use_empty()) {
|
||||
CallInst *Call = cast<CallInst>(Inst);
|
||||
const Value *Arg = Call->getArgOperand(0);
|
||||
@ -2861,20 +2860,6 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {
|
||||
DependingInstructions.clear();
|
||||
Visited.clear();
|
||||
|
||||
// Convert the autorelease to an autoreleaseRV, since it's
|
||||
// returning the value.
|
||||
if (AutoreleaseClass == IC_Autorelease) {
|
||||
DEBUG(dbgs() << "ObjCARCOpt::OptimizeReturns: Converting autorelease "
|
||||
"=> autoreleaseRV since it's returning a value.\n"
|
||||
" In: " << *Autorelease
|
||||
<< "\n");
|
||||
Autorelease->setCalledFunction(getAutoreleaseRVCallee(F.getParent()));
|
||||
DEBUG(dbgs() << " Out: " << *Autorelease
|
||||
<< "\n");
|
||||
Autorelease->setTailCall(); // Always tail call autoreleaseRV.
|
||||
AutoreleaseClass = IC_AutoreleaseRV;
|
||||
}
|
||||
|
||||
// Check that there is nothing that can affect the reference
|
||||
// count between the retain and the call.
|
||||
// Note that Retain need not be in BB.
|
||||
|
@ -428,11 +428,13 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Same as test11 but the value is returned. Do an RV optimization.
|
||||
; Same as test11 but the value is returned. Do not perform an RV optimization
|
||||
; since if the frontend emitted code for an __autoreleasing variable, we may
|
||||
; want it to be in the autorelease pool.
|
||||
|
||||
; CHECK: define i8* @test11b(
|
||||
; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]]
|
||||
; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %0) [[NUW]]
|
||||
; CHECK: call i8* @objc_autorelease(i8* %0) [[NUW]]
|
||||
; CHECK: }
|
||||
define i8* @test11b(i8* %x) nounwind {
|
||||
entry:
|
||||
|
@ -121,7 +121,7 @@ define i8* @test7() {
|
||||
%p = call i8* @returner()
|
||||
call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
|
||||
%t = call i8* @objc_autoreleaseReturnValue(i8* %p)
|
||||
call void @use_pointer(i8* %t)
|
||||
call void @use_pointer(i8* %p)
|
||||
ret i8* %t
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ define i8* @test7b() {
|
||||
call void @use_pointer(i8* %p)
|
||||
call i8* @objc_retainAutoreleasedReturnValue(i8* %p)
|
||||
%t = call i8* @objc_autoreleaseReturnValue(i8* %p)
|
||||
ret i8* %t
|
||||
ret i8* %p
|
||||
}
|
||||
|
||||
; Turn objc_retain into objc_retainAutoreleasedReturnValue if its operand
|
||||
@ -156,11 +156,11 @@ define i8* @test9(i8* %p) {
|
||||
ret i8* %p
|
||||
}
|
||||
|
||||
; Apply the RV optimization.
|
||||
; Do not apply the RV optimization.
|
||||
|
||||
; CHECK: define i8* @test10(i8* %p)
|
||||
; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]]
|
||||
; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %p) [[NUW]]
|
||||
; CHECK: call i8* @objc_autorelease(i8* %p) [[NUW]]
|
||||
; CHECK-NEXT: ret i8* %p
|
||||
define i8* @test10(i8* %p) {
|
||||
%1 = call i8* @objc_retain(i8* %p)
|
||||
|
@ -72,13 +72,3 @@ entry:
|
||||
ret i8* %tmp0
|
||||
}
|
||||
|
||||
; If we convert a called @objc_autorelease to an @objc_autoreleaseReturnValue,
|
||||
; ensure that the tail call is added.
|
||||
define i8* @test6(i8* %x) {
|
||||
entry:
|
||||
; CHECK: %tmp0 = tail call i8* @objc_retain(i8* %x)
|
||||
%tmp0 = tail call i8* @objc_retain(i8* %x)
|
||||
; CHECK: %tmp1 = tail call i8* @objc_autoreleaseReturnValue(i8* %x)
|
||||
%tmp1 = call i8* @objc_autorelease(i8* %x)
|
||||
ret i8* %x
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user