aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2011-08-12 00:36:31 +0000
committerDan Gohman <gohman@apple.com>2011-08-12 00:36:31 +0000
commit10a18d55ce457b3fd1a045105f40a1dbb7f58054 (patch)
tree721caa64d89be146d1a71cefffff9840f1024528
parent9b25cee36f3be25b47c3e839432b445709b844ac (diff)
downloadllvm-10a18d55ce457b3fd1a045105f40a1dbb7f58054.zip
llvm-10a18d55ce457b3fd1a045105f40a1dbb7f58054.tar.gz
llvm-10a18d55ce457b3fd1a045105f40a1dbb7f58054.tar.bz2
Don't convert objc_autoreleaseReturnValue to objc_autorelease if the result
is returned through a bitcast. llvm-svn: 137402
-rw-r--r--llvm/lib/Transforms/Scalar/ObjCARC.cpp19
-rw-r--r--llvm/test/Transforms/ObjCARC/rv.ll11
2 files changed, 24 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Scalar/ObjCARC.cpp b/llvm/lib/Transforms/Scalar/ObjCARC.cpp
index f2cda41..c74c353 100644
--- a/llvm/lib/Transforms/Scalar/ObjCARC.cpp
+++ b/llvm/lib/Transforms/Scalar/ObjCARC.cpp
@@ -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;
diff --git a/llvm/test/Transforms/ObjCARC/rv.ll b/llvm/test/Transforms/ObjCARC/rv.ll
index da53a86..9353a19 100644
--- a/llvm/test/Transforms/ObjCARC/rv.ll
+++ b/llvm/test/Transforms/ObjCARC/rv.ll
@@ -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
+}