1*9880d681SAndroid Build Coastguard Worker; RUN: opt -objc-arc-contract -S < %s | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Workertarget datalayout = "e-p:64:64:64" 4*9880d681SAndroid Build Coastguard Worker 5*9880d681SAndroid Build Coastguard Workerdeclare i8* @objc_retain(i8*) 6*9880d681SAndroid Build Coastguard Workerdeclare void @objc_release(i8*) 7*9880d681SAndroid Build Coastguard Workerdeclare i8* @objc_autorelease(i8*) 8*9880d681SAndroid Build Coastguard Workerdeclare i8* @objc_autoreleaseReturnValue(i8*) 9*9880d681SAndroid Build Coastguard Workerdeclare i8* @objc_retainAutoreleasedReturnValue(i8*) 10*9880d681SAndroid Build Coastguard Worker 11*9880d681SAndroid Build Coastguard Workerdeclare void @use_pointer(i8*) 12*9880d681SAndroid Build Coastguard Workerdeclare i8* @returner() 13*9880d681SAndroid Build Coastguard Workerdeclare void @callee() 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test0( 16*9880d681SAndroid Build Coastguard Worker; CHECK: call void @use_pointer(i8* %0) 17*9880d681SAndroid Build Coastguard Worker; CHECK: } 18*9880d681SAndroid Build Coastguard Workerdefine void @test0(i8* %x) nounwind { 19*9880d681SAndroid Build Coastguard Workerentry: 20*9880d681SAndroid Build Coastguard Worker %0 = call i8* @objc_retain(i8* %x) nounwind 21*9880d681SAndroid Build Coastguard Worker call void @use_pointer(i8* %x) 22*9880d681SAndroid Build Coastguard Worker ret void 23*9880d681SAndroid Build Coastguard Worker} 24*9880d681SAndroid Build Coastguard Worker 25*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test1( 26*9880d681SAndroid Build Coastguard Worker; CHECK: call void @use_pointer(i8* %0) 27*9880d681SAndroid Build Coastguard Worker; CHECK: } 28*9880d681SAndroid Build Coastguard Workerdefine void @test1(i8* %x) nounwind { 29*9880d681SAndroid Build Coastguard Workerentry: 30*9880d681SAndroid Build Coastguard Worker %0 = call i8* @objc_autorelease(i8* %x) nounwind 31*9880d681SAndroid Build Coastguard Worker call void @use_pointer(i8* %x) 32*9880d681SAndroid Build Coastguard Worker ret void 33*9880d681SAndroid Build Coastguard Worker} 34*9880d681SAndroid Build Coastguard Worker 35*9880d681SAndroid Build Coastguard Worker; Merge objc_retain and objc_autorelease into objc_retainAutorelease. 36*9880d681SAndroid Build Coastguard Worker 37*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test2( 38*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retainAutorelease(i8* %x) [[NUW:#[0-9]+]] 39*9880d681SAndroid Build Coastguard Worker; CHECK: } 40*9880d681SAndroid Build Coastguard Workerdefine void @test2(i8* %x) nounwind { 41*9880d681SAndroid Build Coastguard Workerentry: 42*9880d681SAndroid Build Coastguard Worker %0 = tail call i8* @objc_retain(i8* %x) nounwind 43*9880d681SAndroid Build Coastguard Worker call i8* @objc_autorelease(i8* %0) nounwind 44*9880d681SAndroid Build Coastguard Worker call void @use_pointer(i8* %x) 45*9880d681SAndroid Build Coastguard Worker ret void 46*9880d681SAndroid Build Coastguard Worker} 47*9880d681SAndroid Build Coastguard Worker 48*9880d681SAndroid Build Coastguard Worker; Same as test2 but the value is returned. Do an RV optimization. 49*9880d681SAndroid Build Coastguard Worker 50*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i8* @test2b( 51*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retainAutoreleaseReturnValue(i8* %x) [[NUW]] 52*9880d681SAndroid Build Coastguard Worker; CHECK: } 53*9880d681SAndroid Build Coastguard Workerdefine i8* @test2b(i8* %x) nounwind { 54*9880d681SAndroid Build Coastguard Workerentry: 55*9880d681SAndroid Build Coastguard Worker %0 = tail call i8* @objc_retain(i8* %x) nounwind 56*9880d681SAndroid Build Coastguard Worker tail call i8* @objc_autoreleaseReturnValue(i8* %0) nounwind 57*9880d681SAndroid Build Coastguard Worker ret i8* %x 58*9880d681SAndroid Build Coastguard Worker} 59*9880d681SAndroid Build Coastguard Worker 60*9880d681SAndroid Build Coastguard Worker; Merge a retain,autorelease pair around a call. 61*9880d681SAndroid Build Coastguard Worker 62*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test3( 63*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retainAutorelease(i8* %x) [[NUW]] 64*9880d681SAndroid Build Coastguard Worker; CHECK: @use_pointer(i8* %0) 65*9880d681SAndroid Build Coastguard Worker; CHECK: } 66*9880d681SAndroid Build Coastguard Workerdefine void @test3(i8* %x, i64 %n) { 67*9880d681SAndroid Build Coastguard Workerentry: 68*9880d681SAndroid Build Coastguard Worker tail call i8* @objc_retain(i8* %x) nounwind 69*9880d681SAndroid Build Coastguard Worker call void @use_pointer(i8* %x) 70*9880d681SAndroid Build Coastguard Worker call i8* @objc_autorelease(i8* %x) nounwind 71*9880d681SAndroid Build Coastguard Worker ret void 72*9880d681SAndroid Build Coastguard Worker} 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Worker; Trivial retain,autorelease pair with intervening call, but it's post-dominated 75*9880d681SAndroid Build Coastguard Worker; by another release. The retain and autorelease can be merged. 76*9880d681SAndroid Build Coastguard Worker 77*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test4( 78*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: entry: 79*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: @objc_retainAutorelease(i8* %x) [[NUW]] 80*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: @use_pointer 81*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: @objc_release 82*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret void 83*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: } 84*9880d681SAndroid Build Coastguard Workerdefine void @test4(i8* %x, i64 %n) { 85*9880d681SAndroid Build Coastguard Workerentry: 86*9880d681SAndroid Build Coastguard Worker tail call i8* @objc_retain(i8* %x) nounwind 87*9880d681SAndroid Build Coastguard Worker call void @use_pointer(i8* %x) 88*9880d681SAndroid Build Coastguard Worker call i8* @objc_autorelease(i8* %x) nounwind 89*9880d681SAndroid Build Coastguard Worker tail call void @objc_release(i8* %x) nounwind 90*9880d681SAndroid Build Coastguard Worker ret void 91*9880d681SAndroid Build Coastguard Worker} 92*9880d681SAndroid Build Coastguard Worker 93*9880d681SAndroid Build Coastguard Worker; Don't merge retain and autorelease if they're not control-equivalent. 94*9880d681SAndroid Build Coastguard Worker 95*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test5( 96*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]] 97*9880d681SAndroid Build Coastguard Worker; CHECK: true: 98*9880d681SAndroid Build Coastguard Worker; CHECK: call i8* @objc_autorelease(i8* %0) [[NUW]] 99*9880d681SAndroid Build Coastguard Worker; CHECK: } 100*9880d681SAndroid Build Coastguard Workerdefine void @test5(i8* %p, i1 %a) { 101*9880d681SAndroid Build Coastguard Workerentry: 102*9880d681SAndroid Build Coastguard Worker tail call i8* @objc_retain(i8* %p) nounwind 103*9880d681SAndroid Build Coastguard Worker br i1 %a, label %true, label %false 104*9880d681SAndroid Build Coastguard Worker 105*9880d681SAndroid Build Coastguard Workertrue: 106*9880d681SAndroid Build Coastguard Worker call i8* @objc_autorelease(i8* %p) nounwind 107*9880d681SAndroid Build Coastguard Worker call void @use_pointer(i8* %p) 108*9880d681SAndroid Build Coastguard Worker ret void 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Workerfalse: 111*9880d681SAndroid Build Coastguard Worker ret void 112*9880d681SAndroid Build Coastguard Worker} 113*9880d681SAndroid Build Coastguard Worker 114*9880d681SAndroid Build Coastguard Worker; Don't eliminate objc_retainAutoreleasedReturnValue by merging it into 115*9880d681SAndroid Build Coastguard Worker; an objc_autorelease. 116*9880d681SAndroid Build Coastguard Worker; TODO? Merge objc_retainAutoreleasedReturnValue and objc_autorelease into 117*9880d681SAndroid Build Coastguard Worker; objc_retainAutoreleasedReturnValueAutorelease and merge 118*9880d681SAndroid Build Coastguard Worker; objc_retainAutoreleasedReturnValue and objc_autoreleaseReturnValue 119*9880d681SAndroid Build Coastguard Worker; into objc_retainAutoreleasedReturnValueAutoreleaseReturnValue? 120*9880d681SAndroid Build Coastguard Worker; Those entrypoints don't exist yet though. 121*9880d681SAndroid Build Coastguard Worker 122*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i8* @test6( 123*9880d681SAndroid Build Coastguard Worker; CHECK: call i8* @objc_retainAutoreleasedReturnValue(i8* %p) [[NUW]] 124*9880d681SAndroid Build Coastguard Worker; CHECK: %t = tail call i8* @objc_autoreleaseReturnValue(i8* %1) [[NUW]] 125*9880d681SAndroid Build Coastguard Worker; CHECK: } 126*9880d681SAndroid Build Coastguard Workerdefine i8* @test6() { 127*9880d681SAndroid Build Coastguard Worker %p = call i8* @returner() 128*9880d681SAndroid Build Coastguard Worker tail call i8* @objc_retainAutoreleasedReturnValue(i8* %p) nounwind 129*9880d681SAndroid Build Coastguard Worker %t = tail call i8* @objc_autoreleaseReturnValue(i8* %p) nounwind 130*9880d681SAndroid Build Coastguard Worker call void @use_pointer(i8* %t) 131*9880d681SAndroid Build Coastguard Worker ret i8* %t 132*9880d681SAndroid Build Coastguard Worker} 133*9880d681SAndroid Build Coastguard Worker 134*9880d681SAndroid Build Coastguard Worker; Don't spoil the RV optimization. 135*9880d681SAndroid Build Coastguard Worker 136*9880d681SAndroid Build Coastguard Worker; CHECK: define i8* @test7(i8* %p) 137*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retain(i8* %p) 138*9880d681SAndroid Build Coastguard Worker; CHECK: call void @use_pointer(i8* %1) 139*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %1) 140*9880d681SAndroid Build Coastguard Worker; CHECK: ret i8* %2 141*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: } 142*9880d681SAndroid Build Coastguard Workerdefine i8* @test7(i8* %p) { 143*9880d681SAndroid Build Coastguard Worker %1 = tail call i8* @objc_retain(i8* %p) 144*9880d681SAndroid Build Coastguard Worker call void @use_pointer(i8* %p) 145*9880d681SAndroid Build Coastguard Worker %2 = tail call i8* @objc_autoreleaseReturnValue(i8* %p) 146*9880d681SAndroid Build Coastguard Worker ret i8* %p 147*9880d681SAndroid Build Coastguard Worker} 148*9880d681SAndroid Build Coastguard Worker 149*9880d681SAndroid Build Coastguard Worker; Do the return value substitution for PHI nodes too. 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define i8* @test8( 152*9880d681SAndroid Build Coastguard Worker; CHECK: %retval = phi i8* [ %p, %if.then ], [ null, %entry ] 153*9880d681SAndroid Build Coastguard Worker; CHECK: } 154*9880d681SAndroid Build Coastguard Workerdefine i8* @test8(i1 %x, i8* %c) { 155*9880d681SAndroid Build Coastguard Workerentry: 156*9880d681SAndroid Build Coastguard Worker br i1 %x, label %return, label %if.then 157*9880d681SAndroid Build Coastguard Worker 158*9880d681SAndroid Build Coastguard Workerif.then: ; preds = %entry 159*9880d681SAndroid Build Coastguard Worker %p = call i8* @objc_retain(i8* %c) nounwind 160*9880d681SAndroid Build Coastguard Worker br label %return 161*9880d681SAndroid Build Coastguard Worker 162*9880d681SAndroid Build Coastguard Workerreturn: ; preds = %if.then, %entry 163*9880d681SAndroid Build Coastguard Worker %retval = phi i8* [ %c, %if.then ], [ null, %entry ] 164*9880d681SAndroid Build Coastguard Worker ret i8* %retval 165*9880d681SAndroid Build Coastguard Worker} 166*9880d681SAndroid Build Coastguard Worker 167*9880d681SAndroid Build Coastguard Worker; Kill calls to @clang.arc.use(...) 168*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test9( 169*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: clang.arc.use 170*9880d681SAndroid Build Coastguard Worker; CHECK: } 171*9880d681SAndroid Build Coastguard Workerdefine void @test9(i8* %a, i8* %b) { 172*9880d681SAndroid Build Coastguard Worker call void (...) @clang.arc.use(i8* %a, i8* %b) nounwind 173*9880d681SAndroid Build Coastguard Worker ret void 174*9880d681SAndroid Build Coastguard Worker} 175*9880d681SAndroid Build Coastguard Worker 176*9880d681SAndroid Build Coastguard Worker 177*9880d681SAndroid Build Coastguard Worker; Turn objc_retain into objc_retainAutoreleasedReturnValue if its operand 178*9880d681SAndroid Build Coastguard Worker; is a return value. 179*9880d681SAndroid Build Coastguard Worker 180*9880d681SAndroid Build Coastguard Worker; CHECK: define void @test10() 181*9880d681SAndroid Build Coastguard Worker; CHECK: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %p) 182*9880d681SAndroid Build Coastguard Workerdefine void @test10() { 183*9880d681SAndroid Build Coastguard Worker %p = call i8* @returner() 184*9880d681SAndroid Build Coastguard Worker tail call i8* @objc_retain(i8* %p) nounwind 185*9880d681SAndroid Build Coastguard Worker ret void 186*9880d681SAndroid Build Coastguard Worker} 187*9880d681SAndroid Build Coastguard Worker 188*9880d681SAndroid Build Coastguard Worker; Convert objc_retain to objc_retainAutoreleasedReturnValue if its 189*9880d681SAndroid Build Coastguard Worker; argument is a return value. 190*9880d681SAndroid Build Coastguard Worker 191*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test11( 192*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %y = call i8* @returner() 193*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: tail call i8* @objc_retainAutoreleasedReturnValue(i8* %y) [[NUW]] 194*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret void 195*9880d681SAndroid Build Coastguard Workerdefine void @test11() { 196*9880d681SAndroid Build Coastguard Worker %y = call i8* @returner() 197*9880d681SAndroid Build Coastguard Worker tail call i8* @objc_retain(i8* %y) nounwind 198*9880d681SAndroid Build Coastguard Worker ret void 199*9880d681SAndroid Build Coastguard Worker} 200*9880d681SAndroid Build Coastguard Worker 201*9880d681SAndroid Build Coastguard Worker; Don't convert objc_retain to objc_retainAutoreleasedReturnValue if its 202*9880d681SAndroid Build Coastguard Worker; argument is not a return value. 203*9880d681SAndroid Build Coastguard Worker 204*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test12( 205*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: tail call i8* @objc_retain(i8* %y) [[NUW]] 206*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret void 207*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: } 208*9880d681SAndroid Build Coastguard Workerdefine void @test12(i8* %y) { 209*9880d681SAndroid Build Coastguard Worker tail call i8* @objc_retain(i8* %y) nounwind 210*9880d681SAndroid Build Coastguard Worker ret void 211*9880d681SAndroid Build Coastguard Worker} 212*9880d681SAndroid Build Coastguard Worker 213*9880d681SAndroid Build Coastguard Worker; Don't Convert objc_retain to objc_retainAutoreleasedReturnValue if it 214*9880d681SAndroid Build Coastguard Worker; isn't next to the call providing its return value. 215*9880d681SAndroid Build Coastguard Worker 216*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: define void @test13( 217*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: %y = call i8* @returner() 218*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: call void @callee() 219*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: tail call i8* @objc_retain(i8* %y) [[NUW]] 220*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret void 221*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: } 222*9880d681SAndroid Build Coastguard Workerdefine void @test13() { 223*9880d681SAndroid Build Coastguard Worker %y = call i8* @returner() 224*9880d681SAndroid Build Coastguard Worker call void @callee() 225*9880d681SAndroid Build Coastguard Worker tail call i8* @objc_retain(i8* %y) nounwind 226*9880d681SAndroid Build Coastguard Worker ret void 227*9880d681SAndroid Build Coastguard Worker} 228*9880d681SAndroid Build Coastguard Worker 229*9880d681SAndroid Build Coastguard Worker 230*9880d681SAndroid Build Coastguard Workerdeclare void @clang.arc.use(...) nounwind 231*9880d681SAndroid Build Coastguard Worker 232*9880d681SAndroid Build Coastguard Worker; CHECK: attributes [[NUW]] = { nounwind } 233