From: Michael Gottesman Date: Wed, 3 Apr 2013 02:57:24 +0000 (+0000) Subject: Remove an optimization where we were changing an objc_autorelease into an objc_autore... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;ds=sidebyside;h=a67a20c95f08b31b499d06d1fa47bdf14f9d40d0;p=oota-llvm.git 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 --- diff --git a/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/lib/Transforms/ObjCARC/ObjCARCOpts.cpp index a956caeffe0..5ac8c8e6c27 100644 --- a/lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ b/lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -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(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. diff --git a/test/Transforms/ObjCARC/basic.ll b/test/Transforms/ObjCARC/basic.ll index bf6ccc8a7fc..828a8a70112 100644 --- a/test/Transforms/ObjCARC/basic.ll +++ b/test/Transforms/ObjCARC/basic.ll @@ -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: diff --git a/test/Transforms/ObjCARC/rv.ll b/test/Transforms/ObjCARC/rv.ll index a2fef967495..589c60f9f3a 100644 --- a/test/Transforms/ObjCARC/rv.ll +++ b/test/Transforms/ObjCARC/rv.ll @@ -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) diff --git a/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll b/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll index 74ac97c7b30..26cd67727e6 100644 --- a/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll +++ b/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll @@ -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 -}