blob: a852c4e4fbf6de5621572c7c0adbf57c1dadf3d4 [file] [log] [blame]
Dan Gohman00fa9632011-06-16 20:57:14 +00001; RUN: opt -S -objc-arc < %s | FileCheck %s
2
3declare i8* @objc_retain(i8*)
4declare void @objc_release(i8*)
Dan Gohman532fb812012-03-14 23:05:06 +00005declare i8* @objc_retainAutoreleasedReturnValue(i8*)
Dan Gohman00fa9632011-06-16 20:57:14 +00006declare i8* @objc_msgSend(i8*, i8*, ...)
7declare void @use_pointer(i8*)
8declare void @callee()
9
10; ARCOpt shouldn't try to move the releases to the block containing the invoke.
11
12; CHECK: define void @test0(
13; CHECK: invoke.cont:
14; CHECK: call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
15; CHECK: ret void
16; CHECK: lpad:
17; CHECK: call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
18; CHECK: ret void
19define void @test0(i8* %zipFile) {
20entry:
21 call i8* @objc_retain(i8* %zipFile) nounwind
22 call void @use_pointer(i8* %zipFile)
23 invoke void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*)*)(i8* %zipFile)
24 to label %invoke.cont unwind label %lpad
25
26invoke.cont: ; preds = %entry
27 call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
28 ret void
29
30lpad: ; preds = %entry
Bill Wendlinge6174a22011-08-31 21:04:11 +000031 %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
32 cleanup
Dan Gohman00fa9632011-06-16 20:57:14 +000033 call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
34 ret void
35}
36
37; ARCOpt should move the release before the callee calls.
38
39; CHECK: define void @test1(
40; CHECK: invoke.cont:
41; CHECK: call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
42; CHECK: call void @callee()
43; CHECK: br label %done
44; CHECK: lpad:
45; CHECK: call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
46; CHECK: call void @callee()
47; CHECK: br label %done
48; CHECK: done:
49; CHECK-NEXT: ret void
50define void @test1(i8* %zipFile) {
51entry:
52 call i8* @objc_retain(i8* %zipFile) nounwind
53 call void @use_pointer(i8* %zipFile)
54 invoke void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*)*)(i8* %zipFile)
55 to label %invoke.cont unwind label %lpad
56
57invoke.cont: ; preds = %entry
58 call void @callee()
59 br label %done
60
61lpad: ; preds = %entry
Bill Wendlinge6174a22011-08-31 21:04:11 +000062 %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
63 cleanup
Dan Gohman00fa9632011-06-16 20:57:14 +000064 call void @callee()
65 br label %done
66
67done:
68 call void @objc_release(i8* %zipFile) nounwind, !clang.imprecise_release !0
69 ret void
70}
71
Dan Gohman532fb812012-03-14 23:05:06 +000072; The optimizer should ignore invoke unwind paths consistently.
73; PR12265
74
75; CHECK: define void @test2() {
76; CHECK: invoke.cont:
77; CHECK-NEXT: call i8* @objc_retain
78; CHEK-NOT: @objc
79; CHECK: finally.cont:
80; CHECK-NEXT: call void @objc_release
81; CHEK-NOT: @objc
82; CHECK: finally.rethrow:
83; CHEK-NOT: @objc
84; CHECK: }
85define void @test2() {
86entry:
87 %call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* ()*)()
88 to label %invoke.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
89
90invoke.cont: ; preds = %entry
91 %tmp1 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call) nounwind
92 call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void ()*)(), !clang.arc.no_objc_arc_exceptions !0
93 invoke void @use_pointer(i8* %call)
94 to label %finally.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
95
96finally.cont: ; preds = %invoke.cont
97 tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0
98 ret void
99
100finally.rethrow: ; preds = %invoke.cont, %entry
101 %tmp2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
102 catch i8* null
103 unreachable
104}
105
Dan Gohman5c70fad2012-03-23 17:47:54 +0000106; Don't try to place code on invoke critical edges.
107
108; CHECK: define void @test3(
109; CHECK: if.end:
110; CHECK-NEXT: call void @objc_release(i8* %p) nounwind
111; CHECK-NEXT: ret void
112define void @test3(i8* %p, i1 %b) {
113entry:
114 %0 = call i8* @objc_retain(i8* %p)
115 call void @callee()
116 br i1 %b, label %if.else, label %if.then
117
118if.then:
119 invoke void @use_pointer(i8* %p)
120 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
121
122if.else:
123 invoke void @use_pointer(i8* %p)
124 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
125
126lpad:
127 %r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
128 cleanup
129 ret void
130
131if.end:
132 call void @objc_release(i8* %p)
133 ret void
134}
135
136; Like test3, but with ARC-relevant exception handling.
137
138; CHECK: define void @test4(
139; CHECK: lpad:
140; CHECK-NEXT: %r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
141; CHECK-NEXT: cleanup
142; CHECK-NEXT: call void @objc_release(i8* %p) nounwind
143; CHECK-NEXT: ret void
144; CHECK: if.end:
145; CHECK-NEXT: call void @objc_release(i8* %p) nounwind
146; CHECK-NEXT: ret void
147define void @test4(i8* %p, i1 %b) {
148entry:
149 %0 = call i8* @objc_retain(i8* %p)
150 call void @callee()
151 br i1 %b, label %if.else, label %if.then
152
153if.then:
154 invoke void @use_pointer(i8* %p)
155 to label %if.end unwind label %lpad
156
157if.else:
158 invoke void @use_pointer(i8* %p)
159 to label %if.end unwind label %lpad
160
161lpad:
162 %r = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
163 cleanup
164 call void @objc_release(i8* %p)
165 ret void
166
167if.end:
168 call void @objc_release(i8* %p)
169 ret void
170}
171
Bill Wendlinge6174a22011-08-31 21:04:11 +0000172declare i32 @__gxx_personality_v0(...)
Dan Gohman532fb812012-03-14 23:05:06 +0000173declare i32 @__objc_personality_v0(...)
Bill Wendlinge6174a22011-08-31 21:04:11 +0000174
Dan Gohman00fa9632011-06-16 20:57:14 +0000175!0 = metadata !{}