An objc_retain can serve as a may-use for a different pointer.
authorDan Gohman <gohman@apple.com>
Mon, 23 Jul 2012 19:27:31 +0000 (19:27 +0000)
committerDan Gohman <gohman@apple.com>
Mon, 23 Jul 2012 19:27:31 +0000 (19:27 +0000)
rdar://11931823.

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

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

index 64f71d380a8ae2305464bc832e5c382e76d6b3f2..3222f2083b994482978ba43a09d6a654ee612a00 100644 (file)
@@ -2829,7 +2829,10 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
     }
 
     S.IncrementNestCount();
-    return NestingDetected;
+
+    // A retain can be a potential use; procede to the generic checking
+    // code below.
+    break;
   }
   case IC_Release: {
     Arg = GetObjCArg(Inst);
index ba2f778a28ecde3e0b5794d76e4b211b8120c754..d9bb3f25bd79d8f076ff55db03e2c17bf3259524 100644 (file)
@@ -1871,6 +1871,30 @@ return:                                           ; preds = %if.then, %entry
   ret i8* %retval
 }
 
+; An objc_retain can serve as a may-use for a different pointer.
+; rdar://11931823
+
+; CHECK: define void @test66(
+; CHECK:   %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind
+; CHECK:   tail call void @objc_release(i8* %cond) nounwind
+; CHECK: }
+define void @test66(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) {
+entry:
+  br i1 %tobool, label %cond.true, label %cond.end
+
+cond.true:
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.true, %entry
+  %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ]
+  %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind
+  tail call void @objc_release(i8* %call) nounwind
+  %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar
+  %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind
+  tail call void @objc_release(i8* %cond) nounwind
+  ret void
+}
+
 declare void @bar(i32 ()*)
 
 ; A few real-world testcases.