At -O0, prefer objc_storeStrong with a null new value to the
combination of a load+objc_release;  this is generally better
for tools that try to track why values are retained and
released.  Also use objc_storeStrong when copying a block
(again, only at -O0), which requires us to do a preliminary
store of null in order to compensate for objc_storeStrong's
assign semantics.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166085 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenObjC/arc-arm.m b/test/CodeGenObjC/arc-arm.m
index 4c569da..2ab8cb6 100644
--- a/test/CodeGenObjC/arc-arm.m
+++ b/test/CodeGenObjC/arc-arm.m
@@ -13,8 +13,7 @@
   // CHECK-NEXT: call void asm sideeffect "mov\09r7, r7
   // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
   // CHECK-NEXT: store i8* [[T1]],
-  // CHECK-NEXT: load
-  // CHECK-NEXT: call void @objc_release
+  // CHECK-NEXT: call void @objc_storeStrong(
   // CHECK-NEXT: ret void
   id x = test1_helper();
 }
diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m
index cbdb494..38c88af 100644
--- a/test/CodeGenObjC/arc-blocks.m
+++ b/test/CodeGenObjC/arc-blocks.m
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-UNOPT %s
 
 // This shouldn't crash.
 void test0(id (^maker)(void)) {
@@ -41,6 +42,24 @@
 // CHECK-NEXT: ret void
   extern void test2_helper(id (^)(void));
   test2_helper(^{ return x; });
+
+// CHECK:    define internal void @__copy_helper_block_
+// CHECK:      [[T0:%.*]] = load i8**
+// CHECK-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
+// CHECK-NEXT: [[T0:%.*]] = load i8**
+// CHECK-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[SRC]], i32 0, i32 5
+// CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]]
+// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) nounwind
+// CHECK-NEXT: ret void
+
+// CHECK:    define internal void @__destroy_helper_block_
+// CHECK:      [[T0:%.*]] = load i8**
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
+// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 5
+// CHECK-NEXT: [[T3:%.*]] = load i8** [[T2]]
+// CHECK-NEXT: call void @objc_release(i8* [[T3]])
+// CHECK-NEXT: ret void
 }
 
 void test3(void (^sink)(id*)) {
@@ -359,7 +378,7 @@
 // CHECK:      [[T0:%.*]] = load i8** {{%.*}}
 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BYREF_T]]*
 // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T1]], i32 0, i32 6
-// CHECK-NEXT: [[T3:%.*]] = load void ()** [[T2]], align 8
+// CHECK-NEXT: [[T3:%.*]] = load void ()** [[T2]]
 // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
 // CHECK-NEXT: call void @objc_release(i8* [[T4]])
 // CHECK-NEXT: ret void
@@ -589,3 +608,42 @@
 // CHECK-NEXT: call void @objc_release(i8* [[T0]])
 // CHECK-NEXT: store i32
 // CHECK-NEXT: br label
+
+void test18(id x) {
+// CHECK-UNOPT:    define void @test18(
+// CHECK-UNOPT:      [[X:%.*]] = alloca i8*,
+// CHECK-UNOPT-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
+// CHECK-UNOPT-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
+// CHECK-UNOPT-NEXT: store i8* [[PARM]], i8** [[X]]
+// CHECK-UNOPT-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK-UNOPT:      [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8** [[X]],
+// CHECK-UNOPT-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+// CHECK-UNOPT-NEXT: store i8* [[T1]], i8** [[SLOT]],
+// CHECK-UNOPT-NEXT: bitcast
+// CHECK-UNOPT-NEXT: call void @test18_helper(
+// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[SLOTREL]], i8* null) nounwind
+// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null) nounwind
+// CHECK-UNOPT-NEXT: ret void
+  extern void test18_helper(id (^)(void));
+  test18_helper(^{ return x; });
+
+// CHECK-UNOPT:    define internal void @__copy_helper_block_
+// CHECK-UNOPT:      [[T0:%.*]] = load i8**
+// CHECK-UNOPT-NEXT: [[SRC:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
+// CHECK-UNOPT-NEXT: [[T0:%.*]] = load i8**
+// CHECK-UNOPT-NEXT: [[DST:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
+// CHECK-UNOPT-NEXT: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[SRC]], i32 0, i32 5
+// CHECK-UNOPT-NEXT: [[T1:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[DST]], i32 0, i32 5
+// CHECK-UNOPT-NEXT: [[T2:%.*]] = load i8** [[T0]]
+// CHECK-UNOPT-NEXT: store i8* null, i8** [[T1]]
+// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T1]], i8* [[T2]]) nounwind
+// CHECK-UNOPT-NEXT: ret void
+
+// CHECK-UNOPT:    define internal void @__destroy_helper_block_
+// CHECK-UNOPT:      [[T0:%.*]] = load i8**
+// CHECK-UNOPT-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BLOCK_T]]*
+// CHECK-UNOPT-NEXT: [[T2:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[T1]], i32 0, i32 5
+// CHECK-UNOPT-NEXT: call void @objc_storeStrong(i8** [[T2]], i8* null)
+// CHECK-UNOPT-NEXT: ret void
+}
diff --git a/test/CodeGenObjC/arc-exceptions.m b/test/CodeGenObjC/arc-exceptions.m
index 5ef5aba..63945e3 100644
--- a/test/CodeGenObjC/arc-exceptions.m
+++ b/test/CodeGenObjC/arc-exceptions.m
@@ -20,9 +20,8 @@
 // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind
 // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
 // CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
-// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]]
-// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) nounwind
 // CHECK-NEXT: call void @objc_end_catch() nounwind
 
 void test1_helper(void);
diff --git a/test/CodeGenObjC/arc-foreach.m b/test/CodeGenObjC/arc-foreach.m
index 67fad4d..b8d2d30 100644
--- a/test/CodeGenObjC/arc-foreach.m
+++ b/test/CodeGenObjC/arc-foreach.m
@@ -67,8 +67,7 @@
 // CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]]
 // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] 
 // CHECK-LP64: call void @use_block(
-// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[D0]]
-// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]])
+// CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[D0]], i8* null)
 
 // CHECK-LP64:      [[T0:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_
 // CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[SAVED_ARRAY]] to i8*
@@ -79,9 +78,8 @@
 // CHECK-LP64-NEXT: call void @objc_release(i8* [[T0]])
 
 // Destroy 'array'.
-// CHECK-LP64:      [[T0:%.*]] = load [[ARRAY_T]]** [[ARRAY]]
-// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[T0]] to i8*
-// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]])
+// CHECK-LP64:      [[T0:%.*]] = bitcast [[ARRAY_T]]** [[ARRAY]] to i8**
+// CHECK-LP64-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
 // CHECK-LP64-NEXT: ret void
 
 // CHECK-LP64:    define internal void @__test0_block_invoke
diff --git a/test/CodeGenObjC/arc-no-runtime.m b/test/CodeGenObjC/arc-no-runtime.m
index 3c85e87..f5f5b90 100644
--- a/test/CodeGenObjC/arc-no-runtime.m
+++ b/test/CodeGenObjC/arc-no-runtime.m
@@ -1,9 +1,13 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -emit-llvm %s -o - | FileCheck %s
 
 // rdar://problem/9224855
+id make(void) __attribute__((ns_returns_retained));
 void test0() {
+  make();
   id x = 0;
   // CHECK: call void @objc_release(
+  // CHECK: call void @objc_storeStrong(
 }
 
 // CHECK: declare extern_weak void @objc_release(
+// CHECK: declare extern_weak void @objc_storeStrong(
diff --git a/test/CodeGenObjC/arc-property.m b/test/CodeGenObjC/arc-property.m
index 68344b8..db00e36 100644
--- a/test/CodeGenObjC/arc-property.m
+++ b/test/CodeGenObjC/arc-property.m
@@ -11,8 +11,8 @@
 // CHECK: call i8* @objc_retain(
 // CHECK: call i8* @objc_retain(
 // CHECK: @objc_msgSend
-// CHECK: call void @objc_release(
-// CHECK: call void @objc_release(
+// CHECK: call void @objc_storeStrong(
+// CHECK: call void @objc_storeStrong(
 
 struct S1 { Class isa; };
 @interface Test1
diff --git a/test/CodeGenObjC/arc-related-result-type.m b/test/CodeGenObjC/arc-related-result-type.m
index f73aa50..ee0a41d 100644
--- a/test/CodeGenObjC/arc-related-result-type.m
+++ b/test/CodeGenObjC/arc-related-result-type.m
@@ -20,11 +20,9 @@
 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
 // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST0]]*
 // CHECK-NEXT: store [[TEST0]]* [[T2]], [[TEST0]]** [[X]]
-// CHECK-NEXT: [[T0:%.*]] = load [[TEST0]]** [[X]]
-// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST0]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]])
-// CHECK-NEXT: [[T0:%.*]] = load [[TEST0]]** [[VAL]]
-// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST0]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]])
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]** [[X]] to i8**
+// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]** [[VAL]] to i8**
+// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
 // CHECK-NEXT: ret void
 }
diff --git a/test/CodeGenObjC/objc-arc-container-subscripting.m b/test/CodeGenObjC/objc-arc-container-subscripting.m
index 8924916..71339c7 100644
--- a/test/CodeGenObjC/objc-arc-container-subscripting.m
+++ b/test/CodeGenObjC/objc-arc-container-subscripting.m
@@ -13,9 +13,8 @@
 
 // CHECK: [[call:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
 // CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) nounwind
-// CHECK: [[ARRAY:%.*]] = load %0** 
-// CHECK: [[ARRAY_CASTED:%.*]] = bitcast{{.*}}[[ARRAY]] to i8*
-// CHECK: call void @objc_release(i8* [[ARRAY_CASTED]])
+// CHECK: [[ARRAY_CASTED:%.*]] = bitcast %0** {{%.*}} to i8**
+// CHECK: call void @objc_storeStrong(i8** [[ARRAY_CASTED]], i8* null)
 // CHECK: [[EIGHT:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) nounwind
 // CHECK: ret i8* [[EIGHT]]
 
diff --git a/test/CodeGenObjCXX/arc-exceptions.mm b/test/CodeGenObjCXX/arc-exceptions.mm
index b1fa8ca..fb5300d 100644
--- a/test/CodeGenObjCXX/arc-exceptions.mm
+++ b/test/CodeGenObjCXX/arc-exceptions.mm
@@ -20,9 +20,8 @@
 // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind
 // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
 // CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
-// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]]
-// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) nounwind
 // CHECK-NEXT: call void @objc_end_catch() nounwind
 
 void test1_helper(void);
@@ -60,9 +59,8 @@
 // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind
 // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
 // CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
-// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]]
-// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null) nounwind
 // CHECK-NEXT: call void @__cxa_end_catch() nounwind
 
 void test3_helper(void);
diff --git a/test/CodeGenObjCXX/arc-new-delete.mm b/test/CodeGenObjCXX/arc-new-delete.mm
index a778bca..ce7eb3d 100644
--- a/test/CodeGenObjCXX/arc-new-delete.mm
+++ b/test/CodeGenObjCXX/arc-new-delete.mm
@@ -35,7 +35,7 @@
   // CHECK: call i8* @objc_initWeak
   new __weak id(invalue);
 
-  // CHECK: call void @objc_release
+  // CHECK: call void @objc_storeStrong
   // CHECK: ret void
 }
 
@@ -76,8 +76,7 @@
   // CHECK-NEXT: icmp eq i8** [[BEGIN]], [[END]]
   // CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]],
   // CHECK-NEXT: [[CUR]] = getelementptr inbounds i8** [[PAST]], i64 -1
-  // CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]]
-  // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+  // CHECK-NEXT: call void @objc_storeStrong(i8** [[CUR]], i8* null)
   // CHECK-NEXT: icmp eq i8** [[CUR]], [[BEGIN]]
   // CHECK: call void @_ZdaPv
   delete [] sptr;
diff --git a/test/CodeGenObjCXX/arc-special-member-functions.mm b/test/CodeGenObjCXX/arc-special-member-functions.mm
index 421a9fe..0b34538 100644
--- a/test/CodeGenObjCXX/arc-special-member-functions.mm
+++ b/test/CodeGenObjCXX/arc-special-member-functions.mm
@@ -111,7 +111,7 @@
 
 // Implicitly-generated destructor for ObjCBlockMember
 // CHECK: define linkonce_odr void @_ZN15ObjCBlockMemberD2Ev
-// CHECK: call void @objc_release(i8*
+// CHECK: call void @objc_storeStrong(i8*
 // CHECK: ret
 
 // Implicitly-generated default constructor for ObjCBlockMember
@@ -134,8 +134,7 @@
 // CHECK-NEXT: br label
 // CHECK:      [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
 // CHECK-NEXT: [[CUR]] = getelementptr inbounds i8** [[PAST]], i64 -1
-// CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]]
-// CHECK-NEXT: call void @objc_release(i8* [[T0]])
+// CHECK-NEXT: call void @objc_storeStrong(i8** [[CUR]], i8* null)
 // CHECK-NEXT: [[T1:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]]
 // CHECK-NEXT: br i1 [[T1]], 
 // CHECK:      ret void
@@ -154,7 +153,7 @@
 
 // Implicitly-generated destructor for ObjCMember
 // CHECK: define linkonce_odr void @_ZN10ObjCMemberD2Ev
-// CHECK: call void @objc_release
+// CHECK: call void @objc_storeStrong
 // CHECK: ret void
 
 // Implicitly-generated default constructor for ObjCMember