Remove an optimization where we were changing an objc_autorelease into an objc_autore...
authorMichael Gottesman <mgottesman@apple.com>
Wed, 3 Apr 2013 02:57:24 +0000 (02:57 +0000)
committerMichael Gottesman <mgottesman@apple.com>
Wed, 3 Apr 2013 02:57:24 +0000 (02:57 +0000)
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

lib/Transforms/ObjCARC/ObjCARCOpts.cpp
test/Transforms/ObjCARC/basic.ll
test/Transforms/ObjCARC/rv.ll
test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll

index a956caeffe0addba6e172b2a9fce0e90035cfdb4..5ac8c8e6c273e99434d954a4ecd71513a5d9b9f3 100644 (file)
@@ -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.
index bf6ccc8a7fc2bec8c803fc97f3fe7e24693cad35..828a8a701127cb6bbdeec6a6156aefd133d9de9c 100644 (file)
@@ -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:
index a2fef967495b9155fbc809d8d4c066829c8062a8..589c60f9f3aaa13c8201ac848ce666993f217224 100644 (file)
@@ -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)
index 74ac97c7b307f8feef2292e6f40d0b38f730934b..26cd67727e6a66a70d75488abda23294fd72590c 100644 (file)
@@ -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
-}