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: define void @bitcasttest 24 entry: 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) 35 ret void 36 } 37 38 define void @geptest(void (...)** %storage_array, void (...)* %block) { 39 ; CHECK: define void @geptest 40 entry: 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 (...)* 47 48 %storage = getelementptr inbounds void (...)** %storage_array, i64 0 49 50 store void (...)* %t4, void (...)** %storage, align 8 51 ; CHECK-NOT: call void @objc_release 52 call void @objc_release(i8* %t1) 53 ret void 54 } 55 56 define void @selecttest(void (...)** %store1, void (...)** %store2, 57 void (...)* %block) { 58 ; CHECK: define void @selecttest 59 entry: 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) 70 ret void 71 } 72 73 define void @phinodetest(void (...)** %storage1, 74 void (...)** %storage2, 75 void (...)* %block) { 76 ; CHECK: define void @phinodetest 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 br i1 undef, label %store1_set, label %store2_set 85 86 store1_set: 87 br label %end 88 89 store2_set: 90 br label %end 91 92 end: 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) 97 ret void 98 } 99 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 ; 104 ; bugpoint. ; 105 ; ; 106 ; bugzilla://14551 ; 107 ; rdar://12851911 ; 108 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 109 110 define void @phinode_use_cycle(i8* %block) uwtable optsize ssp { 111 ; CHECK: define void @phinode_use_cycle(i8* %block) 112 entry: 113 br label %for.body 114 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 118 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 124 br label %for.body 125 } 126 127 !0 = metadata !{} 128