1// Make sure it works on x86-64. 2// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime=macosx-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=NOTAIL-CALL 3 4// Make sure it works on x86-32. 5// RUN: %clang_cc1 -triple i386-apple-darwin11 -fobjc-runtime=macosx-fragile-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL 6 7// Make sure it works on ARM. 8// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL 9// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED -check-prefix=CALL 10 11// Make sure it works on ARM64. 12// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL 13// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED -check-prefix=CALL 14 15// Make sure that it's implicitly disabled if the runtime version isn't high enough. 16// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=DISABLED 17// RUN: %clang_cc1 -triple arm64-apple-ios8 -fobjc-runtime=ios-8 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=DISABLED -check-prefix=DISABLED-MARKED 18 19@class A; 20 21A *makeA(void); 22 23void test_assign() { 24 __unsafe_unretained id x; 25 x = makeA(); 26} 27// CHECK-LABEL: define void @test_assign() 28// CHECK: [[X:%.*]] = alloca i8* 29// CHECK: [[T0:%.*]] = call [[A:.*]]* @makeA() 30// CHECK-MARKED-NEXT: call void asm sideeffect 31// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 32// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 33// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 34// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* 35// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* 36// CHECK-NEXT: store i8* [[T4]], i8** [[X]] 37// CHECK-OPTIMIZED-NEXT: bitcast 38// CHECK-OPTIMIZED-NEXT: lifetime.end 39// CHECK-NEXT: ret void 40 41// DISABLED-LABEL: define void @test_assign() 42// DISABLED: [[T0:%.*]] = call [[A:.*]]* @makeA() 43// DISABLED-MARKED-NEXT: call void asm sideeffect 44// DISABLED-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 45// DISABLED-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) 46 47void test_assign_assign() { 48 __unsafe_unretained id x, y; 49 x = y = makeA(); 50} 51// CHECK-LABEL: define void @test_assign_assign() 52// CHECK: [[X:%.*]] = alloca i8* 53// CHECK: [[Y:%.*]] = alloca i8* 54// CHECK: [[T0:%.*]] = call [[A]]* @makeA() 55// CHECK-MARKED-NEXT: call void asm sideeffect 56// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 57// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 58// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 59// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* 60// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* 61// CHECK-NEXT: store i8* [[T4]], i8** [[Y]] 62// CHECK-NEXT: store i8* [[T4]], i8** [[X]] 63// CHECK-OPTIMIZED-NEXT: bitcast 64// CHECK-OPTIMIZED-NEXT: lifetime.end 65// CHECK-OPTIMIZED-NEXT: bitcast 66// CHECK-OPTIMIZED-NEXT: lifetime.end 67// CHECK-NEXT: ret void 68 69void test_strong_assign_assign() { 70 __strong id x; 71 __unsafe_unretained id y; 72 x = y = makeA(); 73} 74// CHECK-LABEL: define void @test_strong_assign_assign() 75// CHECK: [[X:%.*]] = alloca i8* 76// CHECK: [[Y:%.*]] = alloca i8* 77// CHECK: [[T0:%.*]] = call [[A]]* @makeA() 78// CHECK-MARKED-NEXT: call void asm sideeffect 79// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 80// CHECK-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) 81// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* 82// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* 83// CHECK-NEXT: store i8* [[T4]], i8** [[Y]] 84// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[X]] 85// CHECK-NEXT: store i8* [[T4]], i8** [[X]] 86// CHECK-NEXT: call void @llvm.objc.release(i8* [[OLD]] 87// CHECK-OPTIMIZED-NEXT: bitcast 88// CHECK-OPTIMIZED-NEXT: lifetime.end 89// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null) 90// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[X]] 91// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]]) 92// CHECK-OPTIMIZED-NEXT: bitcast 93// CHECK-OPTIMIZED-NEXT: lifetime.end 94// CHECK-NEXT: ret void 95 96void test_assign_strong_assign() { 97 __unsafe_unretained id x; 98 __strong id y; 99 x = y = makeA(); 100} 101// CHECK-LABEL: define void @test_assign_strong_assign() 102// CHECK: [[X:%.*]] = alloca i8* 103// CHECK: [[Y:%.*]] = alloca i8* 104// CHECK: [[T0:%.*]] = call [[A]]* @makeA() 105// CHECK-MARKED-NEXT: call void asm sideeffect 106// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 107// CHECK-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) 108// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* 109// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* 110// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[Y]] 111// CHECK-NEXT: store i8* [[T4]], i8** [[Y]] 112// CHECK-NEXT: call void @llvm.objc.release(i8* [[OLD]] 113// CHECK-NEXT: store i8* [[T4]], i8** [[X]] 114// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[Y]], i8* null) 115// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] 116// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]]) 117// CHECK-OPTIMIZED-NEXT: bitcast 118// CHECK-OPTIMIZED-NEXT: lifetime.end 119// CHECK-OPTIMIZED-NEXT: bitcast 120// CHECK-OPTIMIZED-NEXT: lifetime.end 121// CHECK-NEXT: ret void 122 123void test_init() { 124 __unsafe_unretained id x = makeA(); 125} 126// CHECK-LABEL: define void @test_init() 127// CHECK: [[X:%.*]] = alloca i8* 128// CHECK: [[T0:%.*]] = call [[A]]* @makeA() 129// CHECK-MARKED-NEXT: call void asm sideeffect 130// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 131// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 132// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 133// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* 134// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* 135// CHECK-NEXT: store i8* [[T4]], i8** [[X]] 136// CHECK-OPTIMIZED-NEXT: bitcast 137// CHECK-OPTIMIZED-NEXT: lifetime.end 138// CHECK-NEXT: ret void 139 140void test_init_assignment() { 141 __unsafe_unretained id x; 142 __unsafe_unretained id y = x = makeA(); 143} 144// CHECK-LABEL: define void @test_init_assignment() 145// CHECK: [[X:%.*]] = alloca i8* 146// CHECK: [[Y:%.*]] = alloca i8* 147// CHECK: [[T0:%.*]] = call [[A]]* @makeA() 148// CHECK-MARKED-NEXT: call void asm sideeffect 149// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 150// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 151// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 152// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* 153// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* 154// CHECK-NEXT: store i8* [[T4]], i8** [[X]] 155// CHECK-NEXT: store i8* [[T4]], i8** [[Y]] 156// CHECK-OPTIMIZED-NEXT: bitcast 157// CHECK-OPTIMIZED-NEXT: lifetime.end 158// CHECK-OPTIMIZED-NEXT: bitcast 159// CHECK-OPTIMIZED-NEXT: lifetime.end 160// CHECK-NEXT: ret void 161 162void test_strong_init_assignment() { 163 __unsafe_unretained id x; 164 __strong id y = x = makeA(); 165} 166// CHECK-LABEL: define void @test_strong_init_assignment() 167// CHECK: [[X:%.*]] = alloca i8* 168// CHECK: [[Y:%.*]] = alloca i8* 169// CHECK: [[T0:%.*]] = call [[A]]* @makeA() 170// CHECK-MARKED-NEXT: call void asm sideeffect 171// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 172// CHECK-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) 173// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* 174// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* 175// CHECK-NEXT: store i8* [[T4]], i8** [[X]] 176// CHECK-NEXT: store i8* [[T4]], i8** [[Y]] 177// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[Y]], i8* null) 178// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] 179// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]]) 180// CHECK-OPTIMIZED-NEXT: bitcast 181// CHECK-OPTIMIZED-NEXT: lifetime.end 182// CHECK-OPTIMIZED-NEXT: bitcast 183// CHECK-OPTIMIZED-NEXT: lifetime.end 184// CHECK-NEXT: ret void 185 186void test_init_strong_assignment() { 187 __strong id x; 188 __unsafe_unretained id y = x = makeA(); 189} 190// CHECK-LABEL: define void @test_init_strong_assignment() 191// CHECK: [[X:%.*]] = alloca i8* 192// CHECK: [[Y:%.*]] = alloca i8* 193// CHECK: [[T0:%.*]] = call [[A]]* @makeA() 194// CHECK-MARKED-NEXT: call void asm sideeffect 195// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 196// CHECK-NEXT: [[T2:%.*]] = {{.*}}call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]]) 197// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* 198// CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* 199// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[X]] 200// CHECK-NEXT: store i8* [[T4]], i8** [[X]] 201// CHECK-NEXT: call void @llvm.objc.release(i8* [[OLD]]) 202// CHECK-NEXT: store i8* [[T4]], i8** [[Y]] 203// CHECK-OPTIMIZED-NEXT: bitcast 204// CHECK-OPTIMIZED-NEXT: lifetime.end 205// CHECK-UNOPTIMIZED-NEXT: call void @llvm.objc.storeStrong(i8** [[X]], i8* null) 206// CHECK-OPTIMIZED-NEXT: [[T0:%.*]] = load i8*, i8** [[X]] 207// CHECK-OPTIMIZED-NEXT: call void @llvm.objc.release(i8* [[T0]]) 208// CHECK-OPTIMIZED-NEXT: bitcast 209// CHECK-OPTIMIZED-NEXT: lifetime.end 210// CHECK-NEXT: ret void 211 212void test_ignored() { 213 makeA(); 214} 215// CHECK-LABEL: define void @test_ignored() 216// CHECK: [[T0:%.*]] = call [[A]]* @makeA() 217// CHECK-MARKED-NEXT: call void asm sideeffect 218// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 219// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 220// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 221// CHECK-NEXT: bitcast i8* [[T2]] to [[A]]* 222// CHECK-NEXT: ret void 223 224void test_cast_to_void() { 225 (void) makeA(); 226} 227// CHECK-LABEL: define void @test_cast_to_void() 228// CHECK: [[T0:%.*]] = call [[A]]* @makeA() 229// CHECK-MARKED-NEXT: call void asm sideeffect 230// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* 231// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 232// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) 233// CHECK-NEXT: bitcast i8* [[T2]] to [[A]]* 234// CHECK-NEXT: ret void 235 236 237 238// This is always at the end of the module. 239 240// CHECK-OPTIMIZED: !llvm.module.flags = !{!0, 241// CHECK-OPTIMIZED: !0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov{{.*}}marker for objc_retainAutoreleaseReturnValue"} 242