[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / test / Transforms / ObjCARC / invoke.ll
blob3dc95cd2eb0b60314b3e5c0d0e86aa7f0a4a360b
1 ; RUN: opt -S -objc-arc < %s | FileCheck %s
3 declare i8* @llvm.objc.retain(i8*)
4 declare void @llvm.objc.release(i8*)
5 declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
6 declare i8* @llvm.objc.msgSend(i8*, i8*, ...)
7 declare void @use_pointer(i8*)
8 declare void @callee()
9 declare i8* @returner()
11 ; ARCOpt shouldn't try to move the releases to the block containing the invoke.
13 ; CHECK-LABEL: define void @test0(
14 ; CHECK: invoke.cont:
15 ; CHECK:   call void @llvm.objc.release(i8* %zipFile) [[NUW:#[0-9]+]], !clang.imprecise_release !0
16 ; CHECK:   ret void
17 ; CHECK: lpad:
18 ; CHECK:   call void @llvm.objc.release(i8* %zipFile) [[NUW]], !clang.imprecise_release !0
19 ; CHECK:   ret void
20 ; CHECK-NEXT: }
21 define void @test0(i8* %zipFile) personality i32 (...)* @__gxx_personality_v0 {
22 entry:
23   call i8* @llvm.objc.retain(i8* %zipFile) nounwind
24   call void @use_pointer(i8* %zipFile)
25   invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*)*)(i8* %zipFile) 
26           to label %invoke.cont unwind label %lpad
28 invoke.cont:                                      ; preds = %entry
29   call void @llvm.objc.release(i8* %zipFile) nounwind, !clang.imprecise_release !0
30   ret void
32 lpad:                                             ; preds = %entry
33   %exn = landingpad {i8*, i32}
34            cleanup
35   call void @llvm.objc.release(i8* %zipFile) nounwind, !clang.imprecise_release !0
36   ret void
39 ; ARCOpt should move the release before the callee calls.
41 ; CHECK-LABEL: define void @test1(
42 ; CHECK: invoke.cont:
43 ; CHECK:   call void @llvm.objc.release(i8* %zipFile) [[NUW]], !clang.imprecise_release !0
44 ; CHECK:   call void @callee()
45 ; CHECK:   br label %done
46 ; CHECK: lpad:
47 ; CHECK:   call void @llvm.objc.release(i8* %zipFile) [[NUW]], !clang.imprecise_release !0
48 ; CHECK:   call void @callee()
49 ; CHECK:   br label %done
50 ; CHECK: done:
51 ; CHECK-NEXT: ret void
52 ; CHECK-NEXT: }
53 define void @test1(i8* %zipFile) personality i32 (...)* @__gxx_personality_v0 {
54 entry:
55   call i8* @llvm.objc.retain(i8* %zipFile) nounwind
56   call void @use_pointer(i8* %zipFile)
57   invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*)*)(i8* %zipFile)
58           to label %invoke.cont unwind label %lpad
60 invoke.cont:                                      ; preds = %entry
61   call void @callee()
62   br label %done
64 lpad:                                             ; preds = %entry
65   %exn = landingpad {i8*, i32}
66            cleanup
67   call void @callee()
68   br label %done
70 done:
71   call void @llvm.objc.release(i8* %zipFile) nounwind, !clang.imprecise_release !0
72   ret void
75 ; The optimizer should ignore invoke unwind paths consistently.
76 ; PR12265
78 ; CHECK: define void @test2() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
79 ; CHECK: invoke.cont:
80 ; CHECK-NEXT: call i8* @llvm.objc.retain
81 ; CHECK-NOT: @llvm.objc.r
82 ; CHECK: finally.cont:
83 ; CHECK-NEXT: call void @llvm.objc.release
84 ; CHECK-NOT: @objc
85 ; CHECK: finally.rethrow:
86 ; CHECK-NOT: @objc
87 ; CHECK: }
88 define void @test2() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
89 entry:
90   %call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* ()*)()
91           to label %invoke.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
93 invoke.cont:                                      ; preds = %entry
94   %tmp1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
95   call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void ()*)(), !clang.arc.no_objc_arc_exceptions !0
96   invoke void @use_pointer(i8* %call)
97           to label %finally.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
99 finally.cont:                                     ; preds = %invoke.cont
100   tail call void @llvm.objc.release(i8* %call) nounwind, !clang.imprecise_release !0
101   ret void
103 finally.rethrow:                                  ; preds = %invoke.cont, %entry
104   %tmp2 = landingpad { i8*, i32 }
105           catch i8* null
106   unreachable
109 ; Don't try to place code on invoke critical edges.
111 ; CHECK-LABEL: define void @test3(
112 ; CHECK: if.end:
113 ; CHECK-NEXT: call void @llvm.objc.release(i8* %p) [[NUW]]
114 ; CHECK-NEXT: ret void
115 ; CHECK-NEXT: }
116 define void @test3(i8* %p, i1 %b) personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
117 entry:
118   %0 = call i8* @llvm.objc.retain(i8* %p)
119   call void @callee()
120   br i1 %b, label %if.else, label %if.then
122 if.then:
123   invoke void @use_pointer(i8* %p)
124           to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
126 if.else:
127   invoke void @use_pointer(i8* %p)
128           to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
130 lpad:
131   %r = landingpad { i8*, i32 }
132        cleanup
133   ret void
135 if.end:
136   call void @llvm.objc.release(i8* %p)
137   ret void
140 ; Like test3, but with ARC-relevant exception handling.
142 ; CHECK-LABEL: define void @test4(
143 ; CHECK: lpad:
144 ; CHECK-NEXT: %r = landingpad { i8*, i32 }
145 ; CHECK-NEXT: cleanup
146 ; CHECK-NEXT: call void @llvm.objc.release(i8* %p) [[NUW]]
147 ; CHECK-NEXT: ret void
148 ; CHECK: if.end:
149 ; CHECK-NEXT: call void @llvm.objc.release(i8* %p) [[NUW]]
150 ; CHECK-NEXT: ret void
151 ; CHECK-NEXT: }
152 define void @test4(i8* %p, i1 %b) personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
153 entry:
154   %0 = call i8* @llvm.objc.retain(i8* %p)
155   call void @callee()
156   br i1 %b, label %if.else, label %if.then
158 if.then:
159   invoke void @use_pointer(i8* %p)
160           to label %if.end unwind label %lpad
162 if.else:
163   invoke void @use_pointer(i8* %p)
164           to label %if.end unwind label %lpad
166 lpad:
167   %r = landingpad { i8*, i32 }
168        cleanup
169   call void @llvm.objc.release(i8* %p)
170   ret void
172 if.end:
173   call void @llvm.objc.release(i8* %p)
174   ret void
177 ; Don't turn the retainAutoreleaseReturnValue into retain, because it's
178 ; for an invoke which we can assume codegen will put immediately prior.
180 ; CHECK-LABEL: define void @test5(
181 ; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z)
182 ; CHECK: }
183 define void @test5() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
184 entry:
185   %z = invoke i8* @returner()
186           to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
188 lpad:
189   %r13 = landingpad { i8*, i32 }
190           cleanup
191   ret void
193 if.end:
194   call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z)
195   ret void
198 ; Like test5, but there's intervening code.
200 ; CHECK-LABEL: define void @test6(
201 ; CHECK: call i8* @llvm.objc.retain(i8* %z)
202 ; CHECK: }
203 define void @test6() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
204 entry:
205   %z = invoke i8* @returner()
206           to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
208 lpad:
209   %r13 = landingpad { i8*, i32 }
210           cleanup
211   ret void
213 if.end:
214   call void @callee()
215   call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z)
216   ret void
219 declare i32 @__gxx_personality_v0(...)
220 declare i32 @__objc_personality_v0(...)
222 ; CHECK: attributes [[NUW]] = { nounwind }
224 !0 = !{}