1 ; RUN: opt -objc-arc -S < %s | FileCheck %s 2 3 declare i8* @objc_release(i8* %x) 4 declare i8* @objc_retain(i8* %x) 5 declare i8* @objc_autorelease(i8* %x) 6 declare i8* @objc_autoreleaseReturnValue(i8* %x) 7 declare i8* @objc_retainAutoreleasedReturnValue(i8* %x) 8 9 ; Never tail call objc_autorelease. 10 define i8* @test0(i8* %x) { 11 entry: 12 ; CHECK: %tmp0 = call i8* @objc_autorelease(i8* %x) 13 %tmp0 = call i8* @objc_autorelease(i8* %x) 14 ; CHECK: %tmp1 = call i8* @objc_autorelease(i8* %x) 15 %tmp1 = tail call i8* @objc_autorelease(i8* %x) 16 17 ret i8* %x 18 } 19 20 ; Always tail call autoreleaseReturnValue. 21 define i8* @test1(i8* %x) { 22 entry: 23 ; CHECK: %tmp0 = tail call i8* @objc_autoreleaseReturnValue(i8* %x) 24 %tmp0 = call i8* @objc_autoreleaseReturnValue(i8* %x) 25 ; CHECK: %tmp1 = tail call i8* @objc_autoreleaseReturnValue(i8* %x) 26 %tmp1 = tail call i8* @objc_autoreleaseReturnValue(i8* %x) 27 ret i8* %x 28 } 29 30 ; Always tail call objc_retain. 31 define i8* @test2(i8* %x) { 32 entry: 33 ; CHECK: %tmp0 = tail call i8* @objc_retain(i8* %x) 34 %tmp0 = call i8* @objc_retain(i8* %x) 35 ; CHECK: %tmp1 = tail call i8* @objc_retain(i8* %x) 36 %tmp1 = tail call i8* @objc_retain(i8* %x) 37 ret i8* %x 38 } 39 40 define i8* @tmp(i8* %x) { 41 ret i8* %x 42 } 43 44 ; Always tail call objc_retainAutoreleasedReturnValue. 45 define i8* @test3(i8* %x) { 46 entry: 47 %y = call i8* @tmp(i8* %x) 48 ; CHECK: %tmp0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %y) 49 %tmp0 = call i8* @objc_retainAutoreleasedReturnValue(i8* %y) 50 %z = call i8* @tmp(i8* %x) 51 ; CHECK: %tmp1 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %z) 52 %tmp1 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %z) 53 ret i8* %x 54 } 55 56 ; By itself, we should never change whether or not objc_release is tail called. 57 define i8* @test4(i8* %x) { 58 entry: 59 ; CHECK: %tmp0 = call i8* @objc_release(i8* %x) 60 %tmp0 = call i8* @objc_release(i8* %x) 61 ; CHECK: %tmp1 = tail call i8* @objc_release(i8* %x) 62 %tmp1 = tail call i8* @objc_release(i8* %x) 63 ret i8* %x 64 } 65 66 ; If we convert a tail called @objc_autoreleaseReturnValue to an 67 ; @objc_autorelease, ensure that the tail call is removed. 68 define i8* @test5(i8* %x) { 69 entry: 70 ; CHECK: %tmp0 = call i8* @objc_autorelease(i8* %x) 71 %tmp0 = tail call i8* @objc_autoreleaseReturnValue(i8* %x) 72 ret i8* %tmp0 73 } 74 75 ; If we convert a called @objc_autorelease to an @objc_autoreleaseReturnValue, 76 ; ensure that the tail call is added. 77 define i8* @test6(i8* %x) { 78 entry: 79 ; CHECK: %tmp0 = tail call i8* @objc_retain(i8* %x) 80 %tmp0 = tail call i8* @objc_retain(i8* %x) 81 ; CHECK: %tmp1 = tail call i8* @objc_autoreleaseReturnValue(i8* %x) 82 %tmp1 = call i8* @objc_autorelease(i8* %x) 83 ret i8* %x 84 } 85