summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@apple.com>2017-04-28 18:50:57 +0000
committerAkira Hatanaka <ahatanaka@apple.com>2017-04-28 18:50:57 +0000
commita6b6dcc12384359b0e9a5843ec8e69ff3dc28009 (patch)
tree442e88773ef7214cc66949728e2c35031a589de4 /clang/test
parent6652a52e2b208ad593ff562667142affaec4a7df (diff)
downloadbcm5719-llvm-a6b6dcc12384359b0e9a5843ec8e69ff3dc28009.tar.gz
bcm5719-llvm-a6b6dcc12384359b0e9a5843ec8e69ff3dc28009.zip
[CodeGen][ObjC] Don't retain captured Objective-C pointers at block
creation that are const-qualified. When a block captures an ObjC object pointer, clang retains the pointer to prevent prematurely destroying the object the pointer points to before the block is called or copied. When the captured object pointer is const-qualified, we can avoid emitting the retain/release pair since the pointer variable cannot be modified in the scope in which the block literal is introduced. For example: void test(const id x) { callee(^{ (void)x; }); } This patch implements that optimization. rdar://problem/28894510 Differential Revision: https://reviews.llvm.org/D32601 llvm-svn: 301667
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CodeGenObjC/arc-blocks.m36
-rw-r--r--clang/test/CodeGenObjC/arc-foreach.m19
2 files changed, 37 insertions, 18 deletions
diff --git a/clang/test/CodeGenObjC/arc-blocks.m b/clang/test/CodeGenObjC/arc-blocks.m
index 4bb618c3a41..69cd7bb297b 100644
--- a/clang/test/CodeGenObjC/arc-blocks.m
+++ b/clang/test/CodeGenObjC/arc-blocks.m
@@ -298,15 +298,11 @@ void test7(void) {
// CHECK: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]*, [[TEST8]]** [[SELF]],
-// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
-// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
-// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST8]]*
-// CHECK-NEXT: store [[TEST8]]* [[T4]], [[TEST8]]** [[T0]]
+// CHECK-NEXT: store %0* [[T1]], %0** [[T0]]
// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to
// CHECK: call void @test8_helper(
-// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]*, [[TEST8]]** [[D0]]
-// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T2]])
+// CHECK-NEXT: [[T2:%.*]] = load [[TEST8]]*, [[TEST8]]** [[D0]]
+// CHECK-NEXT: call void (...) @clang.arc.use([[TEST8]]* [[T2]])
// CHECK: ret void
extern void test8_helper(void (^)(void));
@@ -741,5 +737,31 @@ void test19(void (^b)(void)) {
// CHECK-NEXT: ret void
}
+// CHECK-LABEL: define void @test20(
+// CHECK: [[XADDR:%.*]] = alloca i8*
+// CHECK-NEXT: [[BLOCK:%.*]] = alloca <[[BLOCKTY:.*]]>
+// CHECK-NEXT: [[RETAINEDX:%.*]] = call i8* @objc_retain(i8* %{{.*}})
+// CHECK-NEXT: store i8* [[RETAINEDX]], i8** [[XADDR]]
+// CHECK-NEXT: [[CAPTUREFIELD:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCK]], i32 0, i32 5
+// CHECK: [[BLOCKCAPTURED:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCK]], i32 0, i32 5
+// CHECK: [[CAPTURED:%.*]] = load i8*, i8** [[XADDR]]
+// CHECK: store i8* [[CAPTURED]], i8** [[BLOCKCAPTURED]]
+// CHECK: [[CAPTURE:%.*]] = load i8*, i8** [[CAPTUREFIELD]]
+// CHECK-NEXT: call void (...) @clang.arc.use(i8* [[CAPTURE]])
+// CHECK-NEXT: [[X:%.*]] = load i8*, i8** [[XADDR]]
+// CHECK-NEXT: call void @objc_release(i8* [[X]])
+// CHECK-NEXT: ret void
+
+// CHECK-LABEL: define internal void @__copy_helper_block
+// CHECK: [[BLOCKSOURCE:%.*]] = bitcast i8* %{{.*}} to <[[BLOCKTY]]>*
+// CHECK: [[CAPTUREFIELD:%.*]] = getelementptr inbounds <[[BLOCKTY]]>, <[[BLOCKTY]]>* [[BLOCKSOURCE]], i32 0, i32 5
+// CHECK: [[BLOCKCOPYSRC:%.*]] = load i8*, i8** [[CAPTUREFIELD]]
+// CHECK: call i8* @objc_retain(i8* [[BLOCKCOPYSRC]])
+
+void test20_callee(void (^)());
+void test20(const id x) {
+ test20_callee(^{ (void)x; });
+}
+
// CHECK: attributes [[NUW]] = { nounwind }
// CHECK-UNOPT: attributes [[NUW]] = { nounwind }
diff --git a/clang/test/CodeGenObjC/arc-foreach.m b/clang/test/CodeGenObjC/arc-foreach.m
index db150e88a59..e34445704e3 100644
--- a/clang/test/CodeGenObjC/arc-foreach.m
+++ b/clang/test/CodeGenObjC/arc-foreach.m
@@ -63,11 +63,11 @@ void test0(NSArray *array) {
// CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-LP64-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
-// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
-// 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: call void @objc_storeStrong(i8** [[D0]], i8* null)
+// CHECK-LP64-NEXT: store i8* [[T1]], i8** [[T0]]
+// CHECK-LP64-NEXT: [[BLOCK1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]]
+// CHECK-LP64-NEXT: call void @use_block(void ()* [[BLOCK1]])
+// CHECK-LP64-NEXT: [[CAPTURE:%.*]] = load i8*, i8** [[D0]]
+// CHECK-LP64: call void (...) @clang.arc.use(i8* [[CAPTURE]])
// CHECK-LP64: [[T0:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[SAVED_ARRAY]] to i8*
@@ -200,13 +200,10 @@ NSArray *array4;
// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>* [[BLOCK]], i32 0, i32 5
// CHECK-LP64: [[BC:%.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, [[TY]]* }>* [[BLOCK]], i32 0, i32 5
// CHECK-LP64: [[T1:%.*]] = load [[TY]]*, [[TY]]** [[SELF_ADDR]]
-// CHECK-LP64: [[T2:%.*]] = bitcast [[TY]]* [[T1]] to i8*
-// CHECK-LP64: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
-// CHECK-LP64: [[T4:%.*]] = bitcast i8* [[T3]] to [[TY]]*
-// CHECK-LP64: store [[TY]]* [[T4]], [[TY]]** [[BC]]
+// CHECK-LP64: store [[TY]]* [[T1]], [[TY]]** [[BC]]
-// CHECK-LP64: [[T5:%.*]] = bitcast [[TY]]** [[T0]] to i8**
-// CHECK-LP64: call void @objc_storeStrong(i8** [[T5]], i8* null)
+// CHECK-LP64: [[T5:%.*]] = load [[TY]]*, [[TY]]** [[T0]]
+// CHECK-LP64: call void (...) @clang.arc.use([[TY]]* [[T5]])
// CHECK-LP64: switch i32 {{%.*}}, label %[[UNREACHABLE:.*]] [
// CHECK-LP64-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
// CHECK-LP64-NEXT: i32 2, label %[[FORCOLL_END:.*]]
OpenPOWER on IntegriCloud