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