1 ; RUN: opt -basicaa -objc-arc -S < %s | FileCheck %s 2 3 target datalayout = "e-p:64:64:64" 4 5 declare i8* @objc_retain(i8*) 6 declare i8* @objc_retainAutorelease(i8*) 7 declare void @objc_release(i8*) 8 declare i8* @objc_autorelease(i8*) 9 10 declare void @clang.arc.use(...) 11 12 declare void @test0_helper(i8*, i8**) 13 14 ; Ensure that we honor clang.arc.use as a use and don't miscompile 15 ; the reduced test case from <rdar://13195034>. 16 ; 17 ; FIXME: the fact that we re-order retains w.r.t. @clang.arc.use could 18 ; be problematic if we get run twice, e.g. under LTO. 19 ; 20 ; CHECK-LABEL: define void @test0( 21 ; CHECK: @objc_retain(i8* %x) 22 ; CHECK-NEXT: store i8* %y, i8** %temp0 23 ; CHECK-NEXT: @objc_retain(i8* %y) 24 ; CHECK-NEXT: call void @test0_helper 25 ; CHECK-NEXT: [[VAL1:%.*]] = load i8** %temp0 26 ; CHECK-NEXT: call void (...)* @clang.arc.use(i8* %y) 27 ; CHECK-NEXT: @objc_retain(i8* [[VAL1]]) 28 ; CHECK-NEXT: @objc_release(i8* %y) 29 ; CHECK-NEXT: store i8* [[VAL1]], i8** %temp1 30 ; CHECK-NEXT: call void @test0_helper 31 ; CHECK-NEXT: [[VAL2:%.*]] = load i8** %temp1 32 ; CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[VAL1]]) 33 ; CHECK-NEXT: @objc_retain(i8* [[VAL2]]) 34 ; CHECK-NEXT: @objc_release(i8* [[VAL1]]) 35 ; CHECK-NEXT: @objc_autorelease(i8* %x) 36 ; CHECK-NEXT: store i8* %x, i8** %out 37 ; CHECK-NEXT: @objc_retain(i8* %x) 38 ; CHECK-NEXT: @objc_release(i8* [[VAL2]]) 39 ; CHECK-NEXT: @objc_release(i8* %x) 40 ; CHECK-NEXT: ret void 41 ; CHECK-NEXT: } 42 define void @test0(i8** %out, i8* %x, i8* %y) { 43 entry: 44 %temp0 = alloca i8*, align 8 45 %temp1 = alloca i8*, align 8 46 %0 = call i8* @objc_retain(i8* %x) nounwind 47 %1 = call i8* @objc_retain(i8* %y) nounwind 48 store i8* %y, i8** %temp0 49 call void @test0_helper(i8* %x, i8** %temp0) 50 %val1 = load i8** %temp0 51 %2 = call i8* @objc_retain(i8* %val1) nounwind 52 call void (...)* @clang.arc.use(i8* %y) nounwind 53 call void @objc_release(i8* %y) nounwind 54 store i8* %val1, i8** %temp1 55 call void @test0_helper(i8* %x, i8** %temp1) 56 %val2 = load i8** %temp1 57 %3 = call i8* @objc_retain(i8* %val2) nounwind 58 call void (...)* @clang.arc.use(i8* %val1) nounwind 59 call void @objc_release(i8* %val1) nounwind 60 %4 = call i8* @objc_retain(i8* %x) nounwind 61 %5 = call i8* @objc_autorelease(i8* %x) nounwind 62 store i8* %x, i8** %out 63 call void @objc_release(i8* %val2) nounwind 64 call void @objc_release(i8* %x) nounwind 65 ret void 66 } 67 68 ; CHECK-LABEL: define void @test0a( 69 ; CHECK: @objc_retain(i8* %x) 70 ; CHECK-NEXT: store i8* %y, i8** %temp0 71 ; CHECK-NEXT: @objc_retain(i8* %y) 72 ; CHECK-NEXT: call void @test0_helper 73 ; CHECK-NEXT: [[VAL1:%.*]] = load i8** %temp0 74 ; CHECK-NEXT: call void (...)* @clang.arc.use(i8* %y) 75 ; CHECK-NEXT: @objc_retain(i8* [[VAL1]]) 76 ; CHECK-NEXT: @objc_release(i8* %y) 77 ; CHECK-NEXT: store i8* [[VAL1]], i8** %temp1 78 ; CHECK-NEXT: call void @test0_helper 79 ; CHECK-NEXT: [[VAL2:%.*]] = load i8** %temp1 80 ; CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[VAL1]]) 81 ; CHECK-NEXT: @objc_retain(i8* [[VAL2]]) 82 ; CHECK-NEXT: @objc_release(i8* [[VAL1]]) 83 ; CHECK-NEXT: @objc_autorelease(i8* %x) 84 ; CHECK-NEXT: @objc_release(i8* [[VAL2]]) 85 ; CHECK-NEXT: store i8* %x, i8** %out 86 ; CHECK-NEXT: ret void 87 ; CHECK-NEXT: } 88 define void @test0a(i8** %out, i8* %x, i8* %y) { 89 entry: 90 %temp0 = alloca i8*, align 8 91 %temp1 = alloca i8*, align 8 92 %0 = call i8* @objc_retain(i8* %x) nounwind 93 %1 = call i8* @objc_retain(i8* %y) nounwind 94 store i8* %y, i8** %temp0 95 call void @test0_helper(i8* %x, i8** %temp0) 96 %val1 = load i8** %temp0 97 %2 = call i8* @objc_retain(i8* %val1) nounwind 98 call void (...)* @clang.arc.use(i8* %y) nounwind 99 call void @objc_release(i8* %y) nounwind, !clang.imprecise_release !0 100 store i8* %val1, i8** %temp1 101 call void @test0_helper(i8* %x, i8** %temp1) 102 %val2 = load i8** %temp1 103 %3 = call i8* @objc_retain(i8* %val2) nounwind 104 call void (...)* @clang.arc.use(i8* %val1) nounwind 105 call void @objc_release(i8* %val1) nounwind, !clang.imprecise_release !0 106 %4 = call i8* @objc_retain(i8* %x) nounwind 107 %5 = call i8* @objc_autorelease(i8* %x) nounwind 108 store i8* %x, i8** %out 109 call void @objc_release(i8* %val2) nounwind, !clang.imprecise_release !0 110 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 111 ret void 112 } 113 114 115 !0 = metadata !{} 116 117