diff options
author | John McCall <rjmccall@apple.com> | 2012-10-17 02:28:37 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2012-10-17 02:28:37 +0000 |
commit | 015f33b6741ffceba3a71ee2d71d46418a7dc34c (patch) | |
tree | fe2a0c3d3a8b66f0282ef93a379d5eca01f38a4b /test | |
parent | 5708c18904304ed4e39abed8131fcad5e2fc0896 (diff) |
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
Diffstat (limited to 'test')
-rw-r--r-- | test/CodeGenObjC/arc-arm.m | 3 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-blocks.m | 60 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-exceptions.m | 5 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-foreach.m | 8 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-no-runtime.m | 4 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-property.m | 4 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-related-result-type.m | 10 | ||||
-rw-r--r-- | test/CodeGenObjC/objc-arc-container-subscripting.m | 5 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-exceptions.mm | 10 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-new-delete.mm | 5 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-special-member-functions.mm | 7 |
11 files changed, 86 insertions, 35 deletions
diff --git a/test/CodeGenObjC/arc-arm.m b/test/CodeGenObjC/arc-arm.m index 4c569da114..2ab8cb6ef5 100644 --- a/test/CodeGenObjC/arc-arm.m +++ b/test/CodeGenObjC/arc-arm.m @@ -13,8 +13,7 @@ void test1(void) { // 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 cbdb49418b..38c88afb4d 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 @@ void test2(id x) { // 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 @@ void test10a(void) { // 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 @@ id (^test17(id self, int which))(void) { // 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 5ef5ababe6..63945e3a1b 100644 --- a/test/CodeGenObjC/arc-exceptions.m +++ b/test/CodeGenObjC/arc-exceptions.m @@ -20,9 +20,8 @@ void test0(void) { // 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 67fad4d9b0..b8d2d30ab4 100644 --- a/test/CodeGenObjC/arc-foreach.m +++ b/test/CodeGenObjC/arc-foreach.m @@ -67,8 +67,7 @@ void test0(NSArray *array) { // 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 @@ void test0(NSArray *array) { // 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 3c85e8783c..f5f5b90ea5 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 68344b83b0..db00e369cf 100644 --- a/test/CodeGenObjC/arc-property.m +++ b/test/CodeGenObjC/arc-property.m @@ -11,8 +11,8 @@ void test0(Test0 *t0, id value) { // 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 f73aa5049f..ee0a41dd00 100644 --- a/test/CodeGenObjC/arc-related-result-type.m +++ b/test/CodeGenObjC/arc-related-result-type.m @@ -20,11 +20,9 @@ void test0(Test0 *val) { // 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 892491630e..71339c7085 100644 --- a/test/CodeGenObjC/objc-arc-container-subscripting.m +++ b/test/CodeGenObjC/objc-arc-container-subscripting.m @@ -13,9 +13,8 @@ id func() { // 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 b1fa8ca240..fb5300d15e 100644 --- a/test/CodeGenObjCXX/arc-exceptions.mm +++ b/test/CodeGenObjCXX/arc-exceptions.mm @@ -20,9 +20,8 @@ void test0(void) { // 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 @@ void test2(void) { // 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 a778bcad8f..ce7eb3deb1 100644 --- a/test/CodeGenObjCXX/arc-new-delete.mm +++ b/test/CodeGenObjCXX/arc-new-delete.mm @@ -35,7 +35,7 @@ void test_new(id invalue) { // 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 @@ void test_array_delete(__strong id *sptr, __weak id *wptr) { // 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 421a9fedff..0b34538d13 100644 --- a/test/CodeGenObjCXX/arc-special-member-functions.mm +++ b/test/CodeGenObjCXX/arc-special-member-functions.mm @@ -111,7 +111,7 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) { // 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 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) { // 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 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) { // 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 |