1 ; RUN: opt -S -objc-arc < %s | FileCheck %s 2 3 declare i8* @objc_retain(i8*) nonlazybind 4 declare void @objc_release(i8*) nonlazybind 5 declare i8* @objc_retainBlock(i8*) 6 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: ; 10 ; ; 11 ; 1. BitCast. ; 12 ; 2. GEP. ; 13 ; 3. PhiNode. ; 14 ; 4. SelectInst. ; 15 ; ; 16 ; Make sure that such instructions do not confuse the optimizer into removing ; 17 ; an objc_retainBlock that is needed. ; 18 ; ; 19 ; rdar://13273675. (With extra test cases to handle bitcast, phi, and select. ; 20 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21 22 define void @bitcasttest(i8* %storage, void (...)* %block) { 23 ; CHECK-LABEL: define void @bitcasttest( 24 entry: 25 %t1 = bitcast void (...)* %block to i8* 26 ; CHECK: 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: call void @objc_release 34 call void @objc_release(i8* %t1) 35 ret void 36 ; CHECK: } 37 } 38 39 define void @bitcasttest_a(i8* %storage, void (...)* %block) { 40 ; CHECK-LABEL: define void @bitcasttest_a( 41 entry: 42 %t1 = bitcast void (...)* %block to i8* 43 ; CHECK-NOT: tail call i8* @objc_retain 44 %t2 = tail call i8* @objc_retain(i8* %t1) 45 ; CHECK: tail call i8* @objc_retainBlock 46 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0 47 %t4 = bitcast i8* %storage to void (...)** 48 %t5 = bitcast i8* %t3 to void (...)* 49 store void (...)* %t5, void (...)** %t4, align 8 50 ; CHECK-NOT: call void @objc_release 51 call void @objc_release(i8* %t1), !clang.imprecise_release !0 52 ret void 53 ; CHECK: } 54 } 55 56 define void @geptest(void (...)** %storage_array, void (...)* %block) { 57 ; CHECK-LABEL: define void @geptest( 58 entry: 59 %t1 = bitcast void (...)* %block to i8* 60 ; CHECK: tail call i8* @objc_retain 61 %t2 = tail call i8* @objc_retain(i8* %t1) 62 ; CHECK: tail call i8* @objc_retainBlock 63 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0 64 %t4 = bitcast i8* %t3 to void (...)* 65 66 %storage = getelementptr inbounds void (...)** %storage_array, i64 0 67 68 store void (...)* %t4, void (...)** %storage, align 8 69 ; CHECK: call void @objc_release 70 call void @objc_release(i8* %t1) 71 ret void 72 ; CHECK: } 73 } 74 75 define void @geptest_a(void (...)** %storage_array, void (...)* %block) { 76 ; CHECK-LABEL: define void @geptest_a( 77 entry: 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 85 %storage = getelementptr inbounds void (...)** %storage_array, i64 0 86 87 store void (...)* %t4, void (...)** %storage, align 8 88 ; CHECK-NOT: call void @objc_release 89 call void @objc_release(i8* %t1), !clang.imprecise_release !0 90 ret void 91 ; CHECK: } 92 } 93 94 define void @selecttest(void (...)** %store1, void (...)** %store2, 95 void (...)* %block) { 96 ; CHECK-LABEL: define void @selecttest( 97 entry: 98 %t1 = bitcast void (...)* %block to i8* 99 ; CHECK: tail call i8* @objc_retain 100 %t2 = tail call i8* @objc_retain(i8* %t1) 101 ; CHECK: tail call i8* @objc_retainBlock 102 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0 103 %t4 = bitcast i8* %t3 to void (...)* 104 %store = select i1 undef, void (...)** %store1, void (...)** %store2 105 store void (...)* %t4, void (...)** %store, align 8 106 ; CHECK: call void @objc_release 107 call void @objc_release(i8* %t1) 108 ret void 109 ; CHECK: } 110 } 111 112 define void @selecttest_a(void (...)** %store1, void (...)** %store2, 113 void (...)* %block) { 114 ; CHECK-LABEL: define void @selecttest_a( 115 entry: 116 %t1 = bitcast void (...)* %block to i8* 117 ; CHECK-NOT: tail call i8* @objc_retain 118 %t2 = tail call i8* @objc_retain(i8* %t1) 119 ; CHECK: tail call i8* @objc_retainBlock 120 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0 121 %t4 = bitcast i8* %t3 to void (...)* 122 %store = select i1 undef, void (...)** %store1, void (...)** %store2 123 store void (...)* %t4, void (...)** %store, align 8 124 ; CHECK-NOT: call void @objc_release 125 call void @objc_release(i8* %t1), !clang.imprecise_release !0 126 ret void 127 ; CHECK: } 128 } 129 130 define void @phinodetest(void (...)** %storage1, 131 void (...)** %storage2, 132 void (...)* %block) { 133 ; CHECK-LABEL: define void @phinodetest( 134 entry: 135 %t1 = bitcast void (...)* %block to i8* 136 ; CHECK: tail call i8* @objc_retain 137 %t2 = tail call i8* @objc_retain(i8* %t1) 138 ; CHECK: tail call i8* @objc_retainBlock 139 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0 140 %t4 = bitcast i8* %t3 to void (...)* 141 br i1 undef, label %store1_set, label %store2_set 142 ; CHECK: store1_set: 143 144 store1_set: 145 br label %end 146 147 store2_set: 148 br label %end 149 150 end: 151 ; CHECK: end: 152 %storage = phi void (...)** [ %storage1, %store1_set ], [ %storage2, %store2_set] 153 store void (...)* %t4, void (...)** %storage, align 8 154 ; CHECK: call void @objc_release 155 call void @objc_release(i8* %t1) 156 ret void 157 ; CHECK: } 158 } 159 160 define void @phinodetest_a(void (...)** %storage1, 161 void (...)** %storage2, 162 void (...)* %block) { 163 ; CHECK-LABEL: define void @phinodetest_a( 164 entry: 165 %t1 = bitcast void (...)* %block to i8* 166 ; CHECK-NOT: tail call i8* @objc_retain 167 %t2 = tail call i8* @objc_retain(i8* %t1) 168 ; CHECK: tail call i8* @objc_retainBlock 169 %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0 170 %t4 = bitcast i8* %t3 to void (...)* 171 br i1 undef, label %store1_set, label %store2_set 172 173 store1_set: 174 br label %end 175 176 store2_set: 177 br label %end 178 179 end: 180 %storage = phi void (...)** [ %storage1, %store1_set ], [ %storage2, %store2_set] 181 store void (...)* %t4, void (...)** %storage, align 8 182 ; CHECK-NOT: call void @objc_release 183 call void @objc_release(i8* %t1), !clang.imprecise_release !0 184 ret void 185 } 186 187 188 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 189 ; This test makes sure that we do not hang clang when visiting a use ; 190 ; cycle caused by phi nodes during objc-arc analysis. *NOTE* This ; 191 ; test case looks a little convoluted since it was produced by ; 192 ; bugpoint. ; 193 ; ; 194 ; bugzilla://14551 ; 195 ; rdar://12851911 ; 196 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 197 198 define void @phinode_use_cycle(i8* %block) uwtable optsize ssp { 199 ; CHECK: define void @phinode_use_cycle(i8* %block) 200 entry: 201 br label %for.body 202 203 for.body: ; preds = %if.then, %for.body, %entry 204 %block.05 = phi void (...)* [ null, %entry ], [ %1, %if.then ], [ %block.05, %for.body ] 205 br i1 undef, label %for.body, label %if.then 206 207 if.then: ; preds = %for.body 208 %0 = call i8* @objc_retainBlock(i8* %block), !clang.arc.copy_on_escape !0 209 %1 = bitcast i8* %0 to void (...)* 210 %2 = bitcast void (...)* %block.05 to i8* 211 call void @objc_release(i8* %2) nounwind, !clang.imprecise_release !0 212 br label %for.body 213 } 214 215 !0 = metadata !{} 216