1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=14 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=14 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
6
7target datalayout = "e-m:e-i54:64-f80:128-n8:16:32:64-S128"
8
9; Test cases specifically designed for the "willreturn" function attribute.
10; We use FIXME's to indicate problems and missing attributes.
11
12
13; TEST 1 (positive case)
14define void @only_return() #0 {
15; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
16; CHECK-LABEL: define {{[^@]+}}@only_return
17; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
18; CHECK-NEXT:    ret void
19;
20  ret void
21}
22
23
24; TEST 2 (positive & negative case)
25; 2.1 (positive case)
26; recursive function which will halt
27; int fib(int n){
28;    return n<=1? n : fib(n-1) + fib(n-2);
29; }
30
31; FIXME: missing willreturn
32define i32 @fib(i32 %0) local_unnamed_addr #0 {
33; IS__TUNIT_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable
34; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fib
35; IS__TUNIT_OPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
36; IS__TUNIT_OPM-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 2
37; IS__TUNIT_OPM-NEXT:    br i1 [[TMP2]], label [[TMP9:%.*]], label [[TMP3:%.*]]
38; IS__TUNIT_OPM:       3:
39; IS__TUNIT_OPM-NEXT:    [[TMP4:%.*]] = add nsw i32 [[TMP0]], -1
40; IS__TUNIT_OPM-NEXT:    [[TMP5:%.*]] = tail call i32 @fib(i32 [[TMP4]]) #[[ATTR24:[0-9]+]]
41; IS__TUNIT_OPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], -2
42; IS__TUNIT_OPM-NEXT:    [[TMP7:%.*]] = tail call i32 @fib(i32 [[TMP6]]) #[[ATTR24]]
43; IS__TUNIT_OPM-NEXT:    [[TMP8:%.*]] = add nsw i32 [[TMP7]], [[TMP5]]
44; IS__TUNIT_OPM-NEXT:    ret i32 [[TMP8]]
45; IS__TUNIT_OPM:       9:
46; IS__TUNIT_OPM-NEXT:    ret i32 [[TMP0]]
47;
48; IS__TUNIT_NPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable
49; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fib
50; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
51; IS__TUNIT_NPM-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 2
52; IS__TUNIT_NPM-NEXT:    br i1 [[TMP2]], label [[TMP9:%.*]], label [[TMP3:%.*]]
53; IS__TUNIT_NPM:       3:
54; IS__TUNIT_NPM-NEXT:    [[TMP4:%.*]] = add nsw i32 [[TMP0]], -1
55; IS__TUNIT_NPM-NEXT:    [[TMP5:%.*]] = tail call i32 @fib(i32 [[TMP4]]) #[[ATTR26:[0-9]+]]
56; IS__TUNIT_NPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], -2
57; IS__TUNIT_NPM-NEXT:    [[TMP7:%.*]] = tail call i32 @fib(i32 [[TMP6]]) #[[ATTR26]]
58; IS__TUNIT_NPM-NEXT:    [[TMP8:%.*]] = add nsw i32 [[TMP7]], [[TMP5]]
59; IS__TUNIT_NPM-NEXT:    ret i32 [[TMP8]]
60; IS__TUNIT_NPM:       9:
61; IS__TUNIT_NPM-NEXT:    ret i32 [[TMP0]]
62;
63; IS__CGSCC_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable
64; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fib
65; IS__CGSCC_OPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
66; IS__CGSCC_OPM-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 2
67; IS__CGSCC_OPM-NEXT:    br i1 [[TMP2]], label [[TMP9:%.*]], label [[TMP3:%.*]]
68; IS__CGSCC_OPM:       3:
69; IS__CGSCC_OPM-NEXT:    [[TMP4:%.*]] = add nsw i32 [[TMP0]], -1
70; IS__CGSCC_OPM-NEXT:    [[TMP5:%.*]] = tail call i32 @fib(i32 [[TMP4]]) #[[ATTR17:[0-9]+]]
71; IS__CGSCC_OPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], -2
72; IS__CGSCC_OPM-NEXT:    [[TMP7:%.*]] = tail call i32 @fib(i32 [[TMP6]]) #[[ATTR17]]
73; IS__CGSCC_OPM-NEXT:    [[TMP8:%.*]] = add nsw i32 [[TMP7]], [[TMP5]]
74; IS__CGSCC_OPM-NEXT:    ret i32 [[TMP8]]
75; IS__CGSCC_OPM:       9:
76; IS__CGSCC_OPM-NEXT:    ret i32 [[TMP0]]
77;
78; IS__CGSCC_NPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable
79; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fib
80; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
81; IS__CGSCC_NPM-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 2
82; IS__CGSCC_NPM-NEXT:    br i1 [[TMP2]], label [[TMP9:%.*]], label [[TMP3:%.*]]
83; IS__CGSCC_NPM:       3:
84; IS__CGSCC_NPM-NEXT:    [[TMP4:%.*]] = add nsw i32 [[TMP0]], -1
85; IS__CGSCC_NPM-NEXT:    [[TMP5:%.*]] = tail call i32 @fib(i32 [[TMP4]]) #[[ATTR19:[0-9]+]]
86; IS__CGSCC_NPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], -2
87; IS__CGSCC_NPM-NEXT:    [[TMP7:%.*]] = tail call i32 @fib(i32 [[TMP6]]) #[[ATTR19]]
88; IS__CGSCC_NPM-NEXT:    [[TMP8:%.*]] = add nsw i32 [[TMP7]], [[TMP5]]
89; IS__CGSCC_NPM-NEXT:    ret i32 [[TMP8]]
90; IS__CGSCC_NPM:       9:
91; IS__CGSCC_NPM-NEXT:    ret i32 [[TMP0]]
92;
93  %2 = icmp slt i32 %0, 2
94  br i1 %2, label %9, label %3
95
96; <label>:3:                                      ; preds = %1
97  %4 = add nsw i32 %0, -1
98  %5 = tail call i32 @fib(i32 %4)
99  %6 = add nsw i32 %0, -2
100  %7 = tail call i32 @fib(i32 %6)
101  %8 = add nsw i32 %7, %5
102  ret i32 %8
103
104; <label>:9:                                      ; preds = %1
105  ret i32 %0
106}
107
108; 2.2 (negative case)
109; recursive function which doesn't stop for some input.
110; int fact_maybe_not_halt(int n) {
111;   if (n==0) {
112;     return 1;
113;   }
114;   return fact_maybe_not_halt( n > 0 ? n-1 : n) * n;
115; }
116; fact_maybe_not(-1) doesn't stop.
117
118define i32 @fact_maybe_not_halt(i32 %0) local_unnamed_addr #0 {
119; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
120; CHECK-LABEL: define {{[^@]+}}@fact_maybe_not_halt
121; CHECK-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
122; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0
123; CHECK-NEXT:    br i1 [[TMP2]], label [[TMP11:%.*]], label [[TMP3:%.*]]
124; CHECK:       3:
125; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ [[TMP8:%.*]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]
126; CHECK-NEXT:    [[TMP5:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP3]] ], [ 1, [[TMP1]] ]
127; CHECK-NEXT:    [[TMP6:%.*]] = icmp sgt i32 [[TMP4]], 0
128; CHECK-NEXT:    [[TMP7:%.*]] = sext i1 [[TMP6]] to i32
129; CHECK-NEXT:    [[TMP8]] = add nsw i32 [[TMP4]], [[TMP7]]
130; CHECK-NEXT:    [[TMP9]] = mul nsw i32 [[TMP4]], [[TMP5]]
131; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i32 [[TMP8]], 0
132; CHECK-NEXT:    br i1 [[TMP10]], label [[TMP11]], label [[TMP3]]
133; CHECK:       11:
134; CHECK-NEXT:    [[TMP12:%.*]] = phi i32 [ 1, [[TMP1]] ], [ [[TMP9]], [[TMP3]] ]
135; CHECK-NEXT:    ret i32 [[TMP12]]
136;
137  %2 = icmp eq i32 %0, 0
138  br i1 %2, label %11, label %3
139
140; <label>:3:                                      ; preds = %1, %3
141  %4 = phi i32 [ %8, %3 ], [ %0, %1 ]
142  %5 = phi i32 [ %9, %3 ], [ 1, %1 ]
143  %6 = icmp sgt i32 %4, 0
144  %7 = sext i1 %6 to i32
145  %8 = add nsw i32 %4, %7
146  %9 = mul nsw i32 %4, %5
147  %10 = icmp eq i32 %8, 0
148  br i1 %10, label %11, label %3
149
150; <label>:11:                                     ; preds = %3, %1
151  %12 = phi i32 [ 1, %1 ], [ %9, %3 ]
152  ret i32 %12
153}
154
155
156; TEST 3 (positive case)
157; loop
158; int fact_loop(int n ){
159;   int ans = 1;
160;   for(int i = 1;i<=n;i++){
161;     ans *= i;
162;   }
163;   return ans;
164; }
165
166define i32 @fact_loop(i32 %0) local_unnamed_addr #0 {
167; IS________OPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
168; IS________OPM-LABEL: define {{[^@]+}}@fact_loop
169; IS________OPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] {
170; IS________OPM-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1
171; IS________OPM-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
172; IS________OPM:       3:
173; IS________OPM-NEXT:    [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ]
174; IS________OPM-NEXT:    ret i32 [[TMP4]]
175; IS________OPM:       5:
176; IS________OPM-NEXT:    [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ]
177; IS________OPM-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ]
178; IS________OPM-NEXT:    [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]]
179; IS________OPM-NEXT:    [[TMP9]] = add nuw nsw i32 [[TMP6]], 1
180; IS________OPM-NEXT:    [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]]
181; IS________OPM-NEXT:    br i1 [[TMP10]], label [[TMP3]], label [[TMP5]]
182;
183; IS________NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
184; IS________NPM-LABEL: define {{[^@]+}}@fact_loop
185; IS________NPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] {
186; IS________NPM-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1
187; IS________NPM-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
188; IS________NPM:       3:
189; IS________NPM-NEXT:    [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ]
190; IS________NPM-NEXT:    ret i32 [[TMP4]]
191; IS________NPM:       5:
192; IS________NPM-NEXT:    [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ]
193; IS________NPM-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ]
194; IS________NPM-NEXT:    [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]]
195; IS________NPM-NEXT:    [[TMP9]] = add nuw nsw i32 [[TMP6]], 1
196; IS________NPM-NEXT:    [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]]
197; IS________NPM-NEXT:    br i1 [[TMP10]], label [[TMP3]], label [[TMP5]]
198;
199  %2 = icmp slt i32 %0, 1
200  br i1 %2, label %3, label %5
201
202; <label>:3:                                      ; preds = %5, %1
203  %4 = phi i32 [ 1, %1 ], [ %8, %5 ]
204  ret i32 %4
205
206; <label>:5:                                      ; preds = %1, %5
207  %6 = phi i32 [ %9, %5 ], [ 1, %1 ]
208  %7 = phi i32 [ %8, %5 ], [ 1, %1 ]
209  %8 = mul nsw i32 %6, %7
210  %9 = add nuw nsw i32 %6, 1
211  %10 = icmp eq i32 %6, %0
212  br i1 %10, label %3, label %5
213}
214
215; TEST 4 (negative case)
216; mutual recursion
217; void mutual_recursion1(){
218;    mutual_recursion2();
219; }
220; void mutual_recursion2(){
221;     mutual_recursion1();
222; }
223
224declare void @sink() nounwind willreturn nosync nofree
225
226define void @mutual_recursion1(i1 %c) #0 {
227; IS________OPM: Function Attrs: nofree noinline nosync nounwind uwtable
228; IS________OPM-LABEL: define {{[^@]+}}@mutual_recursion1
229; IS________OPM-SAME: (i1 [[C:%.*]]) #[[ATTR4:[0-9]+]] {
230; IS________OPM-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
231; IS________OPM:       rec:
232; IS________OPM-NEXT:    call void @sink() #[[ATTR12:[0-9]+]]
233; IS________OPM-NEXT:    call void @mutual_recursion2(i1 [[C]]) #[[ATTR25:[0-9]+]]
234; IS________OPM-NEXT:    br label [[END]]
235; IS________OPM:       end:
236; IS________OPM-NEXT:    ret void
237;
238; IS________NPM: Function Attrs: nofree noinline nosync nounwind uwtable
239; IS________NPM-LABEL: define {{[^@]+}}@mutual_recursion1
240; IS________NPM-SAME: (i1 [[C:%.*]]) #[[ATTR4:[0-9]+]] {
241; IS________NPM-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
242; IS________NPM:       rec:
243; IS________NPM-NEXT:    call void @sink() #[[ATTR12:[0-9]+]]
244; IS________NPM-NEXT:    call void @mutual_recursion2(i1 noundef [[C]]) #[[ATTR27:[0-9]+]]
245; IS________NPM-NEXT:    br label [[END]]
246; IS________NPM:       end:
247; IS________NPM-NEXT:    ret void
248;
249  br i1 %c, label %rec, label %end
250rec:
251  call void @sink()
252  call void @mutual_recursion2(i1 %c)
253  br label %end
254end:
255  ret void
256}
257
258
259define void @mutual_recursion2(i1 %c) #0 {
260; IS________OPM: Function Attrs: nofree noinline nosync nounwind uwtable
261; IS________OPM-LABEL: define {{[^@]+}}@mutual_recursion2
262; IS________OPM-SAME: (i1 [[C:%.*]]) #[[ATTR4]] {
263; IS________OPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR25]]
264; IS________OPM-NEXT:    ret void
265;
266; IS________NPM: Function Attrs: nofree noinline nosync nounwind uwtable
267; IS________NPM-LABEL: define {{[^@]+}}@mutual_recursion2
268; IS________NPM-SAME: (i1 [[C:%.*]]) #[[ATTR4]] {
269; IS________NPM-NEXT:    call void @mutual_recursion1(i1 [[C]]) #[[ATTR27]]
270; IS________NPM-NEXT:    ret void
271;
272  call void @mutual_recursion1(i1 %c)
273  ret void
274}
275
276
277; TEST 5 (negative case)
278; call exit/abort (has noreturn attribute)
279; CHECK: Function Attrs: noreturn
280; CHECK-NEXT: declare void @exit(i32) local_unnamed_add
281declare void @exit(i32 %0) local_unnamed_addr noreturn
282
283define void @only_exit() local_unnamed_addr #0 {
284; CHECK: Function Attrs: noinline noreturn nounwind uwtable
285; CHECK-LABEL: define {{[^@]+}}@only_exit
286; CHECK-SAME: () local_unnamed_addr #[[ATTR6:[0-9]+]] {
287; CHECK-NEXT:    tail call void @exit(i32 noundef 0) #[[ATTR5:[0-9]+]]
288; CHECK-NEXT:    unreachable
289;
290  tail call void @exit(i32 0)
291  unreachable
292}
293
294; conditional exit
295; void conditional_exit(int cond, int *p){
296;     if(cond){
297;       exit(0);
298;     }
299;     if(*p){
300;       exit(1);
301;     }
302;     return;
303; }
304define void @conditional_exit(i32 %0, i32* nocapture readonly %1) local_unnamed_addr #0 {
305; CHECK: Function Attrs: noinline nounwind uwtable
306; CHECK-LABEL: define {{[^@]+}}@conditional_exit
307; CHECK-SAME: (i32 [[TMP0:%.*]], i32* nocapture nofree readonly [[TMP1:%.*]]) local_unnamed_addr #[[ATTR7:[0-9]+]] {
308; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0
309; CHECK-NEXT:    br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
310; CHECK:       4:
311; CHECK-NEXT:    tail call void @exit(i32 noundef 0) #[[ATTR5]]
312; CHECK-NEXT:    unreachable
313; CHECK:       5:
314; CHECK-NEXT:    [[TMP6:%.*]] = load i32, i32* [[TMP1]], align 4
315; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0
316; CHECK-NEXT:    br i1 [[TMP7]], label [[TMP9:%.*]], label [[TMP8:%.*]]
317; CHECK:       8:
318; CHECK-NEXT:    tail call void @exit(i32 noundef 1) #[[ATTR5]]
319; CHECK-NEXT:    unreachable
320; CHECK:       9:
321; CHECK-NEXT:    ret void
322;
323  %3 = icmp eq i32 %0, 0
324  br i1 %3, label %5, label %4
325
326; <label>:4:                                      ; preds = %2
327  tail call void @exit(i32 0)
328  unreachable
329
330; <label>:5:                                      ; preds = %2
331  %6 = load i32, i32* %1, align 4
332  %7 = icmp eq i32 %6, 0
333  br i1 %7, label %9, label %8
334
335; <label>:8:                                      ; preds = %5
336  tail call void @exit(i32 1)
337  unreachable
338
339; <label>:9:                                      ; preds = %5
340  ret void
341}
342
343; TEST 6 (positive case)
344; Call intrinsic function
345; CHECK: Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
346; CHECK-NEXT: declare float @llvm.floor.f32(float)
347declare float @llvm.floor.f32(float)
348
349define void @call_floor(float %a) #0 {
350; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
351; CHECK-LABEL: define {{[^@]+}}@call_floor
352; CHECK-SAME: (float [[A:%.*]]) #[[ATTR0]] {
353; CHECK-NEXT:    ret void
354;
355  tail call float @llvm.floor.f32(float %a)
356  ret void
357}
358
359define float @call_floor2(float %a) #0 {
360; IS________OPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
361; IS________OPM-LABEL: define {{[^@]+}}@call_floor2
362; IS________OPM-SAME: (float [[A:%.*]]) #[[ATTR0]] {
363; IS________OPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR26:[0-9]+]]
364; IS________OPM-NEXT:    ret float [[C]]
365;
366; IS________NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
367; IS________NPM-LABEL: define {{[^@]+}}@call_floor2
368; IS________NPM-SAME: (float [[A:%.*]]) #[[ATTR0]] {
369; IS________NPM-NEXT:    [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) #[[ATTR28:[0-9]+]]
370; IS________NPM-NEXT:    ret float [[C]]
371;
372  %c = tail call float @llvm.floor.f32(float %a)
373  ret float %c
374}
375
376
377; TEST 7 (negative case)
378; Call function declaration without willreturn
379
380; CHECK: Function Attrs: noinline nounwind uwtable
381; CHECK-NOT: willreturn
382; CHECK-NEXT: declare void @maybe_noreturn()
383declare void @maybe_noreturn() #0
384
385define void @call_maybe_noreturn() #0 {
386; IS________OPM: Function Attrs: noinline nounwind uwtable
387; IS________OPM-LABEL: define {{[^@]+}}@call_maybe_noreturn
388; IS________OPM-SAME: () #[[ATTR7]] {
389; IS________OPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR27:[0-9]+]]
390; IS________OPM-NEXT:    ret void
391;
392; IS________NPM: Function Attrs: noinline nounwind uwtable
393; IS________NPM-LABEL: define {{[^@]+}}@call_maybe_noreturn
394; IS________NPM-SAME: () #[[ATTR7]] {
395; IS________NPM-NEXT:    tail call void @maybe_noreturn() #[[ATTR29:[0-9]+]]
396; IS________NPM-NEXT:    ret void
397;
398  tail call void @maybe_noreturn()
399  ret void
400}
401
402
403; TEST 8 (positive case)
404; Check propagation.
405
406; CHECK: Function Attrs: norecurse willreturn
407; CHECK-NEXT: declare void @will_return()
408declare void @will_return() willreturn norecurse
409
410define void @f1() #0 {
411; IS________OPM: Function Attrs: noinline nounwind willreturn uwtable
412; IS________OPM-LABEL: define {{[^@]+}}@f1
413; IS________OPM-SAME: () #[[ATTR10:[0-9]+]] {
414; IS________OPM-NEXT:    tail call void @will_return() #[[ATTR28:[0-9]+]]
415; IS________OPM-NEXT:    ret void
416;
417; IS________NPM: Function Attrs: noinline nounwind willreturn uwtable
418; IS________NPM-LABEL: define {{[^@]+}}@f1
419; IS________NPM-SAME: () #[[ATTR10:[0-9]+]] {
420; IS________NPM-NEXT:    tail call void @will_return() #[[ATTR30:[0-9]+]]
421; IS________NPM-NEXT:    ret void
422;
423  tail call void @will_return()
424  ret void
425}
426
427define void @f2() #0 {
428; CHECK: Function Attrs: noinline nounwind willreturn uwtable
429; CHECK-LABEL: define {{[^@]+}}@f2
430; CHECK-SAME: () #[[ATTR10:[0-9]+]] {
431; CHECK-NEXT:    tail call void @f1() #[[ATTR12:[0-9]+]]
432; CHECK-NEXT:    ret void
433;
434  tail call void @f1()
435  ret void
436}
437
438
439; TEST 9 (negative case)
440; call willreturn function in endless loop.
441
442define void @call_will_return_but_has_loop() #0 {
443; CHECK: Function Attrs: noinline noreturn nounwind uwtable
444; CHECK-LABEL: define {{[^@]+}}@call_will_return_but_has_loop
445; CHECK-SAME: () #[[ATTR6]] {
446; CHECK-NEXT:    br label [[LABEL1:%.*]]
447; CHECK:       label1:
448; CHECK-NEXT:    tail call void @will_return()
449; CHECK-NEXT:    br label [[LABEL2:%.*]]
450; CHECK:       label2:
451; CHECK-NEXT:    br label [[LABEL1]]
452;
453  br label %label1
454label1:
455  tail call void @will_return()
456  br label %label2
457label2:
458  br label %label1
459}
460
461
462; TEST 10 (positive case)
463; invoke a function with willreturn
464
465; CHECK: Function Attrs: noinline willreturn uwtable
466; CHECK-NEXT: declare i1 @maybe_raise_exception()
467declare i1 @maybe_raise_exception() #1 willreturn
468
469define void @invoke_test() personality i32 (...)* @__gxx_personality_v0 {
470; IS________OPM: Function Attrs: nounwind willreturn
471; IS________OPM-LABEL: define {{[^@]+}}@invoke_test
472; IS________OPM-SAME: () #[[ATTR12]] personality i32 (...)* @__gxx_personality_v0 {
473; IS________OPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR28]]
474; IS________OPM-NEXT:    to label [[N:%.*]] unwind label [[F:%.*]]
475; IS________OPM:       N:
476; IS________OPM-NEXT:    ret void
477; IS________OPM:       F:
478; IS________OPM-NEXT:    [[VAL:%.*]] = landingpad { i8*, i32 }
479; IS________OPM-NEXT:    catch i8* null
480; IS________OPM-NEXT:    ret void
481;
482; IS________NPM: Function Attrs: nounwind willreturn
483; IS________NPM-LABEL: define {{[^@]+}}@invoke_test
484; IS________NPM-SAME: () #[[ATTR12]] personality i32 (...)* @__gxx_personality_v0 {
485; IS________NPM-NEXT:    [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() #[[ATTR30]]
486; IS________NPM-NEXT:    to label [[N:%.*]] unwind label [[F:%.*]]
487; IS________NPM:       N:
488; IS________NPM-NEXT:    ret void
489; IS________NPM:       F:
490; IS________NPM-NEXT:    [[VAL:%.*]] = landingpad { i8*, i32 }
491; IS________NPM-NEXT:    catch i8* null
492; IS________NPM-NEXT:    ret void
493;
494  invoke i1 @maybe_raise_exception()
495  to label %N unwind label %F
496  N:
497  ret void
498  F:
499  %val = landingpad { i8*, i32 }
500  catch i8* null
501  ret void
502}
503
504declare i32 @__gxx_personality_v0(...)
505
506
507; TEST 11 (positive case)
508; constant trip count
509; int loop_constant_trip_count(int*p){
510;    int ans = 0;
511;    for(int i = 0;i<10;i++){
512;        ans += p[i];
513;    }
514;    return ans;
515; }
516
517define i32 @loop_constant_trip_count(i32* nocapture readonly %0) #0 {
518; IS________OPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable
519; IS________OPM-LABEL: define {{[^@]+}}@loop_constant_trip_count
520; IS________OPM-SAME: (i32* nocapture nofree readonly [[TMP0:%.*]]) #[[ATTR13:[0-9]+]] {
521; IS________OPM-NEXT:    br label [[TMP3:%.*]]
522; IS________OPM:       2:
523; IS________OPM-NEXT:    ret i32 [[TMP8:%.*]]
524; IS________OPM:       3:
525; IS________OPM-NEXT:    [[TMP4:%.*]] = phi i64 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP3]] ]
526; IS________OPM-NEXT:    [[TMP5:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP3]] ]
527; IS________OPM-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP4]]
528; IS________OPM-NEXT:    [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4
529; IS________OPM-NEXT:    [[TMP8]] = add nsw i32 [[TMP7]], [[TMP5]]
530; IS________OPM-NEXT:    [[TMP9]] = add nuw nsw i64 [[TMP4]], 1
531; IS________OPM-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 10
532; IS________OPM-NEXT:    br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP3]]
533;
534; IS________NPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable
535; IS________NPM-LABEL: define {{[^@]+}}@loop_constant_trip_count
536; IS________NPM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[TMP0:%.*]]) #[[ATTR13:[0-9]+]] {
537; IS________NPM-NEXT:    br label [[TMP3:%.*]]
538; IS________NPM:       2:
539; IS________NPM-NEXT:    ret i32 [[TMP8:%.*]]
540; IS________NPM:       3:
541; IS________NPM-NEXT:    [[TMP4:%.*]] = phi i64 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP3]] ]
542; IS________NPM-NEXT:    [[TMP5:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP3]] ]
543; IS________NPM-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP4]]
544; IS________NPM-NEXT:    [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4
545; IS________NPM-NEXT:    [[TMP8]] = add nsw i32 [[TMP7]], [[TMP5]]
546; IS________NPM-NEXT:    [[TMP9]] = add nuw nsw i64 [[TMP4]], 1
547; IS________NPM-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 10
548; IS________NPM-NEXT:    br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP3]]
549;
550  br label %3
551
552; <label>:2:                                      ; preds = %3
553  ret i32 %8
554
555; <label>:3:                                      ; preds = %3, %1
556  %4 = phi i64 [ 0, %1 ], [ %9, %3 ]
557  %5 = phi i32 [ 0, %1 ], [ %8, %3 ]
558  %6 = getelementptr inbounds i32, i32* %0, i64 %4
559  %7 = load i32, i32* %6, align 4
560  %8 = add nsw i32 %7, %5
561  %9 = add nuw nsw i64 %4, 1
562  %10 = icmp eq i64 %9, 10
563  br i1 %10, label %2, label %3
564}
565
566
567; TEST 12 (negative case)
568; unbounded trip count
569
570; int loop_trip_count_unbound(unsigned s,unsigned e, int *p, int offset){
571;     int ans = 0;
572;     for(unsigned i = s;i != e;i+=offset){
573;         ans += p[i];
574;     }
575;     return ans;
576; }
577define i32 @loop_trip_count_unbound(i32 %0, i32 %1, i32* nocapture readonly %2, i32 %3) local_unnamed_addr #0 {
578; IS________OPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable
579; IS________OPM-LABEL: define {{[^@]+}}@loop_trip_count_unbound
580; IS________OPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* nocapture nofree readonly [[TMP2:%.*]], i32 [[TMP3:%.*]]) local_unnamed_addr #[[ATTR13]] {
581; IS________OPM-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
582; IS________OPM-NEXT:    br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP8:%.*]]
583; IS________OPM:       6:
584; IS________OPM-NEXT:    [[TMP7:%.*]] = phi i32 [ 0, [[TMP4:%.*]] ], [ [[TMP14:%.*]], [[TMP8]] ]
585; IS________OPM-NEXT:    ret i32 [[TMP7]]
586; IS________OPM:       8:
587; IS________OPM-NEXT:    [[TMP9:%.*]] = phi i32 [ [[TMP15:%.*]], [[TMP8]] ], [ [[TMP0]], [[TMP4]] ]
588; IS________OPM-NEXT:    [[TMP10:%.*]] = phi i32 [ [[TMP14]], [[TMP8]] ], [ 0, [[TMP4]] ]
589; IS________OPM-NEXT:    [[TMP11:%.*]] = zext i32 [[TMP9]] to i64
590; IS________OPM-NEXT:    [[TMP12:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP11]]
591; IS________OPM-NEXT:    [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4
592; IS________OPM-NEXT:    [[TMP14]] = add nsw i32 [[TMP13]], [[TMP10]]
593; IS________OPM-NEXT:    [[TMP15]] = add i32 [[TMP9]], [[TMP3]]
594; IS________OPM-NEXT:    [[TMP16:%.*]] = icmp eq i32 [[TMP15]], [[TMP1]]
595; IS________OPM-NEXT:    br i1 [[TMP16]], label [[TMP6]], label [[TMP8]]
596;
597; IS________NPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable
598; IS________NPM-LABEL: define {{[^@]+}}@loop_trip_count_unbound
599; IS________NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* nocapture nofree readonly [[TMP2:%.*]], i32 [[TMP3:%.*]]) local_unnamed_addr #[[ATTR14:[0-9]+]] {
600; IS________NPM-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
601; IS________NPM-NEXT:    br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP8:%.*]]
602; IS________NPM:       6:
603; IS________NPM-NEXT:    [[TMP7:%.*]] = phi i32 [ 0, [[TMP4:%.*]] ], [ [[TMP14:%.*]], [[TMP8]] ]
604; IS________NPM-NEXT:    ret i32 [[TMP7]]
605; IS________NPM:       8:
606; IS________NPM-NEXT:    [[TMP9:%.*]] = phi i32 [ [[TMP15:%.*]], [[TMP8]] ], [ [[TMP0]], [[TMP4]] ]
607; IS________NPM-NEXT:    [[TMP10:%.*]] = phi i32 [ [[TMP14]], [[TMP8]] ], [ 0, [[TMP4]] ]
608; IS________NPM-NEXT:    [[TMP11:%.*]] = zext i32 [[TMP9]] to i64
609; IS________NPM-NEXT:    [[TMP12:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP11]]
610; IS________NPM-NEXT:    [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4
611; IS________NPM-NEXT:    [[TMP14]] = add nsw i32 [[TMP13]], [[TMP10]]
612; IS________NPM-NEXT:    [[TMP15]] = add i32 [[TMP9]], [[TMP3]]
613; IS________NPM-NEXT:    [[TMP16:%.*]] = icmp eq i32 [[TMP15]], [[TMP1]]
614; IS________NPM-NEXT:    br i1 [[TMP16]], label [[TMP6]], label [[TMP8]]
615;
616  %5 = icmp eq i32 %0, %1
617  br i1 %5, label %6, label %8
618
619; <label>:6:                                      ; preds = %8, %4
620  %7 = phi i32 [ 0, %4 ], [ %14, %8 ]
621  ret i32 %7
622
623; <label>:8:                                      ; preds = %4, %8
624  %9 = phi i32 [ %15, %8 ], [ %0, %4 ]
625  %10 = phi i32 [ %14, %8 ], [ 0, %4 ]
626  %11 = zext i32 %9 to i64
627  %12 = getelementptr inbounds i32, i32* %2, i64 %11
628  %13 = load i32, i32* %12, align 4
629  %14 = add nsw i32 %13, %10
630  %15 = add i32 %9, %3
631  %16 = icmp eq i32 %15, %1
632  br i1 %16, label %6, label %8
633}
634
635
636; TEST 13 (positive case)
637; Function Attrs: norecurse nounwind readonly uwtable
638;  int loop_trip_dec(int n, int *p){
639;    int ans = 0;
640;    for(;n >= 0;n--){
641;        ans += p[n];
642;    }
643;    return ans;
644;  }
645
646
647define i32 @loop_trip_dec(i32 %0, i32* nocapture readonly %1) local_unnamed_addr #0 {
648; IS________OPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable
649; IS________OPM-LABEL: define {{[^@]+}}@loop_trip_dec
650; IS________OPM-SAME: (i32 [[TMP0:%.*]], i32* nocapture nofree readonly [[TMP1:%.*]]) local_unnamed_addr #[[ATTR13]] {
651; IS________OPM-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], -1
652; IS________OPM-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP14:%.*]]
653; IS________OPM:       4:
654; IS________OPM-NEXT:    [[TMP5:%.*]] = sext i32 [[TMP0]] to i64
655; IS________OPM-NEXT:    br label [[TMP6:%.*]]
656; IS________OPM:       6:
657; IS________OPM-NEXT:    [[TMP7:%.*]] = phi i64 [ [[TMP5]], [[TMP4]] ], [ [[TMP12:%.*]], [[TMP6]] ]
658; IS________OPM-NEXT:    [[TMP8:%.*]] = phi i32 [ 0, [[TMP4]] ], [ [[TMP11:%.*]], [[TMP6]] ]
659; IS________OPM-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 [[TMP7]]
660; IS________OPM-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4
661; IS________OPM-NEXT:    [[TMP11]] = add nsw i32 [[TMP10]], [[TMP8]]
662; IS________OPM-NEXT:    [[TMP12]] = add nsw i64 [[TMP7]], -1
663; IS________OPM-NEXT:    [[TMP13:%.*]] = icmp sgt i64 [[TMP7]], 0
664; IS________OPM-NEXT:    br i1 [[TMP13]], label [[TMP6]], label [[TMP14]]
665; IS________OPM:       14:
666; IS________OPM-NEXT:    [[TMP15:%.*]] = phi i32 [ 0, [[TMP2:%.*]] ], [ [[TMP11]], [[TMP6]] ]
667; IS________OPM-NEXT:    ret i32 [[TMP15]]
668;
669; IS________NPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable
670; IS________NPM-LABEL: define {{[^@]+}}@loop_trip_dec
671; IS________NPM-SAME: (i32 [[TMP0:%.*]], i32* nocapture nofree readonly [[TMP1:%.*]]) local_unnamed_addr #[[ATTR13]] {
672; IS________NPM-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], -1
673; IS________NPM-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP14:%.*]]
674; IS________NPM:       4:
675; IS________NPM-NEXT:    [[TMP5:%.*]] = sext i32 [[TMP0]] to i64
676; IS________NPM-NEXT:    br label [[TMP6:%.*]]
677; IS________NPM:       6:
678; IS________NPM-NEXT:    [[TMP7:%.*]] = phi i64 [ [[TMP5]], [[TMP4]] ], [ [[TMP12:%.*]], [[TMP6]] ]
679; IS________NPM-NEXT:    [[TMP8:%.*]] = phi i32 [ 0, [[TMP4]] ], [ [[TMP11:%.*]], [[TMP6]] ]
680; IS________NPM-NEXT:    [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 [[TMP7]]
681; IS________NPM-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4
682; IS________NPM-NEXT:    [[TMP11]] = add nsw i32 [[TMP10]], [[TMP8]]
683; IS________NPM-NEXT:    [[TMP12]] = add nsw i64 [[TMP7]], -1
684; IS________NPM-NEXT:    [[TMP13:%.*]] = icmp sgt i64 [[TMP7]], 0
685; IS________NPM-NEXT:    br i1 [[TMP13]], label [[TMP6]], label [[TMP14]]
686; IS________NPM:       14:
687; IS________NPM-NEXT:    [[TMP15:%.*]] = phi i32 [ 0, [[TMP2:%.*]] ], [ [[TMP11]], [[TMP6]] ]
688; IS________NPM-NEXT:    ret i32 [[TMP15]]
689;
690  %3 = icmp sgt i32 %0, -1
691  br i1 %3, label %4, label %14
692
693; <label>:4:                                      ; preds = %2
694  %5 = sext i32 %0 to i64
695  br label %6
696
697; <label>:6:                                      ; preds = %4, %6
698  %7 = phi i64 [ %5, %4 ], [ %12, %6 ]
699  %8 = phi i32 [ 0, %4 ], [ %11, %6 ]
700  %9 = getelementptr inbounds i32, i32* %1, i64 %7
701  %10 = load i32, i32* %9, align 4
702  %11 = add nsw i32 %10, %8
703  %12 = add nsw i64 %7, -1
704  %13 = icmp sgt i64 %7, 0
705  br i1 %13, label %6, label %14
706
707; <label>:14:                                     ; preds = %6, %2
708  %15 = phi i32 [ 0, %2 ], [ %11, %6 ]
709  ret i32 %15
710}
711
712; TEST 14 (positive case)
713; multiple return
714
715define i32 @multiple_return(i32 %a) #0 {
716; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
717; CHECK-LABEL: define {{[^@]+}}@multiple_return
718; CHECK-SAME: (i32 [[A:%.*]]) #[[ATTR0]] {
719; CHECK-NEXT:    [[B:%.*]] = icmp eq i32 [[A]], 0
720; CHECK-NEXT:    br i1 [[B]], label [[T:%.*]], label [[F:%.*]]
721; CHECK:       t:
722; CHECK-NEXT:    ret i32 1
723; CHECK:       f:
724; CHECK-NEXT:    ret i32 0
725;
726  %b =  icmp eq i32 %a, 0
727  br i1 %b, label %t, label %f
728
729t:
730  ret i32 1
731f:
732  ret i32 0
733}
734
735; TEST 15 (positive & negative case)
736; unreachable exit
737
738; 15.1 (positive case)
739define void @unreachable_exit_positive1() #0 {
740; IS________OPM: Function Attrs: noinline nounwind willreturn uwtable
741; IS________OPM-LABEL: define {{[^@]+}}@unreachable_exit_positive1
742; IS________OPM-SAME: () #[[ATTR10]] {
743; IS________OPM-NEXT:    tail call void @will_return() #[[ATTR28]]
744; IS________OPM-NEXT:    ret void
745; IS________OPM:       unreachable_label:
746; IS________OPM-NEXT:    unreachable
747;
748; IS________NPM: Function Attrs: noinline nounwind willreturn uwtable
749; IS________NPM-LABEL: define {{[^@]+}}@unreachable_exit_positive1
750; IS________NPM-SAME: () #[[ATTR10]] {
751; IS________NPM-NEXT:    tail call void @will_return() #[[ATTR30]]
752; IS________NPM-NEXT:    ret void
753; IS________NPM:       unreachable_label:
754; IS________NPM-NEXT:    unreachable
755;
756  tail call void @will_return()
757  ret void
758
759unreachable_label:
760  tail call void @exit(i32 0)
761  unreachable
762}
763
764define i32 @unreachable_exit_positive2(i32) local_unnamed_addr #0 {
765; IS________OPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable
766; IS________OPM-LABEL: define {{[^@]+}}@unreachable_exit_positive2
767; IS________OPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2]] {
768; IS________OPM-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1
769; IS________OPM-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
770; IS________OPM:       3:
771; IS________OPM-NEXT:    [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ]
772; IS________OPM-NEXT:    ret i32 [[TMP4]]
773; IS________OPM:       5:
774; IS________OPM-NEXT:    [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ]
775; IS________OPM-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ]
776; IS________OPM-NEXT:    [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]]
777; IS________OPM-NEXT:    [[TMP9]] = add nuw nsw i32 [[TMP6]], 1
778; IS________OPM-NEXT:    [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]]
779; IS________OPM-NEXT:    br i1 [[TMP10]], label [[TMP3]], label [[TMP5]]
780; IS________OPM:       unreachable_label:
781; IS________OPM-NEXT:    unreachable
782;
783; IS________NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
784; IS________NPM-LABEL: define {{[^@]+}}@unreachable_exit_positive2
785; IS________NPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] {
786; IS________NPM-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1
787; IS________NPM-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
788; IS________NPM:       3:
789; IS________NPM-NEXT:    [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ]
790; IS________NPM-NEXT:    ret i32 [[TMP4]]
791; IS________NPM:       5:
792; IS________NPM-NEXT:    [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ]
793; IS________NPM-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ]
794; IS________NPM-NEXT:    [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]]
795; IS________NPM-NEXT:    [[TMP9]] = add nuw nsw i32 [[TMP6]], 1
796; IS________NPM-NEXT:    [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]]
797; IS________NPM-NEXT:    br i1 [[TMP10]], label [[TMP3]], label [[TMP5]]
798; IS________NPM:       unreachable_label:
799; IS________NPM-NEXT:    unreachable
800;
801  %2 = icmp slt i32 %0, 1
802  br i1 %2, label %3, label %5
803
804; <label>:3:                                      ; preds = %5, %1
805  %4 = phi i32 [ 1, %1 ], [ %8, %5 ]
806  ret i32 %4
807
808; <label>:5:                                      ; preds = %1, %5
809  %6 = phi i32 [ %9, %5 ], [ 1, %1 ]
810  %7 = phi i32 [ %8, %5 ], [ 1, %1 ]
811  %8 = mul nsw i32 %6, %7
812  %9 = add nuw nsw i32 %6, 1
813  %10 = icmp eq i32 %6, %0
814  br i1 %10, label %3, label %5
815
816unreachable_label:
817  tail call void @exit(i32 0)
818  unreachable
819}
820
821
822;15.2
823
824define void @unreachable_exit_negative1() #0 {
825; CHECK: Function Attrs: noinline nounwind uwtable
826; CHECK-LABEL: define {{[^@]+}}@unreachable_exit_negative1
827; CHECK-SAME: () #[[ATTR7]] {
828; CHECK-NEXT:    tail call void @exit(i32 noundef 0) #[[ATTR5]]
829; CHECK-NEXT:    unreachable
830; CHECK:       unreachable_label:
831; CHECK-NEXT:    unreachable
832;
833  tail call void @exit(i32 0)
834  ret void
835
836unreachable_label:
837  tail call void @exit(i32 0)
838  unreachable
839}
840
841define void @unreachable_exit_negative2() #0 {
842; IS________OPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable
843; IS________OPM-LABEL: define {{[^@]+}}@unreachable_exit_negative2
844; IS________OPM-SAME: () #[[ATTR14:[0-9]+]] {
845; IS________OPM-NEXT:    br label [[L1:%.*]]
846; IS________OPM:       L1:
847; IS________OPM-NEXT:    br label [[L2:%.*]]
848; IS________OPM:       L2:
849; IS________OPM-NEXT:    br label [[L1]]
850; IS________OPM:       unreachable_label:
851; IS________OPM-NEXT:    unreachable
852;
853; IS________NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable
854; IS________NPM-LABEL: define {{[^@]+}}@unreachable_exit_negative2
855; IS________NPM-SAME: () #[[ATTR15:[0-9]+]] {
856; IS________NPM-NEXT:    br label [[L1:%.*]]
857; IS________NPM:       L1:
858; IS________NPM-NEXT:    br label [[L2:%.*]]
859; IS________NPM:       L2:
860; IS________NPM-NEXT:    br label [[L1]]
861; IS________NPM:       unreachable_label:
862; IS________NPM-NEXT:    unreachable
863;
864  br label %L1
865L1:
866  br label %L2
867L2:
868  br label %L1
869
870unreachable_label:
871  tail call void @exit(i32 0)
872  unreachable
873}
874
875; CHECK: Function Attrs: noreturn nounwind
876; CHECK-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*)
877declare void @llvm.eh.sjlj.longjmp(i8*)
878
879define void @call_longjmp(i8* nocapture readnone %0) local_unnamed_addr #0 {
880; CHECK: Function Attrs: noinline nounwind uwtable
881; CHECK-LABEL: define {{[^@]+}}@call_longjmp
882; CHECK-SAME: (i8* nocapture readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR7]] {
883; CHECK-NEXT:    tail call void @llvm.eh.sjlj.longjmp(i8* noalias readnone [[TMP0]]) #[[ATTR5]]
884; CHECK-NEXT:    unreachable
885;
886  tail call void @llvm.eh.sjlj.longjmp(i8* %0)
887  ret void
888}
889
890
891; TEST 16 (negative case)
892; int infinite_loop_inside_bounded_loop(int n) {
893;   int ans = 0;
894;   for (int i = 0; i < n; i++) {
895;     while (1)
896;       ans++;
897;   }
898;   return ans;
899; }
900
901define i32 @infinite_loop_inside_bounded_loop(i32 %n) {
902; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone
903; IS________OPM-LABEL: define {{[^@]+}}@infinite_loop_inside_bounded_loop
904; IS________OPM-SAME: (i32 [[N:%.*]]) #[[ATTR16:[0-9]+]] {
905; IS________OPM-NEXT:  entry:
906; IS________OPM-NEXT:    br label [[FOR_COND:%.*]]
907; IS________OPM:       for.cond:
908; IS________OPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[N]], 0
909; IS________OPM-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
910; IS________OPM:       for.cond.cleanup:
911; IS________OPM-NEXT:    br label [[FOR_END:%.*]]
912; IS________OPM:       for.body:
913; IS________OPM-NEXT:    br label [[WHILE_COND:%.*]]
914; IS________OPM:       while.cond:
915; IS________OPM-NEXT:    br label [[WHILE_BODY:%.*]]
916; IS________OPM:       while.body:
917; IS________OPM-NEXT:    br label [[WHILE_COND]]
918; IS________OPM:       for.inc:
919; IS________OPM-NEXT:    unreachable
920; IS________OPM:       for.end:
921; IS________OPM-NEXT:    ret i32 0
922;
923; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone
924; IS________NPM-LABEL: define {{[^@]+}}@infinite_loop_inside_bounded_loop
925; IS________NPM-SAME: (i32 [[N:%.*]]) #[[ATTR17:[0-9]+]] {
926; IS________NPM-NEXT:  entry:
927; IS________NPM-NEXT:    br label [[FOR_COND:%.*]]
928; IS________NPM:       for.cond:
929; IS________NPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[N]], 0
930; IS________NPM-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
931; IS________NPM:       for.cond.cleanup:
932; IS________NPM-NEXT:    br label [[FOR_END:%.*]]
933; IS________NPM:       for.body:
934; IS________NPM-NEXT:    br label [[WHILE_COND:%.*]]
935; IS________NPM:       while.cond:
936; IS________NPM-NEXT:    br label [[WHILE_BODY:%.*]]
937; IS________NPM:       while.body:
938; IS________NPM-NEXT:    br label [[WHILE_COND]]
939; IS________NPM:       for.inc:
940; IS________NPM-NEXT:    unreachable
941; IS________NPM:       for.end:
942; IS________NPM-NEXT:    ret i32 0
943;
944entry:
945  br label %for.cond
946
947for.cond:                                         ; preds = %for.inc, %entry
948  %cmp = icmp sgt i32 %n, 0
949  br i1 %cmp, label %for.body, label %for.cond.cleanup
950
951for.cond.cleanup:                                 ; preds = %for.cond
952  br label %for.end
953
954for.body:                                         ; preds = %for.cond
955  br label %while.cond
956
957while.cond:                                       ; preds = %while.body, %for.body
958  br label %while.body
959
960while.body:                                       ; preds = %while.cond
961  br label %while.cond
962
963for.inc:                                          ; No predecessors!
964  br label %for.cond
965
966for.end:                                          ; preds = %for.cond.cleanup
967  ret i32 0
968}
969
970
971; TEST 17 (positive case)
972; Nested loops with constant max trip count
973; int bounded_nested_loops(int n) {
974;   int ans = 0;
975;   for (int i = 0; i < n; i++) {
976;     while (n--) {
977;       ans++;
978;     }
979;   }
980;   return ans;
981; }
982
983define i32 @bounded_nested_loops(i32 %n) {
984; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone
985; IS________OPM-LABEL: define {{[^@]+}}@bounded_nested_loops
986; IS________OPM-SAME: (i32 [[N:%.*]]) #[[ATTR16]] {
987; IS________OPM-NEXT:  entry:
988; IS________OPM-NEXT:    br label [[FOR_COND:%.*]]
989; IS________OPM:       for.cond:
990; IS________OPM-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC1:%.*]], [[FOR_INC:%.*]] ]
991; IS________OPM-NEXT:    [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP:%.*]], [[FOR_INC]] ]
992; IS________OPM-NEXT:    [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[FOR_INC]] ]
993; IS________OPM-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N_ADDR_0]]
994; IS________OPM-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
995; IS________OPM:       for.cond.cleanup:
996; IS________OPM-NEXT:    [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[FOR_COND]] ]
997; IS________OPM-NEXT:    br label [[FOR_END:%.*]]
998; IS________OPM:       for.body:
999; IS________OPM-NEXT:    br label [[WHILE_COND:%.*]]
1000; IS________OPM:       while.cond:
1001; IS________OPM-NEXT:    br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]]
1002; IS________OPM:       while.body:
1003; IS________OPM-NEXT:    unreachable
1004; IS________OPM:       while.end:
1005; IS________OPM-NEXT:    [[TMP]] = add i32 [[N_ADDR_0]], [[ANS_0]]
1006; IS________OPM-NEXT:    br label [[FOR_INC]]
1007; IS________OPM:       for.inc:
1008; IS________OPM-NEXT:    [[INC1]] = add nuw nsw i32 [[I_0]], 1
1009; IS________OPM-NEXT:    br label [[FOR_COND]]
1010; IS________OPM:       for.end:
1011; IS________OPM-NEXT:    ret i32 [[ANS_0_LCSSA]]
1012;
1013; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
1014; IS________NPM-LABEL: define {{[^@]+}}@bounded_nested_loops
1015; IS________NPM-SAME: (i32 [[N:%.*]]) #[[ATTR18:[0-9]+]] {
1016; IS________NPM-NEXT:  entry:
1017; IS________NPM-NEXT:    br label [[FOR_COND:%.*]]
1018; IS________NPM:       for.cond:
1019; IS________NPM-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC1:%.*]], [[FOR_INC:%.*]] ]
1020; IS________NPM-NEXT:    [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP:%.*]], [[FOR_INC]] ]
1021; IS________NPM-NEXT:    [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[FOR_INC]] ]
1022; IS________NPM-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N_ADDR_0]]
1023; IS________NPM-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1024; IS________NPM:       for.cond.cleanup:
1025; IS________NPM-NEXT:    [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[FOR_COND]] ]
1026; IS________NPM-NEXT:    br label [[FOR_END:%.*]]
1027; IS________NPM:       for.body:
1028; IS________NPM-NEXT:    br label [[WHILE_COND:%.*]]
1029; IS________NPM:       while.cond:
1030; IS________NPM-NEXT:    br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]]
1031; IS________NPM:       while.body:
1032; IS________NPM-NEXT:    unreachable
1033; IS________NPM:       while.end:
1034; IS________NPM-NEXT:    [[TMP]] = add i32 [[N_ADDR_0]], [[ANS_0]]
1035; IS________NPM-NEXT:    br label [[FOR_INC]]
1036; IS________NPM:       for.inc:
1037; IS________NPM-NEXT:    [[INC1]] = add nuw nsw i32 [[I_0]], 1
1038; IS________NPM-NEXT:    br label [[FOR_COND]]
1039; IS________NPM:       for.end:
1040; IS________NPM-NEXT:    ret i32 [[ANS_0_LCSSA]]
1041;
1042entry:
1043  br label %for.cond
1044
1045for.cond:                                         ; preds = %for.inc, %entry
1046  %i.0 = phi i32 [ 0, %entry ], [ %inc1, %for.inc ]
1047  %ans.0 = phi i32 [ 0, %entry ], [ %tmp, %for.inc ]
1048  %n.addr.0 = phi i32 [ %n, %entry ], [ -1, %for.inc ]
1049  %cmp = icmp slt i32 %i.0, %n.addr.0
1050  br i1 %cmp, label %for.body, label %for.cond.cleanup
1051
1052for.cond.cleanup:                                 ; preds = %for.cond
1053  %ans.0.lcssa = phi i32 [ %ans.0, %for.cond ]
1054  br label %for.end
1055
1056for.body:                                         ; preds = %for.cond
1057  br label %while.cond
1058
1059while.cond:                                       ; preds = %while.body, %for.body
1060  br i1 true, label %while.end, label %while.body
1061
1062while.body:                                       ; preds = %while.cond
1063  br label %while.cond
1064
1065while.end:                                        ; preds = %while.cond
1066  %tmp = add i32 %n.addr.0, %ans.0
1067  br label %for.inc
1068
1069for.inc:                                          ; preds = %while.end
1070  %inc1 = add nuw nsw i32 %i.0, 1
1071  br label %for.cond
1072
1073for.end:                                          ; preds = %for.cond.cleanup
1074  ret i32 %ans.0.lcssa
1075}
1076
1077
1078; TEST 18 (negative case)
1079; int bounded_loop_inside_unbounded_loop(int n) {
1080;   int ans = 0;
1081;   while (n++) {
1082;     for (int i = 0; i < n; i++) {
1083;       ans++;
1084;     }
1085;   }
1086;   return ans;
1087; }
1088
1089define i32 @bounded_loop_inside_unbounded_loop(i32 %n) {
1090; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone
1091; IS________OPM-LABEL: define {{[^@]+}}@bounded_loop_inside_unbounded_loop
1092; IS________OPM-SAME: (i32 [[N:%.*]]) #[[ATTR16]] {
1093; IS________OPM-NEXT:  entry:
1094; IS________OPM-NEXT:    br label [[WHILE_COND:%.*]]
1095; IS________OPM:       while.cond:
1096; IS________OPM-NEXT:    [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2:%.*]], [[FOR_END:%.*]] ]
1097; IS________OPM-NEXT:    [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[INC:%.*]], [[FOR_END]] ]
1098; IS________OPM-NEXT:    [[TMP:%.*]] = icmp sgt i32 [[N_ADDR_0]], -1
1099; IS________OPM-NEXT:    [[SMAX:%.*]] = select i1 [[TMP]], i32 [[N_ADDR_0]], i32 -1
1100; IS________OPM-NEXT:    [[INC]] = add nsw i32 [[N_ADDR_0]], 1
1101; IS________OPM-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0
1102; IS________OPM-NEXT:    br i1 [[TOBOOL]], label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]]
1103; IS________OPM:       while.body:
1104; IS________OPM-NEXT:    [[TMP1:%.*]] = add i32 [[ANS_0]], 1
1105; IS________OPM-NEXT:    br label [[FOR_COND:%.*]]
1106; IS________OPM:       for.cond:
1107; IS________OPM-NEXT:    br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY:%.*]]
1108; IS________OPM:       for.cond.cleanup:
1109; IS________OPM-NEXT:    [[TMP2]] = add i32 [[TMP1]], [[SMAX]]
1110; IS________OPM-NEXT:    br label [[FOR_END]]
1111; IS________OPM:       for.body:
1112; IS________OPM-NEXT:    unreachable
1113; IS________OPM:       for.inc:
1114; IS________OPM-NEXT:    unreachable
1115; IS________OPM:       for.end:
1116; IS________OPM-NEXT:    br label [[WHILE_COND]]
1117; IS________OPM:       while.end:
1118; IS________OPM-NEXT:    [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ]
1119; IS________OPM-NEXT:    ret i32 [[ANS_0_LCSSA]]
1120;
1121; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone
1122; IS________NPM-LABEL: define {{[^@]+}}@bounded_loop_inside_unbounded_loop
1123; IS________NPM-SAME: (i32 [[N:%.*]]) #[[ATTR17]] {
1124; IS________NPM-NEXT:  entry:
1125; IS________NPM-NEXT:    br label [[WHILE_COND:%.*]]
1126; IS________NPM:       while.cond:
1127; IS________NPM-NEXT:    [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2:%.*]], [[FOR_END:%.*]] ]
1128; IS________NPM-NEXT:    [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[INC:%.*]], [[FOR_END]] ]
1129; IS________NPM-NEXT:    [[TMP:%.*]] = icmp sgt i32 [[N_ADDR_0]], -1
1130; IS________NPM-NEXT:    [[SMAX:%.*]] = select i1 [[TMP]], i32 [[N_ADDR_0]], i32 -1
1131; IS________NPM-NEXT:    [[INC]] = add nsw i32 [[N_ADDR_0]], 1
1132; IS________NPM-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0
1133; IS________NPM-NEXT:    br i1 [[TOBOOL]], label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]]
1134; IS________NPM:       while.body:
1135; IS________NPM-NEXT:    [[TMP1:%.*]] = add i32 [[ANS_0]], 1
1136; IS________NPM-NEXT:    br label [[FOR_COND:%.*]]
1137; IS________NPM:       for.cond:
1138; IS________NPM-NEXT:    br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY:%.*]]
1139; IS________NPM:       for.cond.cleanup:
1140; IS________NPM-NEXT:    [[TMP2]] = add i32 [[TMP1]], [[SMAX]]
1141; IS________NPM-NEXT:    br label [[FOR_END]]
1142; IS________NPM:       for.body:
1143; IS________NPM-NEXT:    unreachable
1144; IS________NPM:       for.inc:
1145; IS________NPM-NEXT:    unreachable
1146; IS________NPM:       for.end:
1147; IS________NPM-NEXT:    br label [[WHILE_COND]]
1148; IS________NPM:       while.end:
1149; IS________NPM-NEXT:    [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ]
1150; IS________NPM-NEXT:    ret i32 [[ANS_0_LCSSA]]
1151;
1152entry:
1153  br label %while.cond
1154
1155while.cond:                                       ; preds = %for.end, %entry
1156  %ans.0 = phi i32 [ 0, %entry ], [ %tmp2, %for.end ]
1157  %n.addr.0 = phi i32 [ %n, %entry ], [ %inc, %for.end ]
1158  %tmp = icmp sgt i32 %n.addr.0, -1
1159  %smax = select i1 %tmp, i32 %n.addr.0, i32 -1
1160  %inc = add nsw i32 %n.addr.0, 1
1161  %tobool = icmp eq i32 %n.addr.0, 0
1162  br i1 %tobool, label %while.end, label %while.body
1163
1164while.body:                                       ; preds = %while.cond
1165  %tmp1 = add i32 %ans.0, 1
1166  br label %for.cond
1167
1168for.cond:                                         ; preds = %for.inc, %while.body
1169  br i1 true, label %for.cond.cleanup, label %for.body
1170
1171for.cond.cleanup:                                 ; preds = %for.cond
1172  %tmp2 = add i32 %tmp1, %smax
1173  br label %for.end
1174
1175for.body:                                         ; preds = %for.cond
1176  br label %for.inc
1177
1178for.inc:                                          ; preds = %for.body
1179  br label %for.cond
1180
1181for.end:                                          ; preds = %for.cond.cleanup
1182  br label %while.cond
1183
1184while.end:                                        ; preds = %while.cond
1185  %ans.0.lcssa = phi i32 [ %ans.0, %while.cond ]
1186  ret i32 %ans.0.lcssa
1187}
1188
1189
1190; TEST 19 (negative case)
1191; int nested_unbounded_loops(int n) {
1192;   int ans = 0;
1193;   while (n--) {
1194;     while (n--) {
1195;       ans++;
1196;     }
1197;     while (n--) {
1198;       ans++;
1199;     }
1200;   }
1201;   return ans;
1202; }
1203
1204define i32 @nested_unbounded_loops(i32 %n) {
1205; IS________OPM: Function Attrs: nofree norecurse nosync nounwind readnone
1206; IS________OPM-LABEL: define {{[^@]+}}@nested_unbounded_loops
1207; IS________OPM-SAME: (i32 [[N:%.*]]) #[[ATTR16]] {
1208; IS________OPM-NEXT:  entry:
1209; IS________OPM-NEXT:    br label [[WHILE_COND:%.*]]
1210; IS________OPM:       while.cond:
1211; IS________OPM-NEXT:    [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP1:%.*]], [[WHILE_END10:%.*]] ]
1212; IS________OPM-NEXT:    [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[WHILE_END10]] ]
1213; IS________OPM-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0
1214; IS________OPM-NEXT:    br i1 [[TOBOOL]], label [[WHILE_END11:%.*]], label [[WHILE_BODY:%.*]]
1215; IS________OPM:       while.body:
1216; IS________OPM-NEXT:    br label [[WHILE_COND1:%.*]]
1217; IS________OPM:       while.cond1:
1218; IS________OPM-NEXT:    br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY4:%.*]]
1219; IS________OPM:       while.body4:
1220; IS________OPM-NEXT:    unreachable
1221; IS________OPM:       while.end:
1222; IS________OPM-NEXT:    [[TMP:%.*]] = add i32 [[N_ADDR_0]], -2
1223; IS________OPM-NEXT:    br label [[WHILE_COND5:%.*]]
1224; IS________OPM:       while.cond5:
1225; IS________OPM-NEXT:    br i1 true, label [[WHILE_END10]], label [[WHILE_BODY8:%.*]]
1226; IS________OPM:       while.body8:
1227; IS________OPM-NEXT:    unreachable
1228; IS________OPM:       while.end10:
1229; IS________OPM-NEXT:    [[TMP1]] = add i32 [[TMP]], [[ANS_0]]
1230; IS________OPM-NEXT:    br label [[WHILE_COND]]
1231; IS________OPM:       while.end11:
1232; IS________OPM-NEXT:    [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ]
1233; IS________OPM-NEXT:    ret i32 [[ANS_0_LCSSA]]
1234;
1235; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readnone
1236; IS________NPM-LABEL: define {{[^@]+}}@nested_unbounded_loops
1237; IS________NPM-SAME: (i32 [[N:%.*]]) #[[ATTR17]] {
1238; IS________NPM-NEXT:  entry:
1239; IS________NPM-NEXT:    br label [[WHILE_COND:%.*]]
1240; IS________NPM:       while.cond:
1241; IS________NPM-NEXT:    [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP1:%.*]], [[WHILE_END10:%.*]] ]
1242; IS________NPM-NEXT:    [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[WHILE_END10]] ]
1243; IS________NPM-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0
1244; IS________NPM-NEXT:    br i1 [[TOBOOL]], label [[WHILE_END11:%.*]], label [[WHILE_BODY:%.*]]
1245; IS________NPM:       while.body:
1246; IS________NPM-NEXT:    br label [[WHILE_COND1:%.*]]
1247; IS________NPM:       while.cond1:
1248; IS________NPM-NEXT:    br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY4:%.*]]
1249; IS________NPM:       while.body4:
1250; IS________NPM-NEXT:    unreachable
1251; IS________NPM:       while.end:
1252; IS________NPM-NEXT:    [[TMP:%.*]] = add i32 [[N_ADDR_0]], -2
1253; IS________NPM-NEXT:    br label [[WHILE_COND5:%.*]]
1254; IS________NPM:       while.cond5:
1255; IS________NPM-NEXT:    br i1 true, label [[WHILE_END10]], label [[WHILE_BODY8:%.*]]
1256; IS________NPM:       while.body8:
1257; IS________NPM-NEXT:    unreachable
1258; IS________NPM:       while.end10:
1259; IS________NPM-NEXT:    [[TMP1]] = add i32 [[TMP]], [[ANS_0]]
1260; IS________NPM-NEXT:    br label [[WHILE_COND]]
1261; IS________NPM:       while.end11:
1262; IS________NPM-NEXT:    [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ]
1263; IS________NPM-NEXT:    ret i32 [[ANS_0_LCSSA]]
1264;
1265entry:
1266  br label %while.cond
1267
1268while.cond:                                       ; preds = %while.end10, %entry
1269  %ans.0 = phi i32 [ 0, %entry ], [ %tmp1, %while.end10 ]
1270  %n.addr.0 = phi i32 [ %n, %entry ], [ -1, %while.end10 ]
1271  %tobool = icmp eq i32 %n.addr.0, 0
1272  br i1 %tobool, label %while.end11, label %while.body
1273
1274while.body:                                       ; preds = %while.cond
1275  br label %while.cond1
1276
1277while.cond1:                                      ; preds = %while.body4, %while.body
1278  br i1 true, label %while.end, label %while.body4
1279
1280while.body4:                                      ; preds = %while.cond1
1281  br label %while.cond1
1282
1283while.end:                                        ; preds = %while.cond1
1284  %tmp = add i32 %n.addr.0, -2
1285  br label %while.cond5
1286
1287while.cond5:                                      ; preds = %while.body8, %while.end
1288  br i1 true, label %while.end10, label %while.body8
1289
1290while.body8:                                      ; preds = %while.cond5
1291  br label %while.cond5
1292
1293while.end10:                                      ; preds = %while.cond5
1294  %tmp1 = add i32 %tmp, %ans.0
1295  br label %while.cond
1296
1297while.end11:                                      ; preds = %while.cond
1298  %ans.0.lcssa = phi i32 [ %ans.0, %while.cond ]
1299  ret i32 %ans.0.lcssa
1300}
1301
1302
1303; TEST 20 (negative case)
1304;    void non_loop_cycle(int n) {
1305;      if (fact_loop(n)>5)
1306;        goto entry1;
1307;      else
1308;        goto entry2;
1309;
1310;    entry1:
1311;      if (fact_loop(n)>5)
1312;        goto exit;
1313;      else
1314;        goto entry2;
1315;    entry2:
1316;      if (fact_loop(n)>5)
1317;        goto exit;
1318;      else
1319;        goto entry1;
1320;    exit:
1321;      return;
1322;    }
1323
1324define void @non_loop_cycle(i32 %n) {
1325; IS__TUNIT_OPM: Function Attrs: nofree norecurse nosync nounwind readnone
1326; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@non_loop_cycle
1327; IS__TUNIT_OPM-SAME: (i32 [[N:%.*]]) #[[ATTR16]] {
1328; IS__TUNIT_OPM-NEXT:  entry:
1329; IS__TUNIT_OPM-NEXT:    [[CALL:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR24]]
1330; IS__TUNIT_OPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CALL]], 5
1331; IS__TUNIT_OPM-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1332; IS__TUNIT_OPM:       if.then:
1333; IS__TUNIT_OPM-NEXT:    br label [[ENTRY1:%.*]]
1334; IS__TUNIT_OPM:       if.else:
1335; IS__TUNIT_OPM-NEXT:    br label [[ENTRY2:%.*]]
1336; IS__TUNIT_OPM:       entry1:
1337; IS__TUNIT_OPM-NEXT:    [[CALL1:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR24]]
1338; IS__TUNIT_OPM-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[CALL1]], 5
1339; IS__TUNIT_OPM-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]]
1340; IS__TUNIT_OPM:       if.then3:
1341; IS__TUNIT_OPM-NEXT:    br label [[EXIT:%.*]]
1342; IS__TUNIT_OPM:       if.else4:
1343; IS__TUNIT_OPM-NEXT:    br label [[ENTRY2]]
1344; IS__TUNIT_OPM:       entry2:
1345; IS__TUNIT_OPM-NEXT:    [[CALL5:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR24]]
1346; IS__TUNIT_OPM-NEXT:    [[CMP6:%.*]] = icmp sgt i32 [[CALL5]], 5
1347; IS__TUNIT_OPM-NEXT:    br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_ELSE8:%.*]]
1348; IS__TUNIT_OPM:       if.then7:
1349; IS__TUNIT_OPM-NEXT:    br label [[EXIT]]
1350; IS__TUNIT_OPM:       if.else8:
1351; IS__TUNIT_OPM-NEXT:    br label [[ENTRY1]]
1352; IS__TUNIT_OPM:       exit:
1353; IS__TUNIT_OPM-NEXT:    ret void
1354;
1355; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readnone
1356; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@non_loop_cycle
1357; IS__TUNIT_NPM-SAME: (i32 [[N:%.*]]) #[[ATTR17]] {
1358; IS__TUNIT_NPM-NEXT:  entry:
1359; IS__TUNIT_NPM-NEXT:    [[CALL:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR26]]
1360; IS__TUNIT_NPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CALL]], 5
1361; IS__TUNIT_NPM-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1362; IS__TUNIT_NPM:       if.then:
1363; IS__TUNIT_NPM-NEXT:    br label [[ENTRY1:%.*]]
1364; IS__TUNIT_NPM:       if.else:
1365; IS__TUNIT_NPM-NEXT:    br label [[ENTRY2:%.*]]
1366; IS__TUNIT_NPM:       entry1:
1367; IS__TUNIT_NPM-NEXT:    [[CALL1:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR26]]
1368; IS__TUNIT_NPM-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[CALL1]], 5
1369; IS__TUNIT_NPM-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]]
1370; IS__TUNIT_NPM:       if.then3:
1371; IS__TUNIT_NPM-NEXT:    br label [[EXIT:%.*]]
1372; IS__TUNIT_NPM:       if.else4:
1373; IS__TUNIT_NPM-NEXT:    br label [[ENTRY2]]
1374; IS__TUNIT_NPM:       entry2:
1375; IS__TUNIT_NPM-NEXT:    [[CALL5:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR26]]
1376; IS__TUNIT_NPM-NEXT:    [[CMP6:%.*]] = icmp sgt i32 [[CALL5]], 5
1377; IS__TUNIT_NPM-NEXT:    br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_ELSE8:%.*]]
1378; IS__TUNIT_NPM:       if.then7:
1379; IS__TUNIT_NPM-NEXT:    br label [[EXIT]]
1380; IS__TUNIT_NPM:       if.else8:
1381; IS__TUNIT_NPM-NEXT:    br label [[ENTRY1]]
1382; IS__TUNIT_NPM:       exit:
1383; IS__TUNIT_NPM-NEXT:    ret void
1384;
1385; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone
1386; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@non_loop_cycle
1387; IS__CGSCC_OPM-SAME: (i32 [[N:%.*]]) #[[ATTR17]] {
1388; IS__CGSCC_OPM-NEXT:  entry:
1389; IS__CGSCC_OPM-NEXT:    [[CALL:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR29:[0-9]+]]
1390; IS__CGSCC_OPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CALL]], 5
1391; IS__CGSCC_OPM-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1392; IS__CGSCC_OPM:       if.then:
1393; IS__CGSCC_OPM-NEXT:    br label [[ENTRY1:%.*]]
1394; IS__CGSCC_OPM:       if.else:
1395; IS__CGSCC_OPM-NEXT:    br label [[ENTRY2:%.*]]
1396; IS__CGSCC_OPM:       entry1:
1397; IS__CGSCC_OPM-NEXT:    [[CALL1:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR29]]
1398; IS__CGSCC_OPM-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[CALL1]], 5
1399; IS__CGSCC_OPM-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]]
1400; IS__CGSCC_OPM:       if.then3:
1401; IS__CGSCC_OPM-NEXT:    br label [[EXIT:%.*]]
1402; IS__CGSCC_OPM:       if.else4:
1403; IS__CGSCC_OPM-NEXT:    br label [[ENTRY2]]
1404; IS__CGSCC_OPM:       entry2:
1405; IS__CGSCC_OPM-NEXT:    [[CALL5:%.*]] = call i32 @fact_loop(i32 [[N]]) #[[ATTR29]]
1406; IS__CGSCC_OPM-NEXT:    [[CMP6:%.*]] = icmp sgt i32 [[CALL5]], 5
1407; IS__CGSCC_OPM-NEXT:    br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_ELSE8:%.*]]
1408; IS__CGSCC_OPM:       if.then7:
1409; IS__CGSCC_OPM-NEXT:    br label [[EXIT]]
1410; IS__CGSCC_OPM:       if.else8:
1411; IS__CGSCC_OPM-NEXT:    br label [[ENTRY1]]
1412; IS__CGSCC_OPM:       exit:
1413; IS__CGSCC_OPM-NEXT:    ret void
1414;
1415; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone
1416; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@non_loop_cycle
1417; IS__CGSCC_NPM-SAME: (i32 [[N:%.*]]) #[[ATTR19]] {
1418; IS__CGSCC_NPM-NEXT:  entry:
1419; IS__CGSCC_NPM-NEXT:    [[CALL:%.*]] = call i32 @fact_loop(i32 [[N]])
1420; IS__CGSCC_NPM-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[CALL]], 5
1421; IS__CGSCC_NPM-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1422; IS__CGSCC_NPM:       if.then:
1423; IS__CGSCC_NPM-NEXT:    br label [[ENTRY1:%.*]]
1424; IS__CGSCC_NPM:       if.else:
1425; IS__CGSCC_NPM-NEXT:    br label [[ENTRY2:%.*]]
1426; IS__CGSCC_NPM:       entry1:
1427; IS__CGSCC_NPM-NEXT:    [[CALL1:%.*]] = call i32 @fact_loop(i32 [[N]])
1428; IS__CGSCC_NPM-NEXT:    [[CMP2:%.*]] = icmp sgt i32 [[CALL1]], 5
1429; IS__CGSCC_NPM-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]]
1430; IS__CGSCC_NPM:       if.then3:
1431; IS__CGSCC_NPM-NEXT:    br label [[EXIT:%.*]]
1432; IS__CGSCC_NPM:       if.else4:
1433; IS__CGSCC_NPM-NEXT:    br label [[ENTRY2]]
1434; IS__CGSCC_NPM:       entry2:
1435; IS__CGSCC_NPM-NEXT:    [[CALL5:%.*]] = call i32 @fact_loop(i32 [[N]])
1436; IS__CGSCC_NPM-NEXT:    [[CMP6:%.*]] = icmp sgt i32 [[CALL5]], 5
1437; IS__CGSCC_NPM-NEXT:    br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_ELSE8:%.*]]
1438; IS__CGSCC_NPM:       if.then7:
1439; IS__CGSCC_NPM-NEXT:    br label [[EXIT]]
1440; IS__CGSCC_NPM:       if.else8:
1441; IS__CGSCC_NPM-NEXT:    br label [[ENTRY1]]
1442; IS__CGSCC_NPM:       exit:
1443; IS__CGSCC_NPM-NEXT:    ret void
1444;
1445entry:
1446  %call = call i32 @fact_loop(i32 %n)
1447  %cmp = icmp sgt i32 %call, 5
1448  br i1 %cmp, label %if.then, label %if.else
1449
1450if.then:                                          ; preds = %entry
1451  br label %entry1
1452
1453if.else:                                          ; preds = %entry
1454  br label %entry2
1455
1456entry1:                                           ; preds = %if.else8, %if.then
1457  %call1 = call i32 @fact_loop(i32 %n)
1458  %cmp2 = icmp sgt i32 %call1, 5
1459  br i1 %cmp2, label %if.then3, label %if.else4
1460
1461if.then3:                                         ; preds = %entry1
1462  br label %exit
1463
1464if.else4:                                         ; preds = %entry1
1465  br label %entry2
1466
1467entry2:                                           ; preds = %if.else4, %if.else
1468  %call5 = call i32 @fact_loop(i32 %n)
1469  %cmp6 = icmp sgt i32 %call5, 5
1470  br i1 %cmp6, label %if.then7, label %if.else8
1471
1472if.then7:                                         ; preds = %entry2
1473  br label %exit
1474
1475if.else8:                                         ; preds = %entry2
1476  br label %entry1
1477
1478exit:                                             ; preds = %if.then7, %if.then3
1479  ret void
1480}
1481
1482declare void @unknown()
1483declare void @readonly() readonly
1484declare void @readnone() readnone
1485declare void @unknown_mustprogress() mustprogress
1486declare void @readonly_mustprogress() readonly mustprogress
1487
1488define void @willreturn_mustprogress_caller_1() mustprogress {
1489; IS__TUNIT_OPM: Function Attrs: mustprogress
1490; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_1
1491; IS__TUNIT_OPM-SAME: () #[[ATTR19:[0-9]+]] {
1492; IS__TUNIT_OPM-NEXT:    call void @unknown()
1493; IS__TUNIT_OPM-NEXT:    ret void
1494;
1495; IS__TUNIT_NPM: Function Attrs: mustprogress
1496; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_1
1497; IS__TUNIT_NPM-SAME: () #[[ATTR21:[0-9]+]] {
1498; IS__TUNIT_NPM-NEXT:    call void @unknown()
1499; IS__TUNIT_NPM-NEXT:    ret void
1500;
1501; IS__CGSCC_OPM: Function Attrs: mustprogress
1502; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_1
1503; IS__CGSCC_OPM-SAME: () #[[ATTR20:[0-9]+]] {
1504; IS__CGSCC_OPM-NEXT:    call void @unknown()
1505; IS__CGSCC_OPM-NEXT:    ret void
1506;
1507; IS__CGSCC_NPM: Function Attrs: mustprogress
1508; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_1
1509; IS__CGSCC_NPM-SAME: () #[[ATTR22:[0-9]+]] {
1510; IS__CGSCC_NPM-NEXT:    call void @unknown()
1511; IS__CGSCC_NPM-NEXT:    ret void
1512;
1513  call void @unknown()
1514  ret void
1515}
1516define void @willreturn_mustprogress_caller_2() mustprogress {
1517; IS__TUNIT_OPM: Function Attrs: mustprogress readonly willreturn
1518; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_2
1519; IS__TUNIT_OPM-SAME: () #[[ATTR21:[0-9]+]] {
1520; IS__TUNIT_OPM-NEXT:    call void @readonly() #[[ATTR17:[0-9]+]]
1521; IS__TUNIT_OPM-NEXT:    ret void
1522;
1523; IS__TUNIT_NPM: Function Attrs: mustprogress readonly willreturn
1524; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_2
1525; IS__TUNIT_NPM-SAME: () #[[ATTR23:[0-9]+]] {
1526; IS__TUNIT_NPM-NEXT:    call void @readonly() #[[ATTR19:[0-9]+]]
1527; IS__TUNIT_NPM-NEXT:    ret void
1528;
1529; IS__CGSCC_OPM: Function Attrs: mustprogress readonly willreturn
1530; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_2
1531; IS__CGSCC_OPM-SAME: () #[[ATTR22:[0-9]+]] {
1532; IS__CGSCC_OPM-NEXT:    call void @readonly() #[[ATTR18:[0-9]+]]
1533; IS__CGSCC_OPM-NEXT:    ret void
1534;
1535; IS__CGSCC_NPM: Function Attrs: mustprogress readonly willreturn
1536; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_2
1537; IS__CGSCC_NPM-SAME: () #[[ATTR24:[0-9]+]] {
1538; IS__CGSCC_NPM-NEXT:    call void @readonly() #[[ATTR20:[0-9]+]]
1539; IS__CGSCC_NPM-NEXT:    ret void
1540;
1541  call void @readonly()
1542  ret void
1543}
1544define void @willreturn_mustprogress_caller_3() mustprogress {
1545; IS__TUNIT_OPM: Function Attrs: mustprogress nosync readnone willreturn
1546; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_3
1547; IS__TUNIT_OPM-SAME: () #[[ATTR22:[0-9]+]] {
1548; IS__TUNIT_OPM-NEXT:    call void @readnone()
1549; IS__TUNIT_OPM-NEXT:    ret void
1550;
1551; IS__TUNIT_NPM: Function Attrs: mustprogress nosync readnone willreturn
1552; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_3
1553; IS__TUNIT_NPM-SAME: () #[[ATTR24:[0-9]+]] {
1554; IS__TUNIT_NPM-NEXT:    call void @readnone()
1555; IS__TUNIT_NPM-NEXT:    ret void
1556;
1557; IS__CGSCC_OPM: Function Attrs: mustprogress nosync readnone willreturn
1558; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_3
1559; IS__CGSCC_OPM-SAME: () #[[ATTR23:[0-9]+]] {
1560; IS__CGSCC_OPM-NEXT:    call void @readnone()
1561; IS__CGSCC_OPM-NEXT:    ret void
1562;
1563; IS__CGSCC_NPM: Function Attrs: mustprogress nosync readnone willreturn
1564; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_caller_3
1565; IS__CGSCC_NPM-SAME: () #[[ATTR25:[0-9]+]] {
1566; IS__CGSCC_NPM-NEXT:    call void @readnone()
1567; IS__CGSCC_NPM-NEXT:    ret void
1568;
1569  call void @readnone()
1570  ret void
1571}
1572define void @willreturn_mustprogress_callee_1() {
1573; CHECK-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_1() {
1574; CHECK-NEXT:    call void @unknown_mustprogress()
1575; CHECK-NEXT:    ret void
1576;
1577  call void @unknown_mustprogress()
1578  ret void
1579}
1580define void @willreturn_mustprogress_callee_2() {
1581; IS__TUNIT_OPM: Function Attrs: readonly willreturn
1582; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_2
1583; IS__TUNIT_OPM-SAME: () #[[ATTR23:[0-9]+]] {
1584; IS__TUNIT_OPM-NEXT:    call void @readonly_mustprogress() #[[ATTR23]]
1585; IS__TUNIT_OPM-NEXT:    ret void
1586;
1587; IS__TUNIT_NPM: Function Attrs: readonly willreturn
1588; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_2
1589; IS__TUNIT_NPM-SAME: () #[[ATTR25:[0-9]+]] {
1590; IS__TUNIT_NPM-NEXT:    call void @readonly_mustprogress() #[[ATTR25]]
1591; IS__TUNIT_NPM-NEXT:    ret void
1592;
1593; IS__CGSCC_OPM: Function Attrs: readonly willreturn
1594; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_2
1595; IS__CGSCC_OPM-SAME: () #[[ATTR24:[0-9]+]] {
1596; IS__CGSCC_OPM-NEXT:    call void @readonly_mustprogress() #[[ATTR24]]
1597; IS__CGSCC_OPM-NEXT:    ret void
1598;
1599; IS__CGSCC_NPM: Function Attrs: readonly willreturn
1600; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_2
1601; IS__CGSCC_NPM-SAME: () #[[ATTR26:[0-9]+]] {
1602; IS__CGSCC_NPM-NEXT:    call void @readonly_mustprogress() #[[ATTR26]]
1603; IS__CGSCC_NPM-NEXT:    ret void
1604;
1605  call void @readonly_mustprogress()
1606  ret void
1607}
1608define void @willreturn_mustprogress_callee_3() {
1609; CHECK-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_3() {
1610; CHECK-NEXT:    call void @willreturn_mustprogress_callee_1()
1611; CHECK-NEXT:    ret void
1612;
1613  call void @willreturn_mustprogress_callee_1()
1614  ret void
1615}
1616define void @willreturn_mustprogress_callee_4() {
1617; IS__TUNIT_OPM: Function Attrs: readonly willreturn
1618; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_4
1619; IS__TUNIT_OPM-SAME: () #[[ATTR23]] {
1620; IS__TUNIT_OPM-NEXT:    call void @willreturn_mustprogress_callee_2() #[[ATTR23]]
1621; IS__TUNIT_OPM-NEXT:    ret void
1622;
1623; IS__TUNIT_NPM: Function Attrs: readonly willreturn
1624; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_4
1625; IS__TUNIT_NPM-SAME: () #[[ATTR25]] {
1626; IS__TUNIT_NPM-NEXT:    call void @willreturn_mustprogress_callee_2() #[[ATTR25]]
1627; IS__TUNIT_NPM-NEXT:    ret void
1628;
1629; IS__CGSCC_OPM: Function Attrs: readonly willreturn
1630; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_4
1631; IS__CGSCC_OPM-SAME: () #[[ATTR24]] {
1632; IS__CGSCC_OPM-NEXT:    call void @willreturn_mustprogress_callee_2() #[[ATTR24]]
1633; IS__CGSCC_OPM-NEXT:    ret void
1634;
1635; IS__CGSCC_NPM: Function Attrs: readonly willreturn
1636; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@willreturn_mustprogress_callee_4
1637; IS__CGSCC_NPM-SAME: () #[[ATTR26]] {
1638; IS__CGSCC_NPM-NEXT:    call void @willreturn_mustprogress_callee_2() #[[ATTR26]]
1639; IS__CGSCC_NPM-NEXT:    ret void
1640;
1641  call void @willreturn_mustprogress_callee_2()
1642  ret void
1643}
1644
1645attributes #0 = { nounwind uwtable noinline }
1646attributes #1 = { uwtable noinline }
1647;.
1648; IS__TUNIT_OPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable }
1649; IS__TUNIT_OPM: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable }
1650; IS__TUNIT_OPM: attributes #[[ATTR2]] = { nofree noinline norecurse nosync nounwind readnone uwtable }
1651; IS__TUNIT_OPM: attributes #[[ATTR3:[0-9]+]] = { nofree nosync nounwind willreturn }
1652; IS__TUNIT_OPM: attributes #[[ATTR4]] = { nofree noinline nosync nounwind uwtable }
1653; IS__TUNIT_OPM: attributes #[[ATTR5]] = { noreturn }
1654; IS__TUNIT_OPM: attributes #[[ATTR6]] = { noinline noreturn nounwind uwtable }
1655; IS__TUNIT_OPM: attributes #[[ATTR7]] = { noinline nounwind uwtable }
1656; IS__TUNIT_OPM: attributes #[[ATTR8:[0-9]+]] = { nocallback nofree nosync nounwind readnone speculatable willreturn }
1657; IS__TUNIT_OPM: attributes #[[ATTR9:[0-9]+]] = { norecurse willreturn }
1658; IS__TUNIT_OPM: attributes #[[ATTR10]] = { noinline nounwind willreturn uwtable }
1659; IS__TUNIT_OPM: attributes #[[ATTR11:[0-9]+]] = { noinline willreturn uwtable }
1660; IS__TUNIT_OPM: attributes #[[ATTR12]] = { nounwind willreturn }
1661; IS__TUNIT_OPM: attributes #[[ATTR13]] = { argmemonly nofree noinline norecurse nosync nounwind readonly uwtable }
1662; IS__TUNIT_OPM: attributes #[[ATTR14]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable }
1663; IS__TUNIT_OPM: attributes #[[ATTR15:[0-9]+]] = { noreturn nounwind }
1664; IS__TUNIT_OPM: attributes #[[ATTR16]] = { nofree norecurse nosync nounwind readnone }
1665; IS__TUNIT_OPM: attributes #[[ATTR17]] = { readonly }
1666; IS__TUNIT_OPM: attributes #[[ATTR18:[0-9]+]] = { readnone }
1667; IS__TUNIT_OPM: attributes #[[ATTR19]] = { mustprogress }
1668; IS__TUNIT_OPM: attributes #[[ATTR20:[0-9]+]] = { mustprogress readonly }
1669; IS__TUNIT_OPM: attributes #[[ATTR21]] = { mustprogress readonly willreturn }
1670; IS__TUNIT_OPM: attributes #[[ATTR22]] = { mustprogress nosync readnone willreturn }
1671; IS__TUNIT_OPM: attributes #[[ATTR23]] = { readonly willreturn }
1672; IS__TUNIT_OPM: attributes #[[ATTR24]] = { nofree nosync nounwind readnone }
1673; IS__TUNIT_OPM: attributes #[[ATTR25]] = { nofree nosync nounwind }
1674; IS__TUNIT_OPM: attributes #[[ATTR26]] = { readnone willreturn }
1675; IS__TUNIT_OPM: attributes #[[ATTR27]] = { nounwind }
1676; IS__TUNIT_OPM: attributes #[[ATTR28]] = { willreturn }
1677;.
1678; IS__TUNIT_NPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable }
1679; IS__TUNIT_NPM: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable }
1680; IS__TUNIT_NPM: attributes #[[ATTR2]] = { nofree noinline norecurse nosync nounwind readnone uwtable }
1681; IS__TUNIT_NPM: attributes #[[ATTR3:[0-9]+]] = { nofree nosync nounwind willreturn }
1682; IS__TUNIT_NPM: attributes #[[ATTR4]] = { nofree noinline nosync nounwind uwtable }
1683; IS__TUNIT_NPM: attributes #[[ATTR5]] = { noreturn }
1684; IS__TUNIT_NPM: attributes #[[ATTR6]] = { noinline noreturn nounwind uwtable }
1685; IS__TUNIT_NPM: attributes #[[ATTR7]] = { noinline nounwind uwtable }
1686; IS__TUNIT_NPM: attributes #[[ATTR8:[0-9]+]] = { nocallback nofree nosync nounwind readnone speculatable willreturn }
1687; IS__TUNIT_NPM: attributes #[[ATTR9:[0-9]+]] = { norecurse willreturn }
1688; IS__TUNIT_NPM: attributes #[[ATTR10]] = { noinline nounwind willreturn uwtable }
1689; IS__TUNIT_NPM: attributes #[[ATTR11:[0-9]+]] = { noinline willreturn uwtable }
1690; IS__TUNIT_NPM: attributes #[[ATTR12]] = { nounwind willreturn }
1691; IS__TUNIT_NPM: attributes #[[ATTR13]] = { argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable }
1692; IS__TUNIT_NPM: attributes #[[ATTR14]] = { argmemonly nofree noinline norecurse nosync nounwind readonly uwtable }
1693; IS__TUNIT_NPM: attributes #[[ATTR15]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable }
1694; IS__TUNIT_NPM: attributes #[[ATTR16:[0-9]+]] = { noreturn nounwind }
1695; IS__TUNIT_NPM: attributes #[[ATTR17]] = { nofree norecurse nosync nounwind readnone }
1696; IS__TUNIT_NPM: attributes #[[ATTR18]] = { nofree norecurse nosync nounwind readnone willreturn }
1697; IS__TUNIT_NPM: attributes #[[ATTR19]] = { readonly }
1698; IS__TUNIT_NPM: attributes #[[ATTR20:[0-9]+]] = { readnone }
1699; IS__TUNIT_NPM: attributes #[[ATTR21]] = { mustprogress }
1700; IS__TUNIT_NPM: attributes #[[ATTR22:[0-9]+]] = { mustprogress readonly }
1701; IS__TUNIT_NPM: attributes #[[ATTR23]] = { mustprogress readonly willreturn }
1702; IS__TUNIT_NPM: attributes #[[ATTR24]] = { mustprogress nosync readnone willreturn }
1703; IS__TUNIT_NPM: attributes #[[ATTR25]] = { readonly willreturn }
1704; IS__TUNIT_NPM: attributes #[[ATTR26]] = { nofree nosync nounwind readnone }
1705; IS__TUNIT_NPM: attributes #[[ATTR27]] = { nofree nosync nounwind }
1706; IS__TUNIT_NPM: attributes #[[ATTR28]] = { readnone willreturn }
1707; IS__TUNIT_NPM: attributes #[[ATTR29]] = { nounwind }
1708; IS__TUNIT_NPM: attributes #[[ATTR30]] = { willreturn }
1709;.
1710; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable }
1711; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable }
1712; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree noinline norecurse nosync nounwind readnone uwtable }
1713; IS__CGSCC_OPM: attributes #[[ATTR3:[0-9]+]] = { nofree nosync nounwind willreturn }
1714; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nofree noinline nosync nounwind uwtable }
1715; IS__CGSCC_OPM: attributes #[[ATTR5]] = { noreturn }
1716; IS__CGSCC_OPM: attributes #[[ATTR6]] = { noinline noreturn nounwind uwtable }
1717; IS__CGSCC_OPM: attributes #[[ATTR7]] = { noinline nounwind uwtable }
1718; IS__CGSCC_OPM: attributes #[[ATTR8:[0-9]+]] = { nocallback nofree nosync nounwind readnone speculatable willreturn }
1719; IS__CGSCC_OPM: attributes #[[ATTR9:[0-9]+]] = { norecurse willreturn }
1720; IS__CGSCC_OPM: attributes #[[ATTR10]] = { noinline nounwind willreturn uwtable }
1721; IS__CGSCC_OPM: attributes #[[ATTR11:[0-9]+]] = { noinline willreturn uwtable }
1722; IS__CGSCC_OPM: attributes #[[ATTR12]] = { nounwind willreturn }
1723; IS__CGSCC_OPM: attributes #[[ATTR13]] = { argmemonly nofree noinline norecurse nosync nounwind readonly uwtable }
1724; IS__CGSCC_OPM: attributes #[[ATTR14]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable }
1725; IS__CGSCC_OPM: attributes #[[ATTR15:[0-9]+]] = { noreturn nounwind }
1726; IS__CGSCC_OPM: attributes #[[ATTR16]] = { nofree norecurse nosync nounwind readnone }
1727; IS__CGSCC_OPM: attributes #[[ATTR17]] = { nofree nosync nounwind readnone }
1728; IS__CGSCC_OPM: attributes #[[ATTR18]] = { readonly }
1729; IS__CGSCC_OPM: attributes #[[ATTR19:[0-9]+]] = { readnone }
1730; IS__CGSCC_OPM: attributes #[[ATTR20]] = { mustprogress }
1731; IS__CGSCC_OPM: attributes #[[ATTR21:[0-9]+]] = { mustprogress readonly }
1732; IS__CGSCC_OPM: attributes #[[ATTR22]] = { mustprogress readonly willreturn }
1733; IS__CGSCC_OPM: attributes #[[ATTR23]] = { mustprogress nosync readnone willreturn }
1734; IS__CGSCC_OPM: attributes #[[ATTR24]] = { readonly willreturn }
1735; IS__CGSCC_OPM: attributes #[[ATTR25]] = { nofree nosync nounwind }
1736; IS__CGSCC_OPM: attributes #[[ATTR26]] = { readnone willreturn }
1737; IS__CGSCC_OPM: attributes #[[ATTR27]] = { nounwind }
1738; IS__CGSCC_OPM: attributes #[[ATTR28]] = { willreturn }
1739; IS__CGSCC_OPM: attributes #[[ATTR29]] = { nounwind readnone }
1740;.
1741; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable }
1742; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable }
1743; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nofree noinline norecurse nosync nounwind readnone uwtable }
1744; IS__CGSCC_NPM: attributes #[[ATTR3:[0-9]+]] = { nofree nosync nounwind willreturn }
1745; IS__CGSCC_NPM: attributes #[[ATTR4]] = { nofree noinline nosync nounwind uwtable }
1746; IS__CGSCC_NPM: attributes #[[ATTR5]] = { noreturn }
1747; IS__CGSCC_NPM: attributes #[[ATTR6]] = { noinline noreturn nounwind uwtable }
1748; IS__CGSCC_NPM: attributes #[[ATTR7]] = { noinline nounwind uwtable }
1749; IS__CGSCC_NPM: attributes #[[ATTR8:[0-9]+]] = { nocallback nofree nosync nounwind readnone speculatable willreturn }
1750; IS__CGSCC_NPM: attributes #[[ATTR9:[0-9]+]] = { norecurse willreturn }
1751; IS__CGSCC_NPM: attributes #[[ATTR10]] = { noinline nounwind willreturn uwtable }
1752; IS__CGSCC_NPM: attributes #[[ATTR11:[0-9]+]] = { noinline willreturn uwtable }
1753; IS__CGSCC_NPM: attributes #[[ATTR12]] = { nounwind willreturn }
1754; IS__CGSCC_NPM: attributes #[[ATTR13]] = { argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable }
1755; IS__CGSCC_NPM: attributes #[[ATTR14]] = { argmemonly nofree noinline norecurse nosync nounwind readonly uwtable }
1756; IS__CGSCC_NPM: attributes #[[ATTR15]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable }
1757; IS__CGSCC_NPM: attributes #[[ATTR16:[0-9]+]] = { noreturn nounwind }
1758; IS__CGSCC_NPM: attributes #[[ATTR17]] = { nofree norecurse nosync nounwind readnone }
1759; IS__CGSCC_NPM: attributes #[[ATTR18]] = { nofree norecurse nosync nounwind readnone willreturn }
1760; IS__CGSCC_NPM: attributes #[[ATTR19]] = { nofree nosync nounwind readnone }
1761; IS__CGSCC_NPM: attributes #[[ATTR20]] = { readonly }
1762; IS__CGSCC_NPM: attributes #[[ATTR21:[0-9]+]] = { readnone }
1763; IS__CGSCC_NPM: attributes #[[ATTR22]] = { mustprogress }
1764; IS__CGSCC_NPM: attributes #[[ATTR23:[0-9]+]] = { mustprogress readonly }
1765; IS__CGSCC_NPM: attributes #[[ATTR24]] = { mustprogress readonly willreturn }
1766; IS__CGSCC_NPM: attributes #[[ATTR25]] = { mustprogress nosync readnone willreturn }
1767; IS__CGSCC_NPM: attributes #[[ATTR26]] = { readonly willreturn }
1768; IS__CGSCC_NPM: attributes #[[ATTR27]] = { nofree nosync nounwind }
1769; IS__CGSCC_NPM: attributes #[[ATTR28]] = { readnone willreturn }
1770; IS__CGSCC_NPM: attributes #[[ATTR29]] = { nounwind }
1771; IS__CGSCC_NPM: attributes #[[ATTR30]] = { willreturn }
1772;.
1773