1; RUN: opt -basicaa -objc-arc -S < %s | FileCheck %s 2 3target datalayout = "e-p:64:64:64" 4 5declare i8* @objc_retain(i8*) 6declare i8* @objc_retainAutorelease(i8*) 7declare void @objc_release(i8*) 8declare i8* @objc_autorelease(i8*) 9 10declare void @clang.arc.use(...) 11 12declare 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*, 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*, 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: } 42define void @test0(i8** %out, i8* %x, i8* %y) { 43entry: 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*, 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*, 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*, 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*, 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: } 88define void @test0a(i8** %out, i8* %x, i8* %y) { 89entry: 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*, 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*, 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 = !{} 116 117