1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s 2 3 void test0(_Bool cond) { 4 id test0_helper(void) __attribute__((ns_returns_retained)); 5 6 // CHECK-LABEL: define void @test0( 7 // CHECK: [[COND:%.*]] = alloca i8, 8 // CHECK-NEXT: [[X:%.*]] = alloca i8*, 9 // CHECK-NEXT: [[RELVAL:%.*]] = alloca i8* 10 // CHECK-NEXT: [[RELCOND:%.*]] = alloca i1 11 // CHECK-NEXT: zext 12 // CHECK-NEXT: store 13 // CHECK-NEXT: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* 14 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]]) 15 // CHECK-NEXT: [[T0:%.*]] = load i8, i8* [[COND]] 16 // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1 17 // CHECK-NEXT: store i1 false, i1* [[RELCOND]] 18 // CHECK-NEXT: br i1 [[T1]], 19 // CHECK: br label 20 // CHECK: [[CALL:%.*]] = call i8* @test0_helper() 21 // CHECK-NEXT: store i8* [[CALL]], i8** [[RELVAL]] 22 // CHECK-NEXT: store i1 true, i1* [[RELCOND]] 23 // CHECK-NEXT: br label 24 // CHECK: [[T0:%.*]] = phi i8* [ null, {{%.*}} ], [ [[CALL]], {{%.*}} ] 25 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW:#[0-9]+]] 26 // CHECK-NEXT: store i8* [[T1]], i8** [[X]], 27 // CHECK-NEXT: [[REL:%.*]] = load i1, i1* [[RELCOND]] 28 // CHECK-NEXT: br i1 [[REL]], 29 // CHECK: [[T0:%.*]] = load i8*, i8** [[RELVAL]] 30 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] 31 // CHECK-NEXT: br label 32 // CHECK: [[T0:%.*]] = load i8*, i8** [[X]] 33 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]] 34 // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* 35 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]]) 36 // CHECK-NEXT: ret void 37 id x = (cond ? 0 : test0_helper()); 38 } 39 40 void test1(int cond) { 41 __strong id strong; 42 __weak id weak; 43 extern void test1_sink(id *); 44 test1_sink(cond ? &strong : 0); 45 test1_sink(cond ? &weak : 0); 46 47 // CHECK-LABEL: define void @test1( 48 // CHECK: [[COND:%.*]] = alloca i32 49 // CHECK-NEXT: [[STRONG:%.*]] = alloca i8* 50 // CHECK-NEXT: [[WEAK:%.*]] = alloca i8* 51 // CHECK-NEXT: [[TEMP1:%.*]] = alloca i8* 52 // CHECK-NEXT: [[TEMP2:%.*]] = alloca i8* 53 // CHECK-NEXT: [[CONDCLEANUPSAVE:%.*]] = alloca i8* 54 // CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1 55 // CHECK-NEXT: store i32 56 // CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8* 57 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]]) 58 // CHECK-NEXT: store i8* null, i8** [[STRONG]] 59 // CHECK-NEXT: [[WEAKPTR1:%.*]] = bitcast i8** [[WEAK]] to i8* 60 // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKPTR1]]) 61 // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null) 62 63 // CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]] 64 // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 65 // CHECK: [[ARG:%.*]] = phi i8** 66 // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null 67 // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP1]] 68 // CHECK-NEXT: br i1 [[T0]], 69 // CHECK: [[T0:%.*]] = load i8*, i8** [[ARG]] 70 // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP1]] 71 // CHECK-NEXT: br label 72 // CHECK: [[W:%.*]] = phi i8* [ [[T0]], {{%.*}} ], [ undef, {{%.*}} ] 73 // CHECK-NEXT: call void @test1_sink(i8** [[T1]]) 74 // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null 75 // CHECK-NEXT: br i1 [[T0]], 76 // CHECK: [[T0:%.*]] = load i8*, i8** [[TEMP1]] 77 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) 78 // CHECK-NEXT: call void (...) @clang.arc.use(i8* [[W]]) [[NUW]] 79 // CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[ARG]] 80 // CHECK-NEXT: store i8* [[T1]], i8** [[ARG]] 81 // CHECK-NEXT: call void @objc_release(i8* [[T2]]) 82 // CHECK-NEXT: br label 83 84 // CHECK: [[T0:%.*]] = load i32, i32* [[COND]] 85 // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 86 // CHECK: [[ARG:%.*]] = phi i8** 87 // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null 88 // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP2]] 89 // CHECK-NEXT: store i1 false, i1* [[CONDCLEANUP]] 90 // CHECK-NEXT: br i1 [[T0]], 91 // CHECK: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[ARG]]) 92 // CHECK-NEXT: store i8* [[T0]], i8** [[CONDCLEANUPSAVE]] 93 // CHECK-NEXT: store i1 true, i1* [[CONDCLEANUP]] 94 // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP2]] 95 // CHECK-NEXT: br label 96 // CHECK: call void @test1_sink(i8** [[T1]]) 97 // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null 98 // CHECK-NEXT: br i1 [[T0]], 99 // CHECK: [[T0:%.*]] = load i8*, i8** [[TEMP2]] 100 // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[ARG]], i8* [[T0]]) 101 // CHECK-NEXT: br label 102 103 // CHECK: call void @objc_destroyWeak(i8** [[WEAK]]) 104 // CHECK: [[WEAKPTR2:%.*]] = bitcast i8** [[WEAK]] to i8* 105 // CHECK: call void @llvm.lifetime.end(i64 8, i8* [[WEAKPTR2]]) 106 // CHECK: [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8* 107 // CHECK: call void @llvm.lifetime.end(i64 8, i8* [[STRONGPTR2]]) 108 // CHECK: ret void 109 } 110 111 // rdar://13113981 112 // Test that, when emitting an expression at +1 that we can't peephole, 113 // we emit the retain inside the full-expression. If we ever peephole 114 // +1s of conditional expressions (which we probably ought to), we'll 115 // need to find another example of something we need to do this for. 116 void test2(int cond) { 117 extern id test2_producer(void); 118 for (id obj in cond ? test2_producer() : (void*) 0) { 119 } 120 121 // CHECK-LABEL: define void @test2( 122 // CHECK: [[COND:%.*]] = alloca i32, 123 // CHECK: alloca i8* 124 // CHECK: [[CLEANUP_SAVE:%.*]] = alloca i8* 125 // CHECK: [[RUN_CLEANUP:%.*]] = alloca i1 126 // Evaluate condition; cleanup disabled by default. 127 // CHECK: [[T0:%.*]] = load i32, i32* [[COND]], 128 // CHECK-NEXT: icmp ne i32 [[T0]], 0 129 // CHECK-NEXT: store i1 false, i1* [[RUN_CLEANUP]] 130 // CHECK-NEXT: br i1 131 // Within true branch, cleanup enabled. 132 // CHECK: [[T0:%.*]] = call i8* @test2_producer() 133 // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) 134 // CHECK-NEXT: store i8* [[T1]], i8** [[CLEANUP_SAVE]] 135 // CHECK-NEXT: store i1 true, i1* [[RUN_CLEANUP]] 136 // CHECK-NEXT: br label 137 // Join point for conditional operator; retain immediately. 138 // CHECK: [[T0:%.*]] = phi i8* [ [[T1]], {{%.*}} ], [ null, {{%.*}} ] 139 // CHECK-NEXT: [[RESULT:%.*]] = call i8* @objc_retain(i8* [[T0]]) 140 // Leaving full-expression; run conditional cleanup. 141 // CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[RUN_CLEANUP]] 142 // CHECK-NEXT: br i1 [[T0]] 143 // CHECK: [[T0:%.*]] = load i8*, i8** [[CLEANUP_SAVE]] 144 // CHECK-NEXT: call void @objc_release(i8* [[T0]]) 145 // CHECK-NEXT: br label 146 // And way down at the end of the loop: 147 // CHECK: call void @objc_release(i8* [[RESULT]]) 148 } 149 150 // CHECK: attributes [[NUW]] = { nounwind } 151