Don't convert objc_autoreleaseReturnValue to objc_autorelease if the result
authorDan Gohman <gohman@apple.com>
Fri, 12 Aug 2011 00:36:31 +0000 (00:36 +0000)
committerDan Gohman <gohman@apple.com>
Fri, 12 Aug 2011 00:36:31 +0000 (00:36 +0000)
is returned through a bitcast.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137402 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/ObjCARC.cpp
test/Transforms/ObjCARC/rv.ll

index f2cda41c9769aceefa49695a12e7f1363740634a..c74c353e81a9b284944000b7e370311313be900a 100644 (file)
@@ -1925,12 +1925,19 @@ void
 ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV) {
   // Check for a return of the pointer value.
   const Value *Ptr = GetObjCArg(AutoreleaseRV);
-  for (Value::const_use_iterator UI = Ptr->use_begin(), UE = Ptr->use_end();
-       UI != UE; ++UI) {
-    const User *I = *UI;
-    if (isa<ReturnInst>(I) || GetBasicInstructionClass(I) == IC_RetainRV)
-      return;
-  }
+  SmallVector<const Value *, 2> Users;
+  Users.push_back(Ptr);
+  do {
+    Ptr = Users.pop_back_val();
+    for (Value::const_use_iterator UI = Ptr->use_begin(), UE = Ptr->use_end();
+         UI != UE; ++UI) {
+      const User *I = *UI;
+      if (isa<ReturnInst>(I) || GetBasicInstructionClass(I) == IC_RetainRV)
+        return;
+      if (isa<BitCastInst>(I))
+        Users.push_back(I);
+    }
+  } while (!Users.empty());
 
   Changed = true;
   ++NumPeeps;
index da53a86b10fde6b53ae38fd3290727ec3a10bb5c..9353a19f71a440e6fd2fd3784dc2eb809b597949 100644 (file)
@@ -329,3 +329,14 @@ define void @test23(i8* %p) {
   call i8* @objc_autoreleaseReturnValue(i8* %p)
   ret void
 }
+
+; Don't convert autoreleaseRV to autorelease if the result is returned,
+; even through a bitcast.
+
+; CHECK: define {}* @test24(
+; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %p)
+define {}* @test24(i8* %p) {
+  %t = call i8* @objc_autoreleaseReturnValue(i8* %p)
+  %s = bitcast i8* %p to {}*
+  ret {}* %s
+}