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