xref: /llvm-project/llvm/test/Transforms/Attributor/nonnull.ll (revision 8a43d0e8736cf5e0f95a5f02c9b6855a703b2e4e)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
4
5
6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7
8declare nonnull ptr @ret_nonnull()
9declare void @llvm.assume(i1)
10
11; Return a pointer trivially nonnull (call return attribute)
12;.
13; CHECK: @G = internal global i64 1, align 8
14;.
15define ptr @test1() {
16; CHECK-LABEL: define {{[^@]+}}@test1() {
17; CHECK-NEXT:    [[RET:%.*]] = call nonnull ptr @ret_nonnull()
18; CHECK-NEXT:    ret ptr [[RET]]
19;
20  %ret = call ptr @ret_nonnull()
21  ret ptr %ret
22}
23
24; Return a pointer trivially nonnull (argument attribute)
25define ptr @test2(ptr nonnull %p) {
26; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
27; CHECK-LABEL: define {{[^@]+}}@test2
28; CHECK-SAME: (ptr nofree nonnull readnone returned "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1:[0-9]+]] {
29; CHECK-NEXT:    ret ptr [[P]]
30;
31  ret ptr %p
32}
33
34define ptr @test2A(i1 %c, ptr %ret) {
35; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
36; CHECK-LABEL: define {{[^@]+}}@test2A
37; CHECK-SAME: (i1 noundef [[C:%.*]], ptr nofree nonnull readnone returned "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2:[0-9]+]] {
38; CHECK-NEXT:    br i1 [[C]], label [[A:%.*]], label [[B:%.*]]
39; CHECK:       A:
40; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR16:[0-9]+]] [ "nonnull"(ptr [[RET]]) ]
41; CHECK-NEXT:    ret ptr [[RET]]
42; CHECK:       B:
43; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "nonnull"(ptr [[RET]]) ]
44; CHECK-NEXT:    ret ptr [[RET]]
45;
46  br i1 %c, label %A, label %B
47A:
48  call void @llvm.assume(i1 true) [ "nonnull"(ptr %ret) ]
49  ret ptr %ret
50B:
51  call void @llvm.assume(i1 true) [ "nonnull"(ptr %ret) ]
52  ret ptr %ret
53}
54
55define ptr @test2B(i1 %c, ptr %ret) {
56; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
57; CHECK-LABEL: define {{[^@]+}}@test2B
58; CHECK-SAME: (i1 noundef [[C:%.*]], ptr nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2]] {
59; CHECK-NEXT:    br i1 [[C]], label [[A:%.*]], label [[B:%.*]]
60; CHECK:       A:
61; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "dereferenceable"(ptr [[RET]], i32 4) ]
62; CHECK-NEXT:    ret ptr [[RET]]
63; CHECK:       B:
64; CHECK-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "dereferenceable"(ptr [[RET]], i32 4) ]
65; CHECK-NEXT:    ret ptr [[RET]]
66;
67  br i1 %c, label %A, label %B
68A:
69  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ret, i32 4) ]
70  ret ptr %ret
71B:
72  call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ret, i32 4) ]
73  ret ptr %ret
74}
75
76; Given an SCC where one of the functions can not be marked nonnull,
77; can we still mark the other one which is trivially nonnull
78define ptr @scc_binder(i1 %c) {
79; CHECK-LABEL: define {{[^@]+}}@scc_binder
80; CHECK-SAME: (i1 noundef [[C:%.*]]) {
81; CHECK-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
82; CHECK:       rec:
83; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @test3(i1 noundef [[C]])
84; CHECK-NEXT:    br label [[END]]
85; CHECK:       end:
86; CHECK-NEXT:    ret ptr null
87;
88  br i1 %c, label %rec, label %end
89rec:
90  call ptr @test3(i1 %c)
91  br label %end
92end:
93  ret ptr null
94}
95
96define ptr @test3(i1 %c) {
97; CHECK-LABEL: define {{[^@]+}}@test3
98; CHECK-SAME: (i1 [[C:%.*]]) {
99; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @scc_binder(i1 noundef [[C]])
100; CHECK-NEXT:    [[RET:%.*]] = call nonnull ptr @ret_nonnull()
101; CHECK-NEXT:    ret ptr [[RET]]
102;
103  call ptr @scc_binder(i1 %c)
104  %ret = call ptr @ret_nonnull()
105  ret ptr %ret
106}
107
108; Given a mutual recursive set of functions, we can mark them
109; nonnull if neither can ever return null.  (In this case, they
110; just never return period.)
111define ptr @test4_helper() {
112; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
113; TUNIT-LABEL: define {{[^@]+}}@test4_helper
114; TUNIT-SAME: () #[[ATTR3:[0-9]+]] {
115; TUNIT-NEXT:    ret ptr undef
116;
117; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
118; CGSCC-LABEL: define {{[^@]+}}@test4_helper
119; CGSCC-SAME: () #[[ATTR1]] {
120; CGSCC-NEXT:    ret ptr undef
121;
122  %ret = call ptr @test4()
123  ret ptr %ret
124}
125
126define ptr @test4() {
127; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
128; TUNIT-LABEL: define {{[^@]+}}@test4
129; TUNIT-SAME: () #[[ATTR3]] {
130; TUNIT-NEXT:    ret ptr undef
131;
132; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
133; CGSCC-LABEL: define {{[^@]+}}@test4
134; CGSCC-SAME: () #[[ATTR1]] {
135; CGSCC-NEXT:    ret ptr undef
136;
137  %ret = call ptr @test4_helper()
138  ret ptr %ret
139}
140
141; Given a mutual recursive set of functions which *can* return null
142; make sure we haven't marked them as nonnull.
143define ptr @test5_helper(i1 %c) {
144; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
145; TUNIT-LABEL: define {{[^@]+}}@test5_helper
146; TUNIT-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] {
147; TUNIT-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
148; TUNIT:       rec:
149; TUNIT-NEXT:    br label [[END]]
150; TUNIT:       end:
151; TUNIT-NEXT:    ret ptr null
152;
153; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
154; CGSCC-LABEL: define {{[^@]+}}@test5_helper
155; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] {
156; CGSCC-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]
157; CGSCC:       rec:
158; CGSCC-NEXT:    br label [[END]]
159; CGSCC:       end:
160; CGSCC-NEXT:    ret ptr null
161;
162  br i1 %c, label %rec, label %end
163rec:
164  %ret = call ptr @test5(i1 %c)
165  br label %end
166end:
167  ret ptr null
168}
169
170define ptr @test5(i1 %c) {
171; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
172; TUNIT-LABEL: define {{[^@]+}}@test5
173; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
174; TUNIT-NEXT:    ret ptr null
175;
176; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
177; CGSCC-LABEL: define {{[^@]+}}@test5
178; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
179; CGSCC-NEXT:    ret ptr null
180;
181  %ret = call ptr @test5_helper(i1 %c)
182  ret ptr %ret
183}
184
185; Local analysis, but going through a self recursive phi
186define ptr @test6a() {
187;
188; TUNIT: Function Attrs: noreturn
189; TUNIT-LABEL: define {{[^@]+}}@test6a
190; TUNIT-SAME: () #[[ATTR4:[0-9]+]] {
191; TUNIT-NEXT:  entry:
192; TUNIT-NEXT:    [[RET:%.*]] = call ptr @ret_nonnull()
193; TUNIT-NEXT:    br label [[LOOP:%.*]]
194; TUNIT:       loop:
195; TUNIT-NEXT:    unreachable
196; TUNIT:       exit:
197; TUNIT-NEXT:    unreachable
198;
199; CGSCC: Function Attrs: noreturn
200; CGSCC-LABEL: define {{[^@]+}}@test6a
201; CGSCC-SAME: () #[[ATTR3:[0-9]+]] {
202; CGSCC-NEXT:  entry:
203; CGSCC-NEXT:    [[RET:%.*]] = call ptr @ret_nonnull()
204; CGSCC-NEXT:    br label [[LOOP:%.*]]
205; CGSCC:       loop:
206; CGSCC-NEXT:    unreachable
207; CGSCC:       exit:
208; CGSCC-NEXT:    unreachable
209;
210entry:
211  %ret = call ptr @ret_nonnull()
212  br label %loop
213loop:
214  %phi = phi ptr [%ret, %entry], [%phi, %loop]
215  br i1 undef, label %loop, label %exit
216exit:
217  ret ptr %phi
218}
219
220define ptr @test6b(i1 %c) {
221; CHECK-LABEL: define {{[^@]+}}@test6b
222; CHECK-SAME: (i1 [[C:%.*]]) {
223; CHECK-NEXT:  entry:
224; CHECK-NEXT:    [[RET:%.*]] = call nonnull ptr @ret_nonnull()
225; CHECK-NEXT:    br label [[LOOP:%.*]]
226; CHECK:       loop:
227; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[RET]], [[LOOP]] ]
228; CHECK-NEXT:    br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]]
229; CHECK:       exit:
230; CHECK-NEXT:    ret ptr [[RET]]
231;
232entry:
233  %ret = call ptr @ret_nonnull()
234  br label %loop
235loop:
236  %phi = phi ptr [%ret, %entry], [%phi, %loop]
237  br i1 %c, label %loop, label %exit
238exit:
239  ret ptr %phi
240}
241
242define ptr @test7(ptr %a) {
243; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
244; CHECK-LABEL: define {{[^@]+}}@test7
245; CHECK-SAME: (ptr nofree readnone returned "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {
246; CHECK-NEXT:    ret ptr [[A]]
247;
248  ret ptr %a
249}
250
251define ptr @test8(ptr %a) {
252; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
253; CHECK-LABEL: define {{[^@]+}}@test8
254; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {
255; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 1
256; CHECK-NEXT:    ret ptr [[B]]
257;
258  %b = getelementptr inbounds i8, ptr %a, i64 1
259  ret ptr %b
260}
261
262define ptr @test9(ptr %a, i64 %n) {
263; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
264; CHECK-LABEL: define {{[^@]+}}@test9
265; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {
266; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]]
267; CHECK-NEXT:    ret ptr [[B]]
268;
269  %b = getelementptr inbounds i8, ptr %a, i64 %n
270  ret ptr %b
271}
272
273; ATTRIBUTOR_OPM: define ptr @test10
274; ATTRIBUTOR_NPM: define nonnull ptr @test10
275define ptr @test10(ptr %a, i64 %n) {
276; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)
277; CHECK-LABEL: define {{[^@]+}}@test10
278; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) #[[ATTR2]] {
279; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i64 [[N]], 0
280; CHECK-NEXT:    call void @llvm.assume(i1 noundef [[CMP]]) #[[ATTR16]]
281; CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]]
282; CHECK-NEXT:    ret ptr [[B]]
283;
284  %cmp = icmp ne i64 %n, 0
285  call void @llvm.assume(i1 %cmp)
286  %b = getelementptr inbounds i8, ptr %a, i64 %n
287  ret ptr %b
288}
289
290; TEST 11
291; char* test11(char *p) {
292;   return p? p: nonnull();
293; }
294; FIXME: missing nonnull
295define ptr @test11(ptr) local_unnamed_addr {
296; CHECK-LABEL: define {{[^@]+}}@test11
297; CHECK-SAME: (ptr [[TMP0:%.*]]) local_unnamed_addr {
298; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null
299; CHECK-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
300; CHECK:       3:
301; CHECK-NEXT:    [[TMP4:%.*]] = tail call ptr @ret_nonnull()
302; CHECK-NEXT:    br label [[TMP5]]
303; CHECK:       5:
304; CHECK-NEXT:    [[TMP6:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]
305; CHECK-NEXT:    ret ptr [[TMP6]]
306;
307  %2 = icmp eq ptr %0, null
308  br i1 %2, label %3, label %5
309
310; <label>:3:                                      ; preds = %1
311  %4 = tail call ptr @ret_nonnull()
312  br label %5
313
314; <label>:5:                                      ; preds = %3, %1
315  %6 = phi ptr [ %4, %3 ], [ %0, %1 ]
316  ret ptr %6
317}
318
319; TEST 12
320; Simple CallSite Test
321declare void @test12_helper(ptr)
322define void @test12(ptr nonnull %a) {
323; CHECK-LABEL: define {{[^@]+}}@test12
324; CHECK-SAME: (ptr nonnull [[A:%.*]]) {
325; CHECK-NEXT:    tail call void @test12_helper(ptr nonnull [[A]])
326; CHECK-NEXT:    ret void
327;
328  tail call void @test12_helper(ptr %a)
329  ret void
330}
331
332; TEST 13
333; Simple Argument Tests
334declare ptr @unknown()
335define void @test13_helper() {
336; TUNIT-LABEL: define {{[^@]+}}@test13_helper() {
337; TUNIT-NEXT:    [[NONNULLPTR:%.*]] = tail call nonnull ptr @ret_nonnull()
338; TUNIT-NEXT:    [[MAYBENULLPTR:%.*]] = tail call ptr @unknown()
339; TUNIT-NEXT:    tail call void @test13(ptr noalias nofree nonnull readnone captures(none) [[NONNULLPTR]], ptr noalias nofree nonnull readnone captures(none) [[NONNULLPTR]], ptr noalias nofree readnone captures(none) [[MAYBENULLPTR]]) #[[ATTR5:[0-9]+]]
340; TUNIT-NEXT:    tail call void @test13(ptr noalias nofree nonnull readnone captures(none) [[NONNULLPTR]], ptr noalias nofree readnone captures(none) [[MAYBENULLPTR]], ptr noalias nofree nonnull readnone captures(none) [[NONNULLPTR]]) #[[ATTR5]]
341; TUNIT-NEXT:    ret void
342;
343; CGSCC-LABEL: define {{[^@]+}}@test13_helper() {
344; CGSCC-NEXT:    [[NONNULLPTR:%.*]] = tail call nonnull ptr @ret_nonnull()
345; CGSCC-NEXT:    [[MAYBENULLPTR:%.*]] = tail call ptr @unknown()
346; CGSCC-NEXT:    tail call void @test13(ptr noalias nofree nonnull readnone captures(none) [[NONNULLPTR]], ptr noalias nofree nonnull readnone captures(none) [[NONNULLPTR]], ptr noalias nofree readnone captures(none) [[MAYBENULLPTR]]) #[[ATTR4:[0-9]+]]
347; CGSCC-NEXT:    tail call void @test13(ptr noalias nofree nonnull readnone captures(none) [[NONNULLPTR]], ptr noalias nofree readnone captures(none) [[MAYBENULLPTR]], ptr noalias nofree nonnull readnone captures(none) [[NONNULLPTR]]) #[[ATTR4]]
348; CGSCC-NEXT:    ret void
349;
350  %nonnullptr = tail call ptr @ret_nonnull()
351  %maybenullptr = tail call ptr @unknown()
352  tail call void @test13(ptr %nonnullptr, ptr %nonnullptr, ptr %maybenullptr)
353  tail call void @test13(ptr %nonnullptr, ptr %maybenullptr, ptr %nonnullptr)
354  ret void
355}
356define internal void @test13(ptr %a, ptr %b, ptr %c) {
357;
358; TUNIT: Function Attrs: nounwind
359; TUNIT-LABEL: define {{[^@]+}}@test13
360; TUNIT-SAME: (ptr noalias nofree nonnull readnone captures(none) [[A:%.*]], ptr noalias nofree readnone captures(none) [[B:%.*]], ptr noalias nofree readnone captures(none) [[C:%.*]]) #[[ATTR5]] {
361; TUNIT-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR5]]
362; TUNIT-NEXT:    call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[B]]) #[[ATTR5]]
363; TUNIT-NEXT:    call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[C]]) #[[ATTR5]]
364; TUNIT-NEXT:    ret void
365;
366; CGSCC: Function Attrs: nounwind
367; CGSCC-LABEL: define {{[^@]+}}@test13
368; CGSCC-SAME: (ptr noalias nofree nonnull readnone captures(none) [[A:%.*]], ptr noalias nofree readnone captures(none) [[B:%.*]], ptr noalias nofree readnone captures(none) [[C:%.*]]) #[[ATTR4]] {
369; CGSCC-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR4]]
370; CGSCC-NEXT:    call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[B]]) #[[ATTR4]]
371; CGSCC-NEXT:    call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[C]]) #[[ATTR4]]
372; CGSCC-NEXT:    ret void
373;
374  call void @use_i8_ptr(ptr %a)
375  call void @use_i8_ptr(ptr %b)
376  call void @use_i8_ptr(ptr %c)
377  ret void
378}
379
380declare nonnull ptr @nonnull()
381
382; TEST 14
383; Complex propagation
384; Argument of f1, f2, f3 can be marked with nonnull.
385
386; * Argument
387; 1. In f1:bb6, %arg can be marked with nonnull because of the comparison in bb1
388; 2. Because f2 is internal function, f2(ptr %arg) -> @f2(ptr nonnull %arg)
389; 3. In f1:bb4 %tmp5 is nonnull and f3 is internal function.
390;    Then, f3(ptr %arg) -> @f3(ptr nonnull %arg)
391; 4. We get nonnull in whole f1 call sites so f1(ptr %arg) -> @f1(ptr nonnull %arg)
392
393
394define internal ptr @f1(ptr %arg) {
395; FIXME: missing nonnull It should be nonnull @f1(ptr nonnull readonly %arg)
396; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: read)
397; TUNIT-LABEL: define {{[^@]+}}@f1
398; TUNIT-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR6:[0-9]+]] {
399; TUNIT-NEXT:  bb:
400; TUNIT-NEXT:    [[TMP:%.*]] = icmp eq ptr [[ARG]], null
401; TUNIT-NEXT:    br i1 [[TMP]], label [[BB9:%.*]], label [[BB1:%.*]]
402; TUNIT:       bb1:
403; TUNIT-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARG]], align 4
404; TUNIT-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0
405; TUNIT-NEXT:    br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]]
406; TUNIT:       bb4:
407; TUNIT-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 1
408; TUNIT-NEXT:    [[TMP5B:%.*]] = tail call ptr @f3(ptr nofree nonnull readonly [[TMP5]]) #[[ATTR17:[0-9]+]]
409; TUNIT-NEXT:    [[TMP5C:%.*]] = getelementptr inbounds i32, ptr [[TMP5B]], i64 -1
410; TUNIT-NEXT:    br label [[BB9]]
411; TUNIT:       bb6:
412; TUNIT-NEXT:    [[TMP7:%.*]] = tail call ptr @f2(ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG]]) #[[ATTR17]]
413; TUNIT-NEXT:    ret ptr [[TMP7]]
414; TUNIT:       bb9:
415; TUNIT-NEXT:    [[TMP10:%.*]] = phi ptr [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to ptr), [[BB:%.*]] ]
416; TUNIT-NEXT:    ret ptr [[TMP10]]
417;
418; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: read)
419; CGSCC-LABEL: define {{[^@]+}}@f1
420; CGSCC-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR5:[0-9]+]] {
421; CGSCC-NEXT:  bb:
422; CGSCC-NEXT:    [[TMP:%.*]] = icmp eq ptr [[ARG]], null
423; CGSCC-NEXT:    br i1 [[TMP]], label [[BB9:%.*]], label [[BB1:%.*]]
424; CGSCC:       bb1:
425; CGSCC-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARG]], align 4
426; CGSCC-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0
427; CGSCC-NEXT:    br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]]
428; CGSCC:       bb4:
429; CGSCC-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 1
430; CGSCC-NEXT:    [[TMP5B:%.*]] = tail call ptr @f3(ptr nofree nonnull readonly [[TMP5]]) #[[ATTR17:[0-9]+]]
431; CGSCC-NEXT:    [[TMP5C:%.*]] = getelementptr inbounds i32, ptr [[TMP5B]], i64 -1
432; CGSCC-NEXT:    br label [[BB9]]
433; CGSCC:       bb6:
434; CGSCC-NEXT:    [[TMP7:%.*]] = tail call ptr @f2(ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG]]) #[[ATTR17]]
435; CGSCC-NEXT:    ret ptr [[TMP7]]
436; CGSCC:       bb9:
437; CGSCC-NEXT:    [[TMP10:%.*]] = phi ptr [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to ptr), [[BB:%.*]] ]
438; CGSCC-NEXT:    ret ptr [[TMP10]]
439;
440
441bb:
442  %tmp = icmp eq ptr %arg, null
443  br i1 %tmp, label %bb9, label %bb1
444
445bb1:                                              ; preds = %bb
446  %tmp2 = load i32, ptr %arg, align 4
447  %tmp3 = icmp eq i32 %tmp2, 0
448  br i1 %tmp3, label %bb6, label %bb4
449
450bb4:                                              ; preds = %bb1
451  %tmp5 = getelementptr inbounds i32, ptr %arg, i64 1
452  %tmp5b = tail call ptr @f3(ptr %tmp5)
453  %tmp5c = getelementptr inbounds i32, ptr %tmp5b, i64 -1
454  br label %bb9
455
456bb6:                                              ; preds = %bb1
457  %tmp7 = tail call ptr @f2(ptr %arg)
458  ret ptr %tmp7
459
460bb9:                                              ; preds = %bb4, %bb
461  %tmp10 = phi ptr [ %tmp5c, %bb4 ], [ inttoptr (i64 4 to ptr), %bb ]
462  ret ptr %tmp10
463}
464
465define internal ptr @f2(ptr %arg) {
466; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: read)
467; TUNIT-LABEL: define {{[^@]+}}@f2
468; TUNIT-SAME: (ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR6]] {
469; TUNIT-NEXT:  bb:
470; TUNIT-NEXT:    [[TMP:%.*]] = tail call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR17]]
471; TUNIT-NEXT:    ret ptr [[TMP]]
472;
473; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: read)
474; CGSCC-LABEL: define {{[^@]+}}@f2
475; CGSCC-SAME: (ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR5]] {
476; CGSCC-NEXT:  bb:
477; CGSCC-NEXT:    [[TMP:%.*]] = tail call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR17]]
478; CGSCC-NEXT:    ret ptr [[TMP]]
479;
480bb:
481  %tmp = tail call ptr @f1(ptr %arg)
482  ret ptr %tmp
483}
484
485define dso_local noalias ptr @f3(ptr %arg) {
486; FIXME: missing nonnull. It should be nonnull @f3(ptr nonnull readonly %arg)
487; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: read)
488; TUNIT-LABEL: define {{[^@]+}}@f3
489; TUNIT-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR6]] {
490; TUNIT-NEXT:  bb:
491; TUNIT-NEXT:    [[TMP:%.*]] = call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR17]]
492; TUNIT-NEXT:    ret ptr [[TMP]]
493;
494; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: read)
495; CGSCC-LABEL: define {{[^@]+}}@f3
496; CGSCC-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR5]] {
497; CGSCC-NEXT:  bb:
498; CGSCC-NEXT:    [[TMP:%.*]] = call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR17]]
499; CGSCC-NEXT:    ret ptr [[TMP]]
500;
501bb:
502; FIXME: missing nonnull. It should be @f1(ptr nonnull readonly %arg)
503  %tmp = call ptr @f1(ptr %arg)
504  ret ptr %tmp
505}
506
507; TEST 15
508define void @f15(ptr %arg) {
509; CHECK-LABEL: define {{[^@]+}}@f15
510; CHECK-SAME: (ptr noundef nonnull dereferenceable(4) [[ARG:%.*]]) {
511; CHECK-NEXT:    tail call void @use1(ptr noundef nonnull dereferenceable(4) [[ARG]])
512; CHECK-NEXT:    ret void
513;
514
515  tail call void @use1(ptr dereferenceable(4) %arg)
516  ret void
517}
518
519declare void @fun0() #1
520declare void @fun1(ptr) #1
521declare void @fun2(ptr, ptr) #1
522declare void @fun3(ptr, ptr, ptr) #1
523; TEST 16 simple path test
524; if(..)
525;   fun2(nonnull %a, nonnull %b)
526; else
527;   fun2(nonnull %a, %b)
528; We can say that %a is nonnull but %b is not.
529define void @f16(ptr %a, ptr %b, i8 %c) {
530; TUNIT: Function Attrs: mustprogress nounwind willreturn
531; TUNIT-LABEL: define {{[^@]+}}@f16
532; TUNIT-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR8:[0-9]+]] {
533; TUNIT-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0
534; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
535; TUNIT:       if.then:
536; TUNIT-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]]) #[[ATTR7:[0-9]+]]
537; TUNIT-NEXT:    ret void
538; TUNIT:       if.else:
539; TUNIT-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr [[B]]) #[[ATTR7]]
540; TUNIT-NEXT:    ret void
541;
542; CGSCC: Function Attrs: mustprogress nounwind willreturn
543; CGSCC-LABEL: define {{[^@]+}}@f16
544; CGSCC-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR7:[0-9]+]] {
545; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0
546; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
547; CGSCC:       if.then:
548; CGSCC-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]]) #[[ATTR6:[0-9]+]]
549; CGSCC-NEXT:    ret void
550; CGSCC:       if.else:
551; CGSCC-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr [[B]]) #[[ATTR6]]
552; CGSCC-NEXT:    ret void
553;
554  %cmp = icmp eq i8 %c, 0
555  br i1 %cmp, label %if.then, label %if.else
556if.then:
557  tail call void @fun2(ptr nonnull %a, ptr nonnull %b)
558  ret void
559if.else:
560  tail call void @fun2(ptr nonnull %a, ptr %b)
561  ret void
562}
563; TEST 17 explore child BB test
564; if(..)
565;    ... (willreturn & nounwind)
566; else
567;    ... (willreturn & nounwind)
568; fun1(nonnull %a)
569; We can say that %a is nonnull
570define void @f17(ptr %a, i8 %c) {
571;
572; TUNIT: Function Attrs: mustprogress nounwind willreturn
573; TUNIT-LABEL: define {{[^@]+}}@f17
574; TUNIT-SAME: (ptr nonnull [[A:%.*]], i8 [[C:%.*]]) #[[ATTR8]] {
575; TUNIT-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0
576; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
577; TUNIT:       if.then:
578; TUNIT-NEXT:    tail call void @fun0() #[[ATTR7]]
579; TUNIT-NEXT:    br label [[CONT:%.*]]
580; TUNIT:       if.else:
581; TUNIT-NEXT:    tail call void @fun0() #[[ATTR7]]
582; TUNIT-NEXT:    br label [[CONT]]
583; TUNIT:       cont:
584; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR7]]
585; TUNIT-NEXT:    ret void
586;
587; CGSCC: Function Attrs: mustprogress nounwind willreturn
588; CGSCC-LABEL: define {{[^@]+}}@f17
589; CGSCC-SAME: (ptr nonnull [[A:%.*]], i8 [[C:%.*]]) #[[ATTR7]] {
590; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0
591; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
592; CGSCC:       if.then:
593; CGSCC-NEXT:    tail call void @fun0() #[[ATTR6]]
594; CGSCC-NEXT:    br label [[CONT:%.*]]
595; CGSCC:       if.else:
596; CGSCC-NEXT:    tail call void @fun0() #[[ATTR6]]
597; CGSCC-NEXT:    br label [[CONT]]
598; CGSCC:       cont:
599; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR6]]
600; CGSCC-NEXT:    ret void
601;
602  %cmp = icmp eq i8 %c, 0
603  br i1 %cmp, label %if.then, label %if.else
604if.then:
605  tail call void @fun0()
606  br label %cont
607if.else:
608  tail call void @fun0()
609  br label %cont
610cont:
611  tail call void @fun1(ptr nonnull %a)
612  ret void
613}
614; TEST 18 More complex test
615; if(..)
616;    ... (willreturn & nounwind)
617; else
618;    ... (willreturn & nounwind)
619; if(..)
620;    ... (willreturn & nounwind)
621; else
622;    ... (willreturn & nounwind)
623; fun1(nonnull %a)
624
625define void @f18(ptr %a, ptr %b, i8 %c) {
626; TUNIT: Function Attrs: mustprogress nounwind willreturn
627; TUNIT-LABEL: define {{[^@]+}}@f18
628; TUNIT-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR8]] {
629; TUNIT-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[C]], 0
630; TUNIT-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
631; TUNIT:       if.then:
632; TUNIT-NEXT:    tail call void @fun0() #[[ATTR7]]
633; TUNIT-NEXT:    br label [[CONT:%.*]]
634; TUNIT:       if.else:
635; TUNIT-NEXT:    tail call void @fun0() #[[ATTR7]]
636; TUNIT-NEXT:    br label [[CONT]]
637; TUNIT:       cont:
638; TUNIT-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 1
639; TUNIT-NEXT:    br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]]
640; TUNIT:       cont.then:
641; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR7]]
642; TUNIT-NEXT:    br label [[CONT2:%.*]]
643; TUNIT:       cont.else:
644; TUNIT-NEXT:    tail call void @fun0() #[[ATTR7]]
645; TUNIT-NEXT:    br label [[CONT2]]
646; TUNIT:       cont2:
647; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR7]]
648; TUNIT-NEXT:    ret void
649;
650; CGSCC: Function Attrs: mustprogress nounwind willreturn
651; CGSCC-LABEL: define {{[^@]+}}@f18
652; CGSCC-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR7]] {
653; CGSCC-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[C]], 0
654; CGSCC-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
655; CGSCC:       if.then:
656; CGSCC-NEXT:    tail call void @fun0() #[[ATTR6]]
657; CGSCC-NEXT:    br label [[CONT:%.*]]
658; CGSCC:       if.else:
659; CGSCC-NEXT:    tail call void @fun0() #[[ATTR6]]
660; CGSCC-NEXT:    br label [[CONT]]
661; CGSCC:       cont:
662; CGSCC-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 1
663; CGSCC-NEXT:    br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]]
664; CGSCC:       cont.then:
665; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR6]]
666; CGSCC-NEXT:    br label [[CONT2:%.*]]
667; CGSCC:       cont.else:
668; CGSCC-NEXT:    tail call void @fun0() #[[ATTR6]]
669; CGSCC-NEXT:    br label [[CONT2]]
670; CGSCC:       cont2:
671; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR6]]
672; CGSCC-NEXT:    ret void
673;
674  %cmp1 = icmp eq i8 %c, 0
675  br i1 %cmp1, label %if.then, label %if.else
676if.then:
677  tail call void @fun0()
678  br label %cont
679if.else:
680  tail call void @fun0()
681  br label %cont
682cont:
683  %cmp2 = icmp eq i8 %c, 1
684  br i1 %cmp2, label %cont.then, label %cont.else
685cont.then:
686  tail call void @fun1(ptr nonnull %b)
687  br label %cont2
688cont.else:
689  tail call void @fun0()
690  br label %cont2
691cont2:
692  tail call void @fun1(ptr nonnull %a)
693  ret void
694}
695
696; TEST 19: Loop
697
698define void @f19(ptr %a, ptr %b, i8 %c) {
699; TUNIT: Function Attrs: nounwind
700; TUNIT-LABEL: define {{[^@]+}}@f19
701; TUNIT-SAME: (ptr [[A:%.*]], ptr nonnull [[B:%.*]], i8 [[C:%.*]]) #[[ATTR5]] {
702; TUNIT-NEXT:    br label [[LOOP_HEADER:%.*]]
703; TUNIT:       loop.header:
704; TUNIT-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 0
705; TUNIT-NEXT:    br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]]
706; TUNIT:       loop.body:
707; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR5]]
708; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR5]]
709; TUNIT-NEXT:    br label [[LOOP_HEADER]]
710; TUNIT:       loop.exit:
711; TUNIT-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR5]]
712; TUNIT-NEXT:    ret void
713;
714; CGSCC: Function Attrs: nounwind
715; CGSCC-LABEL: define {{[^@]+}}@f19
716; CGSCC-SAME: (ptr [[A:%.*]], ptr nonnull [[B:%.*]], i8 [[C:%.*]]) #[[ATTR4]] {
717; CGSCC-NEXT:    br label [[LOOP_HEADER:%.*]]
718; CGSCC:       loop.header:
719; CGSCC-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 0
720; CGSCC-NEXT:    br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]]
721; CGSCC:       loop.body:
722; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR4]]
723; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR4]]
724; CGSCC-NEXT:    br label [[LOOP_HEADER]]
725; CGSCC:       loop.exit:
726; CGSCC-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR4]]
727; CGSCC-NEXT:    ret void
728;
729  br label %loop.header
730loop.header:
731  %cmp2 = icmp eq i8 %c, 0
732  br i1 %cmp2, label %loop.body, label %loop.exit
733loop.body:
734  tail call void @fun1(ptr nonnull %b)
735  tail call void @fun1(ptr nonnull %a)
736  br label %loop.header
737loop.exit:
738  tail call void @fun1(ptr nonnull %b)
739  ret void
740}
741
742; Test propagation of nonnull callsite args back to caller.
743
744declare void @use1(ptr %x)
745declare void @use2(ptr %x, ptr %y);
746declare void @use3(ptr %x, ptr %y, ptr %z);
747
748declare void @use1nonnull(ptr nonnull %x);
749declare void @use2nonnull(ptr nonnull %x, ptr nonnull %y);
750declare void @use3nonnull(ptr nonnull %x, ptr nonnull %y, ptr nonnull %z);
751
752declare i8 @use1safecall(ptr %x) readonly nounwind willreturn ; nounwind+willreturn guarantees that execution continues to successor
753
754; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute.
755
756define void @parent1(ptr %a, ptr %b, ptr %c) {
757; CHECK-LABEL: define {{[^@]+}}@parent1
758; CHECK-SAME: (ptr [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {
759; CHECK-NEXT:    call void @use3(ptr [[C]], ptr [[A]], ptr [[B]])
760; CHECK-NEXT:    call void @use3nonnull(ptr nonnull [[B]], ptr nonnull [[C]], ptr nonnull [[A]])
761; CHECK-NEXT:    ret void
762;
763  call void @use3(ptr %c, ptr %a, ptr %b)
764  call void @use3nonnull(ptr %b, ptr %c, ptr %a)
765  ret void
766}
767
768; Extend non-null to parent for all arguments.
769
770define void @parent2(ptr %a, ptr %b, ptr %c) {
771; CHECK-LABEL: define {{[^@]+}}@parent2
772; CHECK-SAME: (ptr nonnull [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {
773; CHECK-NEXT:    call void @use3nonnull(ptr nonnull [[B]], ptr nonnull [[C]], ptr nonnull [[A]])
774; CHECK-NEXT:    call void @use3(ptr nonnull [[C]], ptr nonnull [[A]], ptr nonnull [[B]])
775; CHECK-NEXT:    ret void
776;
777
778  call void @use3nonnull(ptr %b, ptr %c, ptr %a)
779  call void @use3(ptr %c, ptr %a, ptr %b)
780  ret void
781}
782
783; Extend non-null to parent for 1st argument.
784
785define void @parent3(ptr %a, ptr %b, ptr %c) {
786; CHECK-LABEL: define {{[^@]+}}@parent3
787; CHECK-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {
788; CHECK-NEXT:    call void @use1nonnull(ptr nonnull [[A]])
789; CHECK-NEXT:    call void @use3(ptr [[C]], ptr [[B]], ptr nonnull [[A]])
790; CHECK-NEXT:    ret void
791;
792
793
794  call void @use1nonnull(ptr %a)
795  call void @use3(ptr %c, ptr %b, ptr %a)
796  ret void
797}
798
799; Extend non-null to parent for last 2 arguments.
800
801define void @parent4(ptr %a, ptr %b, ptr %c) {
802; CHECK-LABEL: define {{[^@]+}}@parent4
803; CHECK-SAME: (ptr [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {
804; CHECK-NEXT:    call void @use2nonnull(ptr nonnull [[C]], ptr nonnull [[B]])
805; CHECK-NEXT:    call void @use2(ptr [[A]], ptr nonnull [[C]])
806; CHECK-NEXT:    call void @use1(ptr nonnull [[B]])
807; CHECK-NEXT:    ret void
808;
809
810
811
812  call void @use2nonnull(ptr %c, ptr %b)
813  call void @use2(ptr %a, ptr %c)
814  call void @use1(ptr %b)
815  ret void
816}
817
818; The callsite must execute in order for the attribute to transfer to the parent.
819; It appears benign to extend non-null to the parent in this case, but we can't do that
820; because it would incorrectly propagate the wrong information to its callers.
821
822define void @parent5(ptr %a, i1 %a_is_notnull) {
823; CHECK-LABEL: define {{[^@]+}}@parent5
824; CHECK-SAME: (ptr [[A:%.*]], i1 noundef [[A_IS_NOTNULL:%.*]]) {
825; CHECK-NEXT:    br i1 [[A_IS_NOTNULL]], label [[T:%.*]], label [[F:%.*]]
826; CHECK:       t:
827; CHECK-NEXT:    call void @use1nonnull(ptr nonnull [[A]])
828; CHECK-NEXT:    ret void
829; CHECK:       f:
830; CHECK-NEXT:    ret void
831;
832
833  br i1 %a_is_notnull, label %t, label %f
834t:
835  call void @use1nonnull(ptr %a)
836  ret void
837f:
838  ret void
839}
840
841; The callsite must execute in order for the attribute to transfer to the parent.
842; The volatile load can't trap, so we can guarantee that we'll get to the call.
843
844define i8 @parent6(ptr %a, ptr %b) {
845; CHECK-LABEL: define {{[^@]+}}@parent6
846; CHECK-SAME: (ptr nonnull [[A:%.*]], ptr nofree noundef [[B:%.*]]) {
847; CHECK-NEXT:    [[C:%.*]] = load volatile i8, ptr [[B]], align 1
848; CHECK-NEXT:    call void @use1nonnull(ptr nonnull [[A]])
849; CHECK-NEXT:    ret i8 [[C]]
850;
851
852  %c = load volatile i8, ptr %b
853  call void @use1nonnull(ptr %a)
854  ret i8 %c
855}
856
857; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent.
858
859define i8 @parent7(ptr %a) {
860; CHECK-LABEL: define {{[^@]+}}@parent7
861; CHECK-SAME: (ptr nonnull [[A:%.*]]) {
862; CHECK-NEXT:    [[RET:%.*]] = call i8 @use1safecall(ptr nonnull readonly [[A]]) #[[ATTR18:[0-9]+]]
863; CHECK-NEXT:    call void @use1nonnull(ptr nonnull [[A]])
864; CHECK-NEXT:    ret i8 [[RET]]
865;
866
867
868  %ret = call i8 @use1safecall(ptr %a)
869  call void @use1nonnull(ptr %a)
870  ret i8 %ret
871}
872
873; Make sure that an invoke works similarly to a call.
874
875declare i32 @esfp(...)
876
877define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{
878; TUNIT: Function Attrs: nounwind
879; TUNIT-LABEL: define {{[^@]+}}@parent8
880; TUNIT-SAME: (ptr nonnull [[A:%.*]], ptr nofree readnone captures(none) [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR5]] personality ptr @esfp {
881; TUNIT-NEXT:  entry:
882; TUNIT-NEXT:    invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]])
883; TUNIT-NEXT:            to label [[CONT:%.*]] unwind label [[EXC:%.*]]
884; TUNIT:       cont:
885; TUNIT-NEXT:    ret i1 false
886; TUNIT:       exc:
887; TUNIT-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }
888; TUNIT-NEXT:            filter [0 x ptr] zeroinitializer
889; TUNIT-NEXT:    unreachable
890;
891; CGSCC: Function Attrs: nounwind
892; CGSCC-LABEL: define {{[^@]+}}@parent8
893; CGSCC-SAME: (ptr nonnull [[A:%.*]], ptr nofree readnone captures(none) [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR4]] personality ptr @esfp {
894; CGSCC-NEXT:  entry:
895; CGSCC-NEXT:    invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]])
896; CGSCC-NEXT:            to label [[CONT:%.*]] unwind label [[EXC:%.*]]
897; CGSCC:       cont:
898; CGSCC-NEXT:    ret i1 false
899; CGSCC:       exc:
900; CGSCC-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }
901; CGSCC-NEXT:            filter [0 x ptr] zeroinitializer
902; CGSCC-NEXT:    unreachable
903;
904
905entry:
906  invoke void @use2nonnull(ptr %a, ptr %b)
907  to label %cont unwind label %exc
908
909cont:
910  %null_check = icmp eq ptr %b, null
911  ret i1 %null_check
912
913exc:
914  %lp = landingpad { ptr, i32 }
915  filter [0 x ptr] zeroinitializer
916  unreachable
917}
918
919define ptr @gep1(ptr %p) {
920; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
921; CHECK-LABEL: define {{[^@]+}}@gep1
922; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] {
923; CHECK-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1
924; CHECK-NEXT:    ret ptr [[Q]]
925;
926  %q = getelementptr inbounds i32, ptr %p, i32 1
927  ret ptr %q
928}
929
930define ptr @gep1_no_null_opt(ptr %p) #0 {
931; Should't be able to derive nonnull based on gep.
932; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)
933; TUNIT-LABEL: define {{[^@]+}}@gep1_no_null_opt
934; TUNIT-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR10:[0-9]+]] {
935; TUNIT-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1
936; TUNIT-NEXT:    ret ptr [[Q]]
937;
938; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)
939; CGSCC-LABEL: define {{[^@]+}}@gep1_no_null_opt
940; CGSCC-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR9:[0-9]+]] {
941; CGSCC-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1
942; CGSCC-NEXT:    ret ptr [[Q]]
943;
944  %q = getelementptr inbounds i32, ptr %p, i32 1
945  ret ptr %q
946}
947
948define ptr addrspace(3) @gep2(ptr addrspace(3) %p) {
949; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
950; CHECK-LABEL: define {{[^@]+}}@gep2
951; CHECK-SAME: (ptr addrspace(3) nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] {
952; CHECK-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr addrspace(3) [[P]], i32 1
953; CHECK-NEXT:    ret ptr addrspace(3) [[Q]]
954;
955  %q = getelementptr inbounds i32, ptr addrspace(3) %p, i32 1
956  ret ptr addrspace(3) %q
957}
958
959; FIXME: We should propagate dereferenceable here but *not* nonnull
960define ptr addrspace(3) @as(ptr addrspace(3) dereferenceable(4) %p) {
961; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
962; CHECK-LABEL: define {{[^@]+}}@as
963; CHECK-SAME: (ptr addrspace(3) nofree noundef readnone returned dereferenceable(4) dereferenceable_or_null(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] {
964; CHECK-NEXT:    ret ptr addrspace(3) [[P]]
965;
966  ret ptr addrspace(3) %p
967}
968
969define internal ptr @g2() {
970; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
971; CGSCC-LABEL: define {{[^@]+}}@g2
972; CGSCC-SAME: () #[[ATTR1]] {
973; CGSCC-NEXT:    ret ptr inttoptr (i64 4 to ptr)
974;
975  ret ptr inttoptr (i64 4 to ptr)
976}
977
978define ptr @g1() {
979; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
980; TUNIT-LABEL: define {{[^@]+}}@g1
981; TUNIT-SAME: () #[[ATTR1]] {
982; TUNIT-NEXT:    ret ptr inttoptr (i64 4 to ptr)
983;
984; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
985; CGSCC-LABEL: define {{[^@]+}}@g1
986; CGSCC-SAME: () #[[ATTR10:[0-9]+]] {
987; CGSCC-NEXT:    [[C:%.*]] = call noundef nonnull align 4 ptr @g2() #[[ATTR19:[0-9]+]]
988; CGSCC-NEXT:    ret ptr [[C]]
989;
990  %c = call ptr @g2()
991  ret ptr %c
992}
993
994declare void @use_i32_ptr(ptr readnone nocapture) nounwind
995define internal void @called_by_weak(ptr %a) {
996; TUNIT: Function Attrs: nounwind
997; TUNIT-LABEL: define {{[^@]+}}@called_by_weak
998; TUNIT-SAME: (ptr noalias nofree nonnull readnone captures(none) [[A:%.*]]) #[[ATTR5]] {
999; TUNIT-NEXT:    call void @use_i32_ptr(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR5]]
1000; TUNIT-NEXT:    ret void
1001;
1002; CGSCC: Function Attrs: nounwind
1003; CGSCC-LABEL: define {{[^@]+}}@called_by_weak
1004; CGSCC-SAME: (ptr noalias nofree nonnull readnone captures(none) [[A:%.*]]) #[[ATTR4]] {
1005; CGSCC-NEXT:    call void @use_i32_ptr(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR4]]
1006; CGSCC-NEXT:    ret void
1007;
1008  call void @use_i32_ptr(ptr %a)
1009  ret void
1010}
1011
1012; Check we do not annotate the function interface of this weak function.
1013define weak_odr void @weak_caller(ptr nonnull %a) {
1014;
1015; TUNIT-LABEL: define {{[^@]+}}@weak_caller
1016; TUNIT-SAME: (ptr nonnull [[A:%.*]]) {
1017; TUNIT-NEXT:    call void @called_by_weak(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR5]]
1018; TUNIT-NEXT:    ret void
1019;
1020; CGSCC-LABEL: define {{[^@]+}}@weak_caller
1021; CGSCC-SAME: (ptr nonnull [[A:%.*]]) {
1022; CGSCC-NEXT:    call void @called_by_weak(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR4]]
1023; CGSCC-NEXT:    ret void
1024;
1025  call void @called_by_weak(ptr %a)
1026  ret void
1027}
1028
1029; Expect nonnull
1030define internal void @control(ptr dereferenceable(4) %a) {
1031; TUNIT: Function Attrs: nounwind
1032; TUNIT-LABEL: define {{[^@]+}}@control
1033; TUNIT-SAME: (ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A:%.*]]) #[[ATTR5]] {
1034; TUNIT-NEXT:    call void @use_i32_ptr(ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A]]) #[[ATTR5]]
1035; TUNIT-NEXT:    ret void
1036;
1037; CGSCC: Function Attrs: nounwind
1038; CGSCC-LABEL: define {{[^@]+}}@control
1039; CGSCC-SAME: (ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A:%.*]]) #[[ATTR4]] {
1040; CGSCC-NEXT:    call void @use_i32_ptr(ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A]]) #[[ATTR4]]
1041; CGSCC-NEXT:    ret void
1042;
1043  call void @use_i32_ptr(ptr %a)
1044  ret void
1045}
1046; Avoid nonnull as we do not touch naked functions
1047define internal void @naked(ptr dereferenceable(4) %a) naked {
1048; CHECK: Function Attrs: naked
1049; CHECK-LABEL: define {{[^@]+}}@naked
1050; CHECK-SAME: (ptr noundef nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] {
1051; CHECK-NEXT:    ret void
1052;
1053  ret void
1054}
1055; Avoid nonnull as we do not touch optnone
1056define internal void @optnone(ptr dereferenceable(4) %a) optnone noinline {
1057;
1058; CHECK: Function Attrs: noinline optnone
1059; CHECK-LABEL: define {{[^@]+}}@optnone
1060; CHECK-SAME: (ptr noundef nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR12:[0-9]+]] {
1061; CHECK-NEXT:    call void @use_i32_ptr(ptr nofree noundef nonnull captures(none) [[A]])
1062; CHECK-NEXT:    ret void
1063;
1064  call void @use_i32_ptr(ptr %a)
1065  ret void
1066}
1067define void @make_live(ptr nonnull dereferenceable(8) %a) {
1068; TUNIT-LABEL: define {{[^@]+}}@make_live
1069; TUNIT-SAME: (ptr noundef nonnull align 16 dereferenceable(8) [[A:%.*]]) {
1070; TUNIT-NEXT:    call void @naked(ptr noundef nonnull align 16 dereferenceable(8) [[A]])
1071; TUNIT-NEXT:    call void @control(ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A]]) #[[ATTR5]]
1072; TUNIT-NEXT:    call void @optnone(ptr noundef nonnull align 16 dereferenceable(8) [[A]])
1073; TUNIT-NEXT:    ret void
1074;
1075; CGSCC-LABEL: define {{[^@]+}}@make_live
1076; CGSCC-SAME: (ptr noundef nonnull align 16 dereferenceable(8) [[A:%.*]]) {
1077; CGSCC-NEXT:    call void @naked(ptr noundef nonnull align 16 dereferenceable(8) [[A]])
1078; CGSCC-NEXT:    call void @control(ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A]]) #[[ATTR4]]
1079; CGSCC-NEXT:    call void @optnone(ptr noundef nonnull align 16 dereferenceable(8) [[A]])
1080; CGSCC-NEXT:    ret void
1081;
1082  call void @naked(ptr nonnull dereferenceable(8) align 16 %a)
1083  call void @control(ptr nonnull dereferenceable(8) align 16 %a)
1084  call void @optnone(ptr nonnull dereferenceable(8) align 16 %a)
1085  ret void
1086}
1087
1088
1089;int f(int *u, int n){
1090;  for(int i = 0;i<n;i++){
1091;    h(u);
1092;  }
1093;  return g(nonnull u);
1094;}
1095declare void @h(ptr) willreturn nounwind
1096declare i32 @g(ptr) willreturn nounwind
1097define i32 @nonnull_exec_ctx_1(ptr %a, i32 %b) {
1098;
1099; TUNIT: Function Attrs: mustprogress nounwind willreturn
1100; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1
1101; TUNIT-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] {
1102; TUNIT-NEXT:  en:
1103; TUNIT-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
1104; TUNIT-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
1105; TUNIT:       ex:
1106; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]]
1107; TUNIT-NEXT:    ret i32 [[TMP5]]
1108; TUNIT:       hd:
1109; TUNIT-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
1110; TUNIT-NEXT:    tail call void @h(ptr [[A]]) #[[ATTR7]]
1111; TUNIT-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
1112; TUNIT-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
1113; TUNIT-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
1114;
1115; CGSCC: Function Attrs: mustprogress nounwind willreturn
1116; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1
1117; CGSCC-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] {
1118; CGSCC-NEXT:  en:
1119; CGSCC-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
1120; CGSCC-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
1121; CGSCC:       ex:
1122; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]]
1123; CGSCC-NEXT:    ret i32 [[TMP5]]
1124; CGSCC:       hd:
1125; CGSCC-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
1126; CGSCC-NEXT:    tail call void @h(ptr [[A]]) #[[ATTR6]]
1127; CGSCC-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
1128; CGSCC-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
1129; CGSCC-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
1130;
1131en:
1132  %tmp3 = icmp eq i32 %b, 0
1133  br i1 %tmp3, label %ex, label %hd
1134
1135ex:
1136  %tmp5 = tail call i32 @g(ptr nonnull %a)
1137  ret i32 %tmp5
1138
1139hd:
1140  %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
1141  tail call void @h(ptr %a)
1142  %tmp8 = add nuw i32 %tmp7, 1
1143  %tmp9 = icmp eq i32 %tmp8, %b
1144  br i1 %tmp9, label %ex, label %hd
1145}
1146
1147define i32 @nonnull_exec_ctx_1b(ptr %a, i32 %b) {
1148;
1149; TUNIT: Function Attrs: mustprogress nounwind willreturn
1150; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b
1151; TUNIT-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] {
1152; TUNIT-NEXT:  en:
1153; TUNIT-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
1154; TUNIT-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
1155; TUNIT:       ex:
1156; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]]
1157; TUNIT-NEXT:    ret i32 [[TMP5]]
1158; TUNIT:       hd:
1159; TUNIT-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
1160; TUNIT-NEXT:    tail call void @h(ptr [[A]]) #[[ATTR7]]
1161; TUNIT-NEXT:    br label [[HD2]]
1162; TUNIT:       hd2:
1163; TUNIT-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
1164; TUNIT-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
1165; TUNIT-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
1166;
1167; CGSCC: Function Attrs: mustprogress nounwind willreturn
1168; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b
1169; CGSCC-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] {
1170; CGSCC-NEXT:  en:
1171; CGSCC-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
1172; CGSCC-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
1173; CGSCC:       ex:
1174; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]]
1175; CGSCC-NEXT:    ret i32 [[TMP5]]
1176; CGSCC:       hd:
1177; CGSCC-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
1178; CGSCC-NEXT:    tail call void @h(ptr [[A]]) #[[ATTR6]]
1179; CGSCC-NEXT:    br label [[HD2]]
1180; CGSCC:       hd2:
1181; CGSCC-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
1182; CGSCC-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
1183; CGSCC-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
1184;
1185en:
1186  %tmp3 = icmp eq i32 %b, 0
1187  br i1 %tmp3, label %ex, label %hd
1188
1189ex:
1190  %tmp5 = tail call i32 @g(ptr nonnull %a)
1191  ret i32 %tmp5
1192
1193hd:
1194  %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]
1195  tail call void @h(ptr %a)
1196  br label %hd2
1197
1198hd2:
1199  %tmp8 = add nuw i32 %tmp7, 1
1200  %tmp9 = icmp eq i32 %tmp8, %b
1201  br i1 %tmp9, label %ex, label %hd
1202}
1203
1204define i32 @nonnull_exec_ctx_2(ptr %a, i32 %b) willreturn nounwind {
1205;
1206; TUNIT: Function Attrs: mustprogress nounwind willreturn
1207; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2
1208; TUNIT-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] {
1209; TUNIT-NEXT:  en:
1210; TUNIT-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
1211; TUNIT-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
1212; TUNIT:       ex:
1213; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]]
1214; TUNIT-NEXT:    ret i32 [[TMP5]]
1215; TUNIT:       hd:
1216; TUNIT-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
1217; TUNIT-NEXT:    tail call void @h(ptr nonnull [[A]]) #[[ATTR5]]
1218; TUNIT-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
1219; TUNIT-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
1220; TUNIT-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
1221;
1222; CGSCC: Function Attrs: mustprogress nounwind willreturn
1223; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2
1224; CGSCC-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] {
1225; CGSCC-NEXT:  en:
1226; CGSCC-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
1227; CGSCC-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
1228; CGSCC:       ex:
1229; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]]
1230; CGSCC-NEXT:    ret i32 [[TMP5]]
1231; CGSCC:       hd:
1232; CGSCC-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
1233; CGSCC-NEXT:    tail call void @h(ptr nonnull [[A]]) #[[ATTR4]]
1234; CGSCC-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
1235; CGSCC-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
1236; CGSCC-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
1237;
1238en:
1239  %tmp3 = icmp eq i32 %b, 0
1240  br i1 %tmp3, label %ex, label %hd
1241
1242ex:
1243  %tmp5 = tail call i32 @g(ptr nonnull %a)
1244  ret i32 %tmp5
1245
1246hd:
1247  %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
1248  tail call void @h(ptr %a)
1249  %tmp8 = add nuw i32 %tmp7, 1
1250  %tmp9 = icmp eq i32 %tmp8, %b
1251  br i1 %tmp9, label %ex, label %hd
1252}
1253
1254define i32 @nonnull_exec_ctx_2b(ptr %a, i32 %b) willreturn nounwind {
1255;
1256; TUNIT: Function Attrs: mustprogress nounwind willreturn
1257; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b
1258; TUNIT-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] {
1259; TUNIT-NEXT:  en:
1260; TUNIT-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
1261; TUNIT-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
1262; TUNIT:       ex:
1263; TUNIT-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]]
1264; TUNIT-NEXT:    ret i32 [[TMP5]]
1265; TUNIT:       hd:
1266; TUNIT-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
1267; TUNIT-NEXT:    tail call void @h(ptr nonnull [[A]]) #[[ATTR5]]
1268; TUNIT-NEXT:    br label [[HD2]]
1269; TUNIT:       hd2:
1270; TUNIT-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
1271; TUNIT-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
1272; TUNIT-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
1273;
1274; CGSCC: Function Attrs: mustprogress nounwind willreturn
1275; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b
1276; CGSCC-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] {
1277; CGSCC-NEXT:  en:
1278; CGSCC-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 0
1279; CGSCC-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
1280; CGSCC:       ex:
1281; CGSCC-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]]
1282; CGSCC-NEXT:    ret i32 [[TMP5]]
1283; CGSCC:       hd:
1284; CGSCC-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
1285; CGSCC-NEXT:    tail call void @h(ptr nonnull [[A]]) #[[ATTR4]]
1286; CGSCC-NEXT:    br label [[HD2]]
1287; CGSCC:       hd2:
1288; CGSCC-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
1289; CGSCC-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
1290; CGSCC-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
1291;
1292en:
1293  %tmp3 = icmp eq i32 %b, 0
1294  br i1 %tmp3, label %ex, label %hd
1295
1296ex:
1297  %tmp5 = tail call i32 @g(ptr nonnull %a)
1298  ret i32 %tmp5
1299
1300hd:
1301  %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]
1302  tail call void @h(ptr %a)
1303  br label %hd2
1304
1305hd2:
1306  %tmp8 = add nuw i32 %tmp7, 1
1307  %tmp9 = icmp eq i32 %tmp8, %b
1308  br i1 %tmp9, label %ex, label %hd
1309}
1310
1311; Original from PR43833
1312declare void @sink(ptr)
1313
1314define void @PR43833(ptr %0, i32 %1) {
1315; CHECK-LABEL: define {{[^@]+}}@PR43833
1316; CHECK-SAME: (ptr [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
1317; CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP1]], 1
1318; CHECK-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
1319; CHECK:       4:
1320; CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
1321; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[TMP5]]
1322; CHECK-NEXT:    br label [[TMP8:%.*]]
1323; CHECK:       7:
1324; CHECK-NEXT:    ret void
1325; CHECK:       8:
1326; CHECK-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
1327; CHECK-NEXT:    tail call void @sink(ptr nonnull [[TMP6]])
1328; CHECK-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
1329; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
1330; CHECK-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
1331;
1332  %3 = icmp sgt i32 %1, 1
1333  br i1 %3, label %4, label %7
1334
13354:                                                ; preds = %2
1336  %5 = zext i32 %1 to i64
1337  %6 = getelementptr inbounds i32, ptr %0, i64 %5
1338  br label %8
1339
13407:                                                ; preds = %8, %2
1341  ret void
1342
13438:                                                ; preds = %8, %4
1344  %9 = phi i32 [ 1, %4 ], [ %10, %8 ]
1345  tail call void @sink(ptr %6)
1346  %10 = add nuw nsw i32 %9, 1
1347  %11 = icmp eq i32 %10, %1
1348  br i1 %11, label %7, label %8
1349}
1350
1351; Adjusted from PR43833
1352define void @PR43833_simple(ptr %0, i32 %1) {
1353; CHECK-LABEL: define {{[^@]+}}@PR43833_simple
1354; CHECK-SAME: (ptr [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
1355; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0
1356; CHECK-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
1357; CHECK:       4:
1358; CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
1359; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[TMP5]]
1360; CHECK-NEXT:    br label [[TMP8:%.*]]
1361; CHECK:       7:
1362; CHECK-NEXT:    ret void
1363; CHECK:       8:
1364; CHECK-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
1365; CHECK-NEXT:    tail call void @sink(ptr nonnull [[TMP6]])
1366; CHECK-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
1367; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
1368; CHECK-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
1369;
1370  %3 = icmp ne i32 %1, 0
1371  br i1 %3, label %4, label %7
1372
13734:                                                ; preds = %2
1374  %5 = zext i32 %1 to i64
1375  %6 = getelementptr inbounds i32, ptr %0, i64 %5
1376  br label %8
1377
13787:                                                ; preds = %8, %2
1379  ret void
1380
13818:                                                ; preds = %8, %4
1382  %9 = phi i32 [ 1, %4 ], [ %10, %8 ]
1383  tail call void @sink(ptr %6)
1384  %10 = add nuw nsw i32 %9, 1
1385  %11 = icmp eq i32 %10, %1
1386  br i1 %11, label %7, label %8
1387}
1388
1389declare ptr @strrchr(ptr %0, i32 %1) nofree nounwind readonly willreturn
1390
1391; We should not mark the return of @strrchr as `nonnull`, it may well be NULL!
1392define ptr @mybasename(ptr nofree readonly %str) {
1393; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read)
1394; TUNIT-LABEL: define {{[^@]+}}@mybasename
1395; TUNIT-SAME: (ptr nofree readonly [[STR:%.*]]) #[[ATTR14:[0-9]+]] {
1396; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @strrchr(ptr nofree readonly [[STR]], i32 noundef 47) #[[ATTR19:[0-9]+]]
1397; TUNIT-NEXT:    [[TOBOOL:%.*]] = icmp ne ptr [[CALL]], null
1398; TUNIT-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 1
1399; TUNIT-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL]], ptr [[ADD_PTR]], ptr [[STR]]
1400; TUNIT-NEXT:    ret ptr [[COND]]
1401;
1402; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read)
1403; CGSCC-LABEL: define {{[^@]+}}@mybasename
1404; CGSCC-SAME: (ptr nofree readonly [[STR:%.*]]) #[[ATTR14:[0-9]+]] {
1405; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @strrchr(ptr nofree readonly [[STR]], i32 noundef 47) #[[ATTR20:[0-9]+]]
1406; CGSCC-NEXT:    [[TOBOOL:%.*]] = icmp ne ptr [[CALL]], null
1407; CGSCC-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 1
1408; CGSCC-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL]], ptr [[ADD_PTR]], ptr [[STR]]
1409; CGSCC-NEXT:    ret ptr [[COND]]
1410;
1411  %call = call ptr @strrchr(ptr %str, i32 47)
1412  %tobool = icmp ne ptr %call, null
1413  %add.ptr = getelementptr inbounds i8, ptr %call, i64 1
1414  %cond = select i1 %tobool, ptr %add.ptr, ptr %str
1415  ret ptr %cond
1416}
1417
1418define void @nonnull_assume_pos(ptr %arg) {
1419; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_pos
1420; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull readnone [[ARG:%.*]])
1421; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) #11 [ "nonnull"(ptr [[ARG]]) ]
1422; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[ARG]])
1423; ATTRIBUTOR-NEXT:    [[TMP1:%.*]] = call ptr @unknown()
1424; ATTRIBUTOR-NEXT:    ret void
1425;
1426; TUNIT-LABEL: define {{[^@]+}}@nonnull_assume_pos
1427; TUNIT-SAME: (ptr nofree nonnull readnone captures(none) [[ARG:%.*]]) {
1428; TUNIT-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "nonnull"(ptr [[ARG]]) ]
1429; TUNIT-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR5]]
1430; TUNIT-NEXT:    [[TMP1:%.*]] = call ptr @unknown()
1431; TUNIT-NEXT:    ret void
1432;
1433; CGSCC-LABEL: define {{[^@]+}}@nonnull_assume_pos
1434; CGSCC-SAME: (ptr nofree nonnull readnone captures(none) [[ARG:%.*]]) {
1435; CGSCC-NEXT:    call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "nonnull"(ptr [[ARG]]) ]
1436; CGSCC-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR4]]
1437; CGSCC-NEXT:    [[TMP1:%.*]] = call ptr @unknown()
1438; CGSCC-NEXT:    ret void
1439;
1440  call void @llvm.assume(i1 true) ["nonnull"(ptr %arg)]
1441  call void @use_i8_ptr(ptr %arg)
1442  call ptr @unknown()
1443  ret void
1444}
1445define void @nonnull_assume_neg(ptr %arg) {
1446; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_neg
1447; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[ARG:%.*]])
1448; ATTRIBUTOR-NEXT:    [[TMP1:%.*]] = call ptr @unknown()
1449; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[ARG]])
1450; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]) ]
1451; ATTRIBUTOR-NEXT:    call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[ARG]])
1452; ATTRIBUTOR-NEXT:    [[TMP2:%.*]] = call ptr @unknown()
1453; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(ptr noalias nocapture nofree nonnull readnone [[ARG]])
1454; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]) ]
1455; ATTRIBUTOR-NEXT:    call void @use_i8_ptr_ret(ptr noalias nocapture nofree nonnull readnone [[ARG]])
1456; ATTRIBUTOR-NEXT:    ret void
1457;
1458;
1459; TUNIT-LABEL: define {{[^@]+}}@nonnull_assume_neg
1460; TUNIT-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]]) {
1461; TUNIT-NEXT:    [[TMP1:%.*]] = call ptr @unknown()
1462; TUNIT-NEXT:    call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[ARG]]) #[[ATTR5]]
1463; TUNIT-NEXT:    call void @llvm.assume(i1 noundef true) [ "nonnull"(ptr [[ARG]]) ]
1464; TUNIT-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR5]]
1465; TUNIT-NEXT:    [[TMP2:%.*]] = call ptr @unknown()
1466; TUNIT-NEXT:    call void @use_i8_ptr_ret(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR5]]
1467; TUNIT-NEXT:    call void @llvm.assume(i1 noundef true) [ "nonnull"(ptr [[ARG]]) ]
1468; TUNIT-NEXT:    call void @use_i8_ptr_ret(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR5]]
1469; TUNIT-NEXT:    ret void
1470;
1471; CGSCC-LABEL: define {{[^@]+}}@nonnull_assume_neg
1472; CGSCC-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]]) {
1473; CGSCC-NEXT:    [[TMP1:%.*]] = call ptr @unknown()
1474; CGSCC-NEXT:    call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[ARG]]) #[[ATTR4]]
1475; CGSCC-NEXT:    call void @llvm.assume(i1 noundef true) [ "nonnull"(ptr [[ARG]]) ]
1476; CGSCC-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR4]]
1477; CGSCC-NEXT:    [[TMP2:%.*]] = call ptr @unknown()
1478; CGSCC-NEXT:    call void @use_i8_ptr_ret(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR4]]
1479; CGSCC-NEXT:    call void @llvm.assume(i1 noundef true) [ "nonnull"(ptr [[ARG]]) ]
1480; CGSCC-NEXT:    call void @use_i8_ptr_ret(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR4]]
1481; CGSCC-NEXT:    ret void
1482;
1483  call ptr @unknown()
1484  call void @use_i8_ptr(ptr %arg)
1485  call void @llvm.assume(i1 true) ["nonnull"(ptr %arg)]
1486  call void @use_i8_ptr(ptr %arg)
1487  call ptr @unknown()
1488  call void @use_i8_ptr_ret(ptr %arg)
1489  call void @llvm.assume(i1 true) ["nonnull"(ptr %arg)]
1490  call void @use_i8_ptr_ret(ptr %arg)
1491  ret void
1492}
1493declare void @use_i8_ptr(ptr nofree nocapture readnone) nounwind
1494declare void @use_i8_ptr_ret(ptr nofree nocapture readnone) nounwind willreturn
1495
1496define ptr @nonnull_function_ptr_1() {
1497; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
1498; CHECK-LABEL: define {{[^@]+}}@nonnull_function_ptr_1
1499; CHECK-SAME: () #[[ATTR1]] {
1500; CHECK-NEXT:    ret ptr @nonnull_function_ptr_1
1501;
1502  ret ptr @nonnull_function_ptr_1
1503}
1504
1505declare ptr @function_decl()
1506define ptr @nonnull_function_ptr_2() {
1507; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
1508; CHECK-LABEL: define {{[^@]+}}@nonnull_function_ptr_2
1509; CHECK-SAME: () #[[ATTR1]] {
1510; CHECK-NEXT:    ret ptr @function_decl
1511;
1512  ret ptr @function_decl
1513}
1514
1515; FIXME: nonnull should not be propagated to the caller's p unless there is noundef
1516define void @nonnull_caller(ptr %p) {
1517; CHECK-LABEL: define {{[^@]+}}@nonnull_caller
1518; CHECK-SAME: (ptr nonnull [[P:%.*]]) {
1519; CHECK-NEXT:    call void @nonnull_callee(ptr nonnull [[P]])
1520; CHECK-NEXT:    ret void
1521;
1522  call void @nonnull_callee(ptr %p)
1523  ret void
1524}
1525declare void @nonnull_callee(ptr nonnull %p)
1526
1527define ptr @phi(ptr %p) {
1528; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
1529; CHECK-LABEL: define {{[^@]+}}@phi
1530; CHECK-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR1]] {
1531; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[P]], null
1532; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 1
1533; CHECK-NEXT:    br i1 [[C]], label [[NULL:%.*]], label [[NNULL:%.*]]
1534; CHECK:       NNULL:
1535; CHECK-NEXT:    br label [[MERGE:%.*]]
1536; CHECK:       NULL:
1537; CHECK-NEXT:    br label [[MERGE]]
1538; CHECK:       merge:
1539; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[P]], [[NNULL]] ], [ [[G]], [[NULL]] ]
1540; CHECK-NEXT:    ret ptr [[PHI]]
1541;
1542  %c = icmp eq ptr %p, null
1543  %g = getelementptr inbounds i8, ptr %p, i64 1
1544  br i1 %c, label %NULL, label %NNULL
1545NNULL:
1546  br label %merge
1547NULL:
1548  br label %merge
1549merge:
1550  %phi = phi ptr [%p, %NNULL], [%g, %NULL]
1551  ret ptr %phi
1552}
1553define void @phi_caller(ptr %p) {
1554; TUNIT: Function Attrs: nounwind
1555; TUNIT-LABEL: define {{[^@]+}}@phi_caller
1556; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] {
1557; TUNIT-NEXT:    [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR20:[0-9]+]]
1558; TUNIT-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[C]]) #[[ATTR5]]
1559; TUNIT-NEXT:    ret void
1560;
1561; CGSCC: Function Attrs: nounwind
1562; CGSCC-LABEL: define {{[^@]+}}@phi_caller
1563; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR4]] {
1564; CGSCC-NEXT:    [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR21:[0-9]+]]
1565; CGSCC-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[C]]) #[[ATTR4]]
1566; CGSCC-NEXT:    ret void
1567;
1568  %c = call ptr @phi(ptr %p)
1569  call void @use_i8_ptr(ptr %c)
1570  ret void
1571}
1572
1573define ptr @multi_ret(ptr %p) {
1574; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
1575; CHECK-LABEL: define {{[^@]+}}@multi_ret
1576; CHECK-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR1]] {
1577; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[P]], null
1578; CHECK-NEXT:    br i1 [[C]], label [[NULL:%.*]], label [[NNULL:%.*]]
1579; CHECK:       NNULL:
1580; CHECK-NEXT:    ret ptr [[P]]
1581; CHECK:       NULL:
1582; CHECK-NEXT:    [[G:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 1
1583; CHECK-NEXT:    ret ptr [[G]]
1584;
1585  %c = icmp eq ptr %p, null
1586  br i1 %c, label %NULL, label %NNULL
1587NNULL:
1588  ret ptr %p
1589NULL:
1590  %g = getelementptr inbounds i8, ptr %p, i64 1
1591  ret ptr %g
1592}
1593define void @multi_ret_caller(ptr %p) {
1594; TUNIT: Function Attrs: nounwind
1595; TUNIT-LABEL: define {{[^@]+}}@multi_ret_caller
1596; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] {
1597; TUNIT-NEXT:    [[C:%.*]] = call nonnull ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR20]]
1598; TUNIT-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[C]]) #[[ATTR5]]
1599; TUNIT-NEXT:    ret void
1600;
1601; CGSCC: Function Attrs: nounwind
1602; CGSCC-LABEL: define {{[^@]+}}@multi_ret_caller
1603; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR4]] {
1604; CGSCC-NEXT:    [[C:%.*]] = call nonnull ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR21]]
1605; CGSCC-NEXT:    call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[C]]) #[[ATTR4]]
1606; CGSCC-NEXT:    ret void
1607;
1608  %c = call ptr @multi_ret(ptr %p)
1609  call void @use_i8_ptr(ptr %c)
1610  ret void
1611}
1612
1613; From https://github.com/llvm/llvm-project/pull/85810
1614@G = internal global i64 1, align 8
1615define dso_local ptr @update_global_in_alive_bb() {
1616; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
1617; CHECK-LABEL: define {{[^@]+}}@update_global_in_alive_bb
1618; CHECK-SAME: () #[[ATTR15:[0-9]+]] {
1619; CHECK-NEXT:  entry:
1620; CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @G, align 8
1621; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i64 [[TMP0]], 0
1622; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1623; CHECK:       if.then:
1624; CHECK-NEXT:    store i64 0, ptr @G, align 8
1625; CHECK-NEXT:    ret ptr inttoptr (i64 5 to ptr)
1626; CHECK:       if.else:
1627; CHECK-NEXT:    ret ptr null
1628;
1629entry:
1630  %0 = load i64, ptr @G, align 8
1631  %cmp = icmp ne i64 %0, 0
1632  br i1 %cmp, label %if.then, label %if.else
1633if.then:
1634  store i64 0, ptr @G, align 8
1635  ret ptr inttoptr (i64 5 to ptr)
1636if.else:
1637  ret ptr null
1638}
1639
1640attributes #0 = { null_pointer_is_valid }
1641attributes #1 = { nounwind willreturn}
1642;.
1643; TUNIT: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
1644; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
1645; TUNIT: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) }
1646; TUNIT: attributes #[[ATTR3]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
1647; TUNIT: attributes #[[ATTR4]] = { noreturn }
1648; TUNIT: attributes #[[ATTR5]] = { nounwind }
1649; TUNIT: attributes #[[ATTR6]] = { nofree nosync nounwind memory(argmem: read) }
1650; TUNIT: attributes #[[ATTR7]] = { nounwind willreturn }
1651; TUNIT: attributes #[[ATTR8]] = { mustprogress nounwind willreturn }
1652; TUNIT: attributes #[[ATTR9:[0-9]+]] = { nounwind willreturn memory(read) }
1653; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none) }
1654; TUNIT: attributes #[[ATTR11]] = { naked }
1655; TUNIT: attributes #[[ATTR12]] = { noinline optnone }
1656; TUNIT: attributes #[[ATTR13:[0-9]+]] = { nofree nounwind willreturn memory(read) }
1657; TUNIT: attributes #[[ATTR14]] = { mustprogress nofree nosync nounwind willreturn memory(read) }
1658; TUNIT: attributes #[[ATTR15]] = { mustprogress nofree norecurse nosync nounwind willreturn }
1659; TUNIT: attributes #[[ATTR16]] = { nofree willreturn memory(write) }
1660; TUNIT: attributes #[[ATTR17]] = { nofree nosync nounwind memory(read) }
1661; TUNIT: attributes #[[ATTR18]] = { nosync willreturn memory(read) }
1662; TUNIT: attributes #[[ATTR19]] = { nofree nosync willreturn memory(read) }
1663; TUNIT: attributes #[[ATTR20]] = { nofree nosync nounwind willreturn memory(none) }
1664;.
1665; CGSCC: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
1666; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
1667; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) }
1668; CGSCC: attributes #[[ATTR3]] = { noreturn }
1669; CGSCC: attributes #[[ATTR4]] = { nounwind }
1670; CGSCC: attributes #[[ATTR5]] = { nofree nosync nounwind memory(argmem: read) }
1671; CGSCC: attributes #[[ATTR6]] = { nounwind willreturn }
1672; CGSCC: attributes #[[ATTR7]] = { mustprogress nounwind willreturn }
1673; CGSCC: attributes #[[ATTR8:[0-9]+]] = { nounwind willreturn memory(read) }
1674; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none) }
1675; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
1676; CGSCC: attributes #[[ATTR11]] = { naked }
1677; CGSCC: attributes #[[ATTR12]] = { noinline optnone }
1678; CGSCC: attributes #[[ATTR13:[0-9]+]] = { nofree nounwind willreturn memory(read) }
1679; CGSCC: attributes #[[ATTR14]] = { mustprogress nofree nosync nounwind willreturn memory(read) }
1680; CGSCC: attributes #[[ATTR15]] = { mustprogress nofree norecurse nosync nounwind willreturn }
1681; CGSCC: attributes #[[ATTR16]] = { nofree willreturn memory(write) }
1682; CGSCC: attributes #[[ATTR17]] = { nofree nosync nounwind memory(read) }
1683; CGSCC: attributes #[[ATTR18]] = { nosync willreturn memory(read) }
1684; CGSCC: attributes #[[ATTR19]] = { nofree nosync willreturn }
1685; CGSCC: attributes #[[ATTR20]] = { nofree nosync willreturn memory(read) }
1686; CGSCC: attributes #[[ATTR21]] = { nofree willreturn }
1687;.
1688