1 ; RUN: opt -S -objc-arc < %s | FileCheck %s
3 declare i8* @objc_retain(i8*) nonlazybind
4 declare void @objc_release(i8*) nonlazybind
5 declare i8* @objc_retainBlock(i8*)
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ; Use by an instruction which copies the value is an escape if the ;
9 ; result is an escape. The current instructions with this property are: ;
16 ; Make sure that such instructions do not confuse the optimizer into removing ;
17 ; an objc_retainBlock that is needed. ;
19 ; rdar://13273675. (With extra test cases to handle bitcast, phi, and select. ;
20 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22 define void @bitcasttest(i8* %storage, void (...)* %block) {
23 ; CHECK: define void @bitcasttest
25 %t1 = bitcast void (...)* %block to i8*
26 ; CHECK-NOT: tail call i8* @objc_retain
27 %t2 = tail call i8* @objc_retain(i8* %t1)
28 ; CHECK: tail call i8* @objc_retainBlock
29 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
30 %t4 = bitcast i8* %storage to void (...)**
31 %t5 = bitcast i8* %t3 to void (...)*
32 store void (...)* %t5, void (...)** %t4, align 8
33 ; CHECK-NOT: call void @objc_release
34 call void @objc_release(i8* %t1)
38 define void @geptest(void (...)** %storage_array, void (...)* %block) {
39 ; CHECK: define void @geptest
41 %t1 = bitcast void (...)* %block to i8*
42 ; CHECK-NOT: tail call i8* @objc_retain
43 %t2 = tail call i8* @objc_retain(i8* %t1)
44 ; CHECK: tail call i8* @objc_retainBlock
45 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
46 %t4 = bitcast i8* %t3 to void (...)*
48 %storage = getelementptr inbounds void (...)** %storage_array, i64 0
50 store void (...)* %t4, void (...)** %storage, align 8
51 ; CHECK-NOT: call void @objc_release
52 call void @objc_release(i8* %t1)
56 define void @selecttest(void (...)** %store1, void (...)** %store2,
58 ; CHECK: define void @selecttest
60 %t1 = bitcast void (...)* %block to i8*
61 ; CHECK-NOT: tail call i8* @objc_retain
62 %t2 = tail call i8* @objc_retain(i8* %t1)
63 ; CHECK: tail call i8* @objc_retainBlock
64 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
65 %t4 = bitcast i8* %t3 to void (...)*
66 %store = select i1 undef, void (...)** %store1, void (...)** %store2
67 store void (...)* %t4, void (...)** %store, align 8
68 ; CHECK-NOT: call void @objc_release
69 call void @objc_release(i8* %t1)
73 define void @phinodetest(void (...)** %storage1,
74 void (...)** %storage2,
76 ; CHECK: define void @phinodetest
78 %t1 = bitcast void (...)* %block to i8*
79 ; CHECK-NOT: tail call i8* @objc_retain
80 %t2 = tail call i8* @objc_retain(i8* %t1)
81 ; CHECK: tail call i8* @objc_retainBlock
82 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
83 %t4 = bitcast i8* %t3 to void (...)*
84 br i1 undef, label %store1_set, label %store2_set
93 %storage = phi void (...)** [ %storage1, %store1_set ], [ %storage2, %store2_set]
94 store void (...)* %t4, void (...)** %storage, align 8
95 ; CHECK-NOT: call void @objc_release
96 call void @objc_release(i8* %t1)
100 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
101 ; This test makes sure that we do not hang clang when visiting a use ;
102 ; cycle caused by phi nodes during objc-arc analysis. *NOTE* This ;
103 ; test case looks a little convoluted since it was produced by ;
108 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
110 define void @phinode_use_cycle(i8* %block) uwtable optsize ssp {
111 ; CHECK: define void @phinode_use_cycle(i8* %block)
115 for.body: ; preds = %if.then, %for.body, %entry
116 %block.05 = phi void (...)* [ null, %entry ], [ %1, %if.then ], [ %block.05, %for.body ]
117 br i1 undef, label %for.body, label %if.then
119 if.then: ; preds = %for.body
120 %0 = call i8* @objc_retainBlock(i8* %block), !clang.arc.copy_on_escape !0
121 %1 = bitcast i8* %0 to void (...)*
122 %2 = bitcast void (...)* %block.05 to i8*
123 call void @objc_release(i8* %2) nounwind, !clang.imprecise_release !0