xref: /llvm-project/llvm/test/Transforms/FunctionAttrs/nounwind.ll (revision 400fde92963588ae2b618626cb1ac73fd91c7d4d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
2; RUN: opt -passes=function-attrs -S < %s | FileCheck --check-prefixes=COMMON,FNATTRS %s
3; RUN: opt -passes=attributor-light -S < %s | FileCheck --check-prefixes=COMMON,ATTRIBUTOR %s
4
5; TEST 1
6define i32 @foo1() {
7; COMMON: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
8; COMMON-LABEL: define {{[^@]+}}@foo1
9; COMMON-SAME: () #[[ATTR0:[0-9]+]] {
10; COMMON-NEXT:    ret i32 1
11;
12  ret i32 1
13}
14
15; TEST 2
16define i32 @scc1_foo() {
17; FNATTRS: Function Attrs: nofree nosync nounwind memory(none)
18; FNATTRS-LABEL: define {{[^@]+}}@scc1_foo
19; FNATTRS-SAME: () #[[ATTR1:[0-9]+]] {
20; FNATTRS-NEXT:    [[TMP1:%.*]] = call i32 @scc1_bar()
21; FNATTRS-NEXT:    ret i32 1
22;
23; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none)
24; ATTRIBUTOR-LABEL: define {{[^@]+}}@scc1_foo
25; ATTRIBUTOR-SAME: () #[[ATTR1:[0-9]+]] {
26; ATTRIBUTOR-NEXT:    [[TMP1:%.*]] = call i32 @scc1_bar() #[[ATTR1]]
27; ATTRIBUTOR-NEXT:    ret i32 1
28;
29  %1 = call i32 @scc1_bar()
30  ret i32 1
31}
32
33
34; TEST 3
35define i32 @scc1_bar() {
36; FNATTRS: Function Attrs: nofree nosync nounwind memory(none)
37; FNATTRS-LABEL: define {{[^@]+}}@scc1_bar
38; FNATTRS-SAME: () #[[ATTR1]] {
39; FNATTRS-NEXT:    [[TMP1:%.*]] = call i32 @scc1_foo()
40; FNATTRS-NEXT:    ret i32 1
41;
42; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none)
43; ATTRIBUTOR-LABEL: define {{[^@]+}}@scc1_bar
44; ATTRIBUTOR-SAME: () #[[ATTR1]] {
45; ATTRIBUTOR-NEXT:    [[TMP1:%.*]] = call i32 @scc1_foo() #[[ATTR1]]
46; ATTRIBUTOR-NEXT:    ret i32 1
47;
48  %1 = call i32 @scc1_foo()
49  ret i32 1
50}
51
52declare i32 @non_nounwind()
53
54; TEST 4
55define void @call_non_nounwind(){
56; COMMON-LABEL: define {{[^@]+}}@call_non_nounwind() {
57; COMMON-NEXT:    [[TMP1:%.*]] = tail call i32 @non_nounwind()
58; COMMON-NEXT:    ret void
59;
60  tail call i32 @non_nounwind()
61  ret void
62}
63
64; TEST 5 - throw
65; int maybe_throw(bool canThrow) {
66;   if (canThrow)
67;     throw;
68;   else
69;     return -1;
70; }
71
72define i32 @maybe_throw(i1 zeroext %0) {
73; COMMON-LABEL: define {{[^@]+}}@maybe_throw
74; COMMON-SAME: (i1 zeroext [[TMP0:%.*]]) {
75; COMMON-NEXT:    br i1 [[TMP0]], label [[TMP2:%.*]], label [[TMP3:%.*]]
76; COMMON:       2:
77; COMMON-NEXT:    tail call void @__cxa_rethrow()
78; COMMON-NEXT:    unreachable
79; COMMON:       3:
80; COMMON-NEXT:    ret i32 -1
81;
82  br i1 %0, label %2, label %3
83
842:                                                ; preds = %1
85  tail call void @__cxa_rethrow() #1
86  unreachable
87
883:                                                ; preds = %1
89  ret i32 -1
90}
91
92declare void @__cxa_rethrow()
93
94; TEST 6 - catch
95; int catch_thing() {
96;   try {
97;       int a = doThing(true);
98;   }
99;   catch(...) { return -1; }
100;   return 1;
101; }
102
103define i32 @catch_thing() personality ptr @__gxx_personality_v0 {
104; COMMON-LABEL: define {{[^@]+}}@catch_thing() personality ptr @__gxx_personality_v0 {
105; COMMON-NEXT:    invoke void @__cxa_rethrow()
106; COMMON-NEXT:    to label [[TMP1:%.*]] unwind label [[TMP2:%.*]]
107; COMMON:       1:
108; COMMON-NEXT:    unreachable
109; COMMON:       2:
110; COMMON-NEXT:    [[TMP3:%.*]] = landingpad { ptr, i32 }
111; COMMON-NEXT:    catch ptr null
112; COMMON-NEXT:    [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0
113; COMMON-NEXT:    [[TMP5:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[TMP4]])
114; COMMON-NEXT:    tail call void @__cxa_end_catch()
115; COMMON-NEXT:    ret i32 -1
116;
117  invoke void @__cxa_rethrow() #1
118  to label %1 unwind label %2
119
1201:                                                ; preds = %0
121  unreachable
122
1232:                                                ; preds = %0
124  %3 = landingpad { ptr, i32 }
125  catch ptr null
126  %4 = extractvalue { ptr, i32 } %3, 0
127  %5 = tail call ptr @__cxa_begin_catch(ptr %4) #2
128  tail call void @__cxa_end_catch()
129  ret i32 -1
130}
131
132define i32 @catch_thing_user() {
133; COMMON-LABEL: define {{[^@]+}}@catch_thing_user() {
134; COMMON-NEXT:    [[CATCH_THING_CALL:%.*]] = call i32 @catch_thing()
135; COMMON-NEXT:    ret i32 [[CATCH_THING_CALL]]
136;
137  %catch_thing_call = call i32 @catch_thing()
138  ret i32 %catch_thing_call
139}
140
141declare void @do_throw()
142declare void @abort() nounwind
143@catch_ty = external global ptr
144
145define void @catch_specific_landingpad() personality ptr @__gxx_personality_v0 {
146; COMMON: Function Attrs: noreturn
147; COMMON-LABEL: define {{[^@]+}}@catch_specific_landingpad
148; COMMON-SAME: () #[[ATTR3:[0-9]+]] personality ptr @__gxx_personality_v0 {
149; COMMON-NEXT:    invoke void @do_throw()
150; COMMON-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
151; COMMON:       lpad:
152; COMMON-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }
153; COMMON-NEXT:    catch ptr @catch_ty
154; COMMON-NEXT:    call void @abort()
155; COMMON-NEXT:    unreachable
156; COMMON:       unreachable:
157; COMMON-NEXT:    unreachable
158;
159  invoke void @do_throw()
160  to label %unreachable unwind label %lpad
161
162lpad:
163  %lp = landingpad { ptr, i32 }
164  catch ptr @catch_ty
165  call void @abort()
166  unreachable
167
168unreachable:
169  unreachable
170}
171
172define void @catch_all_landingpad() personality ptr @__gxx_personality_v0 {
173; COMMON: Function Attrs: noreturn nounwind
174; COMMON-LABEL: define {{[^@]+}}@catch_all_landingpad
175; COMMON-SAME: () #[[ATTR4:[0-9]+]] personality ptr @__gxx_personality_v0 {
176; COMMON-NEXT:    invoke void @do_throw()
177; COMMON-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
178; COMMON:       lpad:
179; COMMON-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }
180; COMMON-NEXT:    catch ptr null
181; COMMON-NEXT:    call void @abort()
182; COMMON-NEXT:    unreachable
183; COMMON:       unreachable:
184; COMMON-NEXT:    unreachable
185;
186  invoke void @do_throw()
187  to label %unreachable unwind label %lpad
188
189lpad:
190  %lp = landingpad { ptr, i32 }
191  catch ptr null
192  call void @abort()
193  unreachable
194
195unreachable:
196  unreachable
197}
198
199define void @filter_specific_landingpad() personality ptr @__gxx_personality_v0 {
200; COMMON: Function Attrs: noreturn
201; COMMON-LABEL: define {{[^@]+}}@filter_specific_landingpad
202; COMMON-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 {
203; COMMON-NEXT:    invoke void @do_throw()
204; COMMON-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
205; COMMON:       lpad:
206; COMMON-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }
207; COMMON-NEXT:    filter [1 x ptr] [ptr @catch_ty]
208; COMMON-NEXT:    call void @abort()
209; COMMON-NEXT:    unreachable
210; COMMON:       unreachable:
211; COMMON-NEXT:    unreachable
212;
213  invoke void @do_throw()
214  to label %unreachable unwind label %lpad
215
216lpad:
217  %lp = landingpad { ptr, i32 }
218  filter [1 x ptr] [ptr @catch_ty]
219  call void @abort()
220  unreachable
221
222unreachable:
223  unreachable
224}
225
226define void @filter_none_landingpad() personality ptr @__gxx_personality_v0 {
227; COMMON: Function Attrs: noreturn nounwind
228; COMMON-LABEL: define {{[^@]+}}@filter_none_landingpad
229; COMMON-SAME: () #[[ATTR4]] personality ptr @__gxx_personality_v0 {
230; COMMON-NEXT:    invoke void @do_throw()
231; COMMON-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
232; COMMON:       lpad:
233; COMMON-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }
234; COMMON-NEXT:    filter [0 x ptr] zeroinitializer
235; COMMON-NEXT:    call void @abort()
236; COMMON-NEXT:    unreachable
237; COMMON:       unreachable:
238; COMMON-NEXT:    unreachable
239;
240  invoke void @do_throw()
241  to label %unreachable unwind label %lpad
242
243lpad:
244  %lp = landingpad { ptr, i32 }
245  filter [0 x ptr] zeroinitializer
246  call void @abort()
247  unreachable
248
249unreachable:
250  unreachable
251}
252
253define void @cleanup_landingpad() personality ptr @__gxx_personality_v0 {
254; COMMON: Function Attrs: noreturn
255; COMMON-LABEL: define {{[^@]+}}@cleanup_landingpad
256; COMMON-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 {
257; COMMON-NEXT:    invoke void @do_throw()
258; COMMON-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]]
259; COMMON:       lpad:
260; COMMON-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }
261; COMMON-NEXT:    cleanup
262; COMMON-NEXT:    call void @abort()
263; COMMON-NEXT:    unreachable
264; COMMON:       unreachable:
265; COMMON-NEXT:    unreachable
266;
267  invoke void @do_throw()
268  to label %unreachable unwind label %lpad
269
270lpad:
271  %lp = landingpad { ptr, i32 }
272  cleanup
273  call void @abort()
274  unreachable
275
276unreachable:
277  unreachable
278}
279
280define void @cleanuppad() personality ptr @__gxx_personality_v0 {
281; FNATTRS: Function Attrs: noreturn
282; FNATTRS-LABEL: define {{[^@]+}}@cleanuppad
283; FNATTRS-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 {
284; FNATTRS-NEXT:    invoke void @do_throw()
285; FNATTRS-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[CPAD:%.*]]
286; FNATTRS:       cpad:
287; FNATTRS-NEXT:    [[CP:%.*]] = cleanuppad within none []
288; FNATTRS-NEXT:    call void @abort()
289; FNATTRS-NEXT:    unreachable
290; FNATTRS:       unreachable:
291; FNATTRS-NEXT:    unreachable
292;
293; ATTRIBUTOR: Function Attrs: noreturn nounwind
294; ATTRIBUTOR-LABEL: define {{[^@]+}}@cleanuppad
295; ATTRIBUTOR-SAME: () #[[ATTR4]] personality ptr @__gxx_personality_v0 {
296; ATTRIBUTOR-NEXT:    invoke void @do_throw()
297; ATTRIBUTOR-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[CPAD:%.*]]
298; ATTRIBUTOR:       cpad:
299; ATTRIBUTOR-NEXT:    [[CP:%.*]] = cleanuppad within none []
300; ATTRIBUTOR-NEXT:    call void @abort()
301; ATTRIBUTOR-NEXT:    unreachable
302; ATTRIBUTOR:       unreachable:
303; ATTRIBUTOR-NEXT:    unreachable
304;
305  invoke void @do_throw()
306  to label %unreachable unwind label %cpad
307
308cpad:
309  %cp = cleanuppad within none []
310  call void @abort()
311  unreachable
312
313unreachable:
314  unreachable
315}
316
317define void @catchswitch_cleanuppad() personality ptr @__gxx_personality_v0 {
318; FNATTRS: Function Attrs: noreturn
319; FNATTRS-LABEL: define {{[^@]+}}@catchswitch_cleanuppad
320; FNATTRS-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 {
321; FNATTRS-NEXT:    invoke void @do_throw()
322; FNATTRS-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[CS:%.*]]
323; FNATTRS:       cs:
324; FNATTRS-NEXT:    [[TOK:%.*]] = catchswitch within none [label %catch] unwind label [[CPAD:%.*]]
325; FNATTRS:       catch:
326; FNATTRS-NEXT:    [[C:%.*]] = catchpad within [[TOK]] [ptr @catch_ty, i32 0, ptr null]
327; FNATTRS-NEXT:    call void @abort()
328; FNATTRS-NEXT:    unreachable
329; FNATTRS:       cpad:
330; FNATTRS-NEXT:    [[CP:%.*]] = cleanuppad within none []
331; FNATTRS-NEXT:    call void @abort()
332; FNATTRS-NEXT:    unreachable
333; FNATTRS:       unreachable:
334; FNATTRS-NEXT:    unreachable
335;
336; ATTRIBUTOR: Function Attrs: noreturn nounwind
337; ATTRIBUTOR-LABEL: define {{[^@]+}}@catchswitch_cleanuppad
338; ATTRIBUTOR-SAME: () #[[ATTR4]] personality ptr @__gxx_personality_v0 {
339; ATTRIBUTOR-NEXT:    invoke void @do_throw()
340; ATTRIBUTOR-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[CS:%.*]]
341; ATTRIBUTOR:       cs:
342; ATTRIBUTOR-NEXT:    [[TOK:%.*]] = catchswitch within none [label %catch] unwind label [[CPAD:%.*]]
343; ATTRIBUTOR:       catch:
344; ATTRIBUTOR-NEXT:    [[C:%.*]] = catchpad within [[TOK]] [ptr @catch_ty, i32 0, ptr null]
345; ATTRIBUTOR-NEXT:    call void @abort()
346; ATTRIBUTOR-NEXT:    unreachable
347; ATTRIBUTOR:       cpad:
348; ATTRIBUTOR-NEXT:    [[CP:%.*]] = cleanuppad within none []
349; ATTRIBUTOR-NEXT:    call void @abort()
350; ATTRIBUTOR-NEXT:    unreachable
351; ATTRIBUTOR:       unreachable:
352; ATTRIBUTOR-NEXT:    unreachable
353;
354  invoke void @do_throw()
355  to label %unreachable unwind label %cs
356
357cs:
358  %tok = catchswitch within none [label %catch] unwind label %cpad
359
360catch:
361  %c = catchpad within %tok [ptr @catch_ty, i32 0, ptr null]
362  call void @abort()
363  unreachable
364
365cpad:
366  %cp = cleanuppad within none []
367  call void @abort()
368  unreachable
369
370unreachable:
371  unreachable
372}
373
374declare i32 @__gxx_personality_v0(...)
375
376declare ptr @__cxa_begin_catch(ptr)
377
378declare void @__cxa_end_catch()
379