[mlir][scf]: Add value bound between scf for loop yield and result (#123200)
[llvm-project.git] / llvm / test / Transforms / FunctionAttrs / nonnull.ll
blob6dd2399093b668d96f2c097af26879a536c05d6d
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
5 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7 declare nonnull ptr @ret_nonnull()
9 ; Return a pointer trivially nonnull (call return attribute)
10 define ptr @test1() {
11 ; COMMON-LABEL: define nonnull ptr @test1() {
12 ; COMMON-NEXT:    [[RET:%.*]] = call ptr @ret_nonnull()
13 ; COMMON-NEXT:    ret ptr [[RET]]
15   %ret = call ptr @ret_nonnull()
16   ret ptr %ret
19 ; Return a pointer trivially nonnull (argument attribute)
20 define 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]]
25 ; ATTRIBUTOR-LABEL: define nonnull ptr @test2(
26 ; ATTRIBUTOR-SAME: ptr nofree nonnull readnone [[P:%.*]]) #[[ATTR0:[0-9]+]] {
27 ; ATTRIBUTOR-NEXT:    ret ptr [[P]]
29   ret ptr %p
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
34 define 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
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
53   br i1 %c, label %rec, label %end
54 rec:
55   call ptr @test3(i1 %c)
56   br label %end
57 end:
58   ret ptr null
61 define 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]]
68   call ptr @scc_binder(i1 %c)
69   %ret = call ptr @ret_nonnull()
70   ret ptr %ret
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.)
76 define 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]]
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]]
87   %ret = call ptr @test4()
88   ret ptr %ret
91 define 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]]
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]]
102   %ret = call ptr @test4_helper()
103   ret ptr %ret
106 ; Given a mutual recursive set of functions which *can* return null
107 ; make sure we haven't marked them as nonnull.
108 define 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
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
127   br i1 %c, label %rec, label %end
128 rec:
129   %ret = call ptr @test5(i1 %c)
130   br label %end
131 end:
132   ret ptr null
135 define 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]]
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]]
146   %ret = call ptr @test5_helper(i1 %c)
147   ret ptr %ret
150 ; Local analysis, but going through a self recursive phi
151 define 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]]
163 entry:
164   %ret = call ptr @ret_nonnull()
165   br label %loop
166 loop:
167   %phi = phi ptr [%ret, %entry], [%phi, %loop]
168   br i1 %arg, label %loop, label %exit
169 exit:
170   ret ptr %phi
173 define 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]]
185 entry:
186   %ret = call ptr @ret_nonnull()
187   br label %loop
188 loop:
189   %phi = phi ptr [%ret, %entry], [%phi, %loop]
190   br i1 %c, label %loop, label %exit
191 exit:
192   ret ptr %phi
195 define ptr @test7(ptr %a) {
196 ; FNATTRS-LABEL: define ptr @test7(
197 ; FNATTRS-SAME: ptr readnone returned [[A:%.*]]) #[[ATTR0]] {
198 ; FNATTRS-NEXT:    ret ptr [[A]]
200 ; ATTRIBUTOR-LABEL: define ptr @test7(
201 ; ATTRIBUTOR-SAME: ptr nofree readnone [[A:%.*]]) #[[ATTR0]] {
202 ; ATTRIBUTOR-NEXT:    ret ptr [[A]]
204   ret ptr %a
207 define 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]]
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]]
218   %b = getelementptr inbounds i8, ptr %a, i64 1
219   ret ptr %b
222 define 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]]
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]]
233   %b = getelementptr inbounds i8, ptr %a, i64 %n
234   ret ptr %b
237 declare void @llvm.assume(i1)
238 ; FIXME: missing nonnull
239 define 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]]
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]]
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
260 ; TEST 11
261 ; char* test11(char *p) {
262 ;   return p? p: nonnull();
263 ; }
264 define 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]]
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]]
287   %2 = icmp eq ptr %0, null
288   br i1 %2, label %3, label %5
290 ; <label>:3:                                      ; preds = %1
291   %4 = tail call ptr @ret_nonnull()
292   br label %5
294 ; <label>:5:                                      ; preds = %3, %1
295   %6 = phi ptr [ %4, %3 ], [ %0, %1 ]
296   ret ptr %6
299 ; TEST 12
300 ; Simple CallSite Test
301 declare void @test12_helper(ptr)
302 define 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
308   tail call void @test12_helper(ptr %a)
309   ret void
312 ; TEST 13
313 ; Simple Argument Tests
314 declare ptr @unknown()
315 define 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
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 nocapture nofree nonnull readnone [[NONNULLPTR]], ptr nocapture nofree nonnull readnone [[NONNULLPTR]], ptr nocapture nofree readnone [[MAYBENULLPTR]])
327 ; ATTRIBUTOR-NEXT:    tail call void @test13(ptr nocapture nofree nonnull readnone [[NONNULLPTR]], ptr nocapture nofree readnone [[MAYBENULLPTR]], ptr nocapture nofree nonnull readnone [[NONNULLPTR]])
328 ; ATTRIBUTOR-NEXT:    ret void
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
336 define internal void @test13(ptr %a, ptr %b, ptr %c) {
337 ; FNATTRS-LABEL: define internal void @test13(
338 ; FNATTRS-SAME: ptr nocapture readnone [[A:%.*]], ptr nocapture readnone [[B:%.*]], ptr nocapture readnone [[C:%.*]]) #[[ATTR0]] {
339 ; FNATTRS-NEXT:    ret void
341 ; ATTRIBUTOR-LABEL: define internal void @test13(
342 ; ATTRIBUTOR-SAME: ptr nocapture nofree nonnull readnone [[A:%.*]], ptr nocapture nofree readnone [[B:%.*]], ptr nocapture nofree readnone [[C:%.*]]) #[[ATTR0]] {
343 ; ATTRIBUTOR-NEXT:    ret void
345   ret void
348 declare nonnull ptr @nonnull()
350 ; TEST 14
351 ; Complex propagation
352 ; Argument of f1, f2, f3 can be marked with nonnull.
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)
362 define 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]]
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]]
407   %tmp = icmp eq ptr %arg, null
408   br i1 %tmp, label %bb9, label %bb1
410 bb1:                                              ; 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
415 bb4:                                              ; 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
421 bb6:                                              ; 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
426 bb9:                                              ; preds = %bb4, %bb
427   %tmp10 = phi ptr [ %tmp5c, %bb4 ], [ inttoptr (i64 4 to ptr), %bb ]
428   ret ptr %tmp10
431 define 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]]
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]]
447 ; FIXME: missing nonnull. It should be @f1(ptr nonnull readonly %arg)
448   %tmp = tail call ptr @f1(ptr %arg)
449   ret ptr %tmp
452 define 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]]
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]]
467 ; FIXME: missing nonnull. It should be @f1(ptr nonnull readonly %arg)
468   %tmp = call ptr @f1(ptr %arg)
469   ret ptr %tmp
472 ; TEST 15
473 define 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
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
484   tail call void @use1(ptr dereferenceable(4) %arg)
485   ret void
488 declare void @fun0() #1
489 declare void @fun1(ptr) #1
490 declare void @fun2(ptr, ptr) #1
491 declare 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.
498 define 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
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
522   %cmp = icmp eq i8 %c, 0
523   br i1 %cmp, label %if.then, label %if.else
524 if.then:
525   tail call void @fun2(ptr nonnull %a, ptr nonnull %b)
526   ret void
527 if.else:
528   tail call void @fun2(ptr nonnull %a, ptr %b)
529   ret void
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
538 define 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
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
567   %cmp = icmp eq i8 %c, 0
568   br i1 %cmp, label %if.then, label %if.else
569 if.then:
570   tail call void @fun0()
571   br label %cont
572 if.else:
573   tail call void @fun0()
574   br label %cont
575 cont:
576   tail call void @fun1(ptr nonnull %a)
577   ret void
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)
590 define 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
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
637   %cmp1 = icmp eq i8 %c, 0
638   br i1 %cmp1, label %if.then, label %if.else
639 if.then:
640   tail call void @fun0()
641   br label %cont
642 if.else:
643   tail call void @fun0()
644   br label %cont
645 cont:
646   %cmp2 = icmp eq i8 %c, 1
647   br i1 %cmp2, label %cont.then, label %cont.else
648 cont.then:
649   tail call void @fun1(ptr nonnull %b)
650   br label %cont2
651 cont.else:
652   tail call void @fun0()
653   br label %cont2
654 cont2:
655   tail call void @fun1(ptr nonnull %a)
656   ret void
659 ; TEST 19: Loop
661 define 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
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
691   br label %loop.header
692 loop.header:
693   %cmp2 = icmp eq i8 %c, 0
694   br i1 %cmp2, label %loop.body, label %loop.exit
695 loop.body:
696   tail call void @fun1(ptr nonnull %b)
697   tail call void @fun1(ptr nonnull %a)
698   br label %loop.header
699 loop.exit:
700   tail call void @fun1(ptr nonnull %b)
701   ret void
704 ; Test propagation of nonnull callsite args back to caller.
706 declare void @use1(ptr %x)
707 declare void @use2(ptr %x, ptr %y);
708 declare void @use3(ptr %x, ptr %y, ptr %z);
710 declare void @use1nonnull(ptr nonnull noundef %x);
711 declare void @use1nonnull_without_noundef(ptr nonnull %x);
712 declare void @use2nonnull(ptr nonnull noundef %x, ptr nonnull noundef %y);
713 declare void @use3nonnull(ptr nonnull noundef %x, ptr nonnull noundef %y, ptr nonnull noundef %z);
715 declare i8 @use1safecall(ptr %x) nounwind willreturn ; nounwind+willreturn guarantees that execution continues to successor
717 ; Without noundef, nonnull cannot be propagated to the parent
719 define 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
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
731   call void @use1nonnull_without_noundef(ptr %a)
732   ret void
735 ; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute.
737 define 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
744   call void @use3(ptr %c, ptr %a, ptr %b)
745   call void @use3nonnull(ptr %b, ptr %c, ptr %a)
746   ret void
749 ; Extend non-null to parent for all arguments.
751 define 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
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
766   call void @use3nonnull(ptr %b, ptr %c, ptr %a)
767   call void @use3(ptr %c, ptr %a, ptr %b)
768   ret void
771 ; Extend non-null to parent for 1st argument.
773 define 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
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
789   call void @use1nonnull(ptr %a)
790   call void @use3(ptr %c, ptr %b, ptr %a)
791   ret void
794 ; Extend non-null to parent for last 2 arguments.
796 define 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
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
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
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.
826 define 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
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
846   br i1 %a_is_notnull, label %t, label %f
848   call void @use1nonnull(ptr %a)
849   ret void
851   ret void
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.
857 define 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]]
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]]
871   %c = load volatile i8, ptr %b
872   call void @use1nonnull(ptr %a)
873   ret i8 %c
876 ; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent.
878 define 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]]
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]]
895   %ret = call i8 @use1safecall(ptr %a)
896   call void @use1nonnull(ptr %a)
897   ret i8 %ret
900 ; Make sure that an invoke works similarly to a call.
902 declare i32 @esfp(...)
904 define 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 nocapture readnone [[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
918 ; ATTRIBUTOR-LABEL: define i1 @parent8(
919 ; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr nocapture nofree readnone [[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
932 entry:
933   invoke void @use2nonnull(ptr %a, ptr %b)
934   to label %cont unwind label %exc
936 cont:
937   %null_check = icmp eq ptr %b, null
938   ret i1 %null_check
940 exc:
941   %lp = landingpad { ptr, i32 }
942   filter [0 x ptr] zeroinitializer
943   unreachable
946 define 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]]
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]]
957   %q = getelementptr inbounds i32, ptr %p, i32 1
958   ret ptr %q
961 define 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]]
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]]
973   %q = getelementptr inbounds i32, ptr %p, i32 1
974   ret ptr %q
977 define 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]]
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]]
988   %q = getelementptr inbounds i32, ptr addrspace(3) %p, i32 1
989   ret ptr addrspace(3) %q
992 ; FIXME: We should propagate dereferenceable here but *not* nonnull
993 define 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]]
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]]
1002   ret ptr addrspace(3) %p
1005 define 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)
1010 ; ATTRIBUTOR-LABEL: define internal nonnull ptr @g2(
1011 ; ATTRIBUTOR-SAME: ) #[[ATTR0]] {
1012 ; ATTRIBUTOR-NEXT:    ret ptr inttoptr (i64 4 to ptr)
1014   ret ptr inttoptr (i64 4 to ptr)
1017 define  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]]
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]]
1028   %c = call ptr @g2()
1029   ret ptr %c
1032 declare void @use_i32_ptr(ptr) readnone nounwind
1033 define internal void @called_by_weak(ptr %a) {
1034 ; FNATTRS-LABEL: define internal void @called_by_weak(
1035 ; FNATTRS-SAME: ptr nocapture readnone [[A:%.*]]) #[[ATTR1]] {
1036 ; FNATTRS-NEXT:    call void @use_i32_ptr(ptr [[A]])
1037 ; FNATTRS-NEXT:    ret void
1039 ; ATTRIBUTOR-LABEL: define internal void @called_by_weak(
1040 ; ATTRIBUTOR-SAME: ptr nocapture nonnull readnone [[A:%.*]]) #[[ATTR10:[0-9]+]] {
1041 ; ATTRIBUTOR-NEXT:    call void @use_i32_ptr(ptr nonnull [[A]]) #[[ATTR17:[0-9]+]]
1042 ; ATTRIBUTOR-NEXT:    ret void
1044   call void @use_i32_ptr(ptr %a)
1045   ret void
1048 ; Check we do not annotate the function interface of this weak function.
1049 define 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
1055 ; ATTRIBUTOR-LABEL: define weak_odr void @weak_caller(
1056 ; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]]) {
1057 ; ATTRIBUTOR-NEXT:    call void @called_by_weak(ptr nocapture nonnull readnone [[A]])
1058 ; ATTRIBUTOR-NEXT:    ret void
1060   call void @called_by_weak(ptr %a)
1061   ret void
1064 ; Expect nonnull
1065 define internal void @control(ptr dereferenceable(4) %a) {
1066 ; FNATTRS-LABEL: define internal void @control(
1067 ; FNATTRS-SAME: ptr nocapture readnone dereferenceable(4) [[A:%.*]]) #[[ATTR1]] {
1068 ; FNATTRS-NEXT:    call void @use_i32_ptr(ptr [[A]])
1069 ; FNATTRS-NEXT:    ret void
1071 ; ATTRIBUTOR-LABEL: define internal void @control(
1072 ; ATTRIBUTOR-SAME: ptr nocapture nonnull readnone dereferenceable(4) [[A:%.*]]) #[[ATTR10]] {
1073 ; ATTRIBUTOR-NEXT:    call void @use_i32_ptr(ptr [[A]]) #[[ATTR17]]
1074 ; ATTRIBUTOR-NEXT:    ret void
1076   call void @use_i32_ptr(ptr %a)
1077   ret void
1079 ; Avoid nonnull as we do not touch naked functions
1080 define 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
1085 ; ATTRIBUTOR-LABEL: define internal void @naked(
1086 ; ATTRIBUTOR-SAME: ptr nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] {
1087 ; ATTRIBUTOR-NEXT:    ret void
1089   ret void
1091 ; Avoid nonnull as we do not touch optnone
1092 define 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
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
1103   call void @use_i32_ptr(ptr %a)
1104   ret void
1106 define 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
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 nocapture nonnull readnone align 16 dereferenceable(8) [[A]])
1118 ; ATTRIBUTOR-NEXT:    call void @optnone(ptr nonnull align 16 dereferenceable(8) [[A]])
1119 ; ATTRIBUTOR-NEXT:    ret void
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
1127 ;int f(int *u, int n){
1128 ;  for(int i = 0;i<n;i++){
1129 ;    h(u);
1130 ;  }
1131 ;  return g(nonnull u);
1133 declare void @h(ptr) willreturn nounwind
1134 declare i32 @g(ptr) willreturn nounwind
1135 define 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]]
1152   %tmp3 = icmp eq i32 %b, 0
1153   br i1 %tmp3, label %ex, label %hd
1156   %tmp5 = tail call i32 @g(ptr nonnull %a)
1157   ret i32 %tmp5
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
1167 define 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]]
1186   %tmp3 = icmp eq i32 %b, 0
1187   br i1 %tmp3, label %ex, label %hd
1190   %tmp5 = tail call i32 @g(ptr nonnull %a)
1191   ret i32 %tmp5
1194   %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]
1195   tail call void @h(ptr %a)
1196   br label %hd2
1198 hd2:
1199   %tmp8 = add nuw i32 %tmp7, 1
1200   %tmp9 = icmp eq i32 %tmp8, %b
1201   br i1 %tmp9, label %ex, label %hd
1204 define 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]]
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]]
1236   %tmp3 = icmp eq i32 %b, 0
1237   br i1 %tmp3, label %ex, label %hd
1240   %tmp5 = tail call i32 @g(ptr nonnull %a)
1241   ret i32 %tmp5
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
1251 define 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]]
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]]
1287   %tmp3 = icmp eq i32 %b, 0
1288   br i1 %tmp3, label %ex, label %hd
1291   %tmp5 = tail call i32 @g(ptr nonnull %a)
1292   ret i32 %tmp5
1295   %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]
1296   tail call void @h(ptr %a)
1297   br label %hd2
1299 hd2:
1300   %tmp8 = add nuw i32 %tmp7, 1
1301   %tmp9 = icmp eq i32 %tmp8, %b
1302   br i1 %tmp9, label %ex, label %hd
1305 ; Original from PR43833
1306 declare void @sink(ptr)
1308 ; FIXME: the sink argument should be marked nonnull as in @PR43833_simple.
1309 define 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]]
1327   %3 = icmp sgt i32 %1, 1
1328   br i1 %3, label %4, label %7
1330 4:                                                ; preds = %2
1331   %5 = zext i32 %1 to i64
1332   %6 = getelementptr inbounds i32, ptr %0, i64 %5
1333   br label %8
1335 7:                                                ; preds = %8, %2
1336   ret void
1338 8:                                                ; 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
1346 ; Adjusted from PR43833
1347 define 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]]
1365   %3 = icmp ne i32 %1, 0
1366   br i1 %3, label %4, label %7
1368 4:                                                ; preds = %2
1369   %5 = zext i32 %1 to i64
1370   %6 = getelementptr inbounds i32, ptr %0, i64 %5
1371   br label %8
1373 7:                                                ; preds = %8, %2
1374   ret void
1376 8:                                                ; 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
1384 define 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]]
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]]
1395   %res = getelementptr i8, ptr %arg, i64 -8
1396   ret ptr %res
1399 attributes #0 = { null_pointer_is_valid }
1400 attributes #1 = { nounwind willreturn}