1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
6
7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
8
9; Test cases specifically designed for the "undefined behavior" abstract function attribute.
10; We want to verify that whenever undefined behavior is assumed, the code becomes unreachable.
11; We use FIXME's to indicate problems and missing attributes.
12
13; -- Load tests --
14
15define void @load_wholly_unreachable() {
16; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
17; CHECK-LABEL: define {{[^@]+}}@load_wholly_unreachable
18; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
19; CHECK-NEXT:    unreachable
20;
21  %a = load i32, i32* null
22  ret void
23}
24
25define void @loads_wholly_unreachable() {
26; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
27; CHECK-LABEL: define {{[^@]+}}@loads_wholly_unreachable
28; CHECK-SAME: () #[[ATTR0]] {
29; CHECK-NEXT:    unreachable
30;
31  %a = load i32, i32* null
32  %b = load i32, i32* null
33  ret void
34}
35
36
37define void @load_single_bb_unreachable(i1 %cond) {
38; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
39; CHECK-LABEL: define {{[^@]+}}@load_single_bb_unreachable
40; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] {
41; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
42; CHECK:       t:
43; CHECK-NEXT:    unreachable
44; CHECK:       e:
45; CHECK-NEXT:    ret void
46;
47  br i1 %cond, label %t, label %e
48t:
49  %b = load i32, i32* null
50  br label %e
51e:
52  ret void
53}
54
55; Note that while the load is removed (because it's unused), the block
56; is not changed to unreachable
57define void @load_null_pointer_is_defined() null_pointer_is_valid {
58; CHECK: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn
59; CHECK-LABEL: define {{[^@]+}}@load_null_pointer_is_defined
60; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
61; CHECK-NEXT:    ret void
62;
63  %a = load i32, i32* null
64  ret void
65}
66
67define internal i32* @ret_null() {
68; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
69; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_null
70; IS__CGSCC____-SAME: () #[[ATTR0]] {
71; IS__CGSCC____-NEXT:    ret i32* null
72;
73  ret i32* null
74}
75
76define void @load_null_propagated() {
77; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
78; CHECK-LABEL: define {{[^@]+}}@load_null_propagated
79; CHECK-SAME: () #[[ATTR0]] {
80; CHECK-NEXT:    unreachable
81;
82  %ptr = call i32* @ret_null()
83  %a = load i32, i32* %ptr
84  ret void
85}
86
87; -- Store tests --
88
89define void @store_wholly_unreachable() {
90; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
91; CHECK-LABEL: define {{[^@]+}}@store_wholly_unreachable
92; CHECK-SAME: () #[[ATTR0]] {
93; CHECK-NEXT:    unreachable
94;
95  store i32 5, i32* null
96  ret void
97}
98
99define void @store_wholly_unreachable_volatile() {
100; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn
101; CHECK-LABEL: define {{[^@]+}}@store_wholly_unreachable_volatile
102; CHECK-SAME: () #[[ATTR2:[0-9]+]] {
103; CHECK-NEXT:    store volatile i32 5, i32* null, align 4294967296
104; CHECK-NEXT:    ret void
105;
106  store volatile i32 5, i32* null
107  ret void
108}
109
110define void @store_single_bb_unreachable(i1 %cond) {
111; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
112; CHECK-LABEL: define {{[^@]+}}@store_single_bb_unreachable
113; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] {
114; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
115; CHECK:       t:
116; CHECK-NEXT:    unreachable
117; CHECK:       e:
118; CHECK-NEXT:    ret void
119;
120  br i1 %cond, label %t, label %e
121t:
122  store i32 5, i32* null
123  br label %e
124e:
125  ret void
126}
127
128define void @store_null_pointer_is_defined() null_pointer_is_valid {
129; CHECK: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly
130; CHECK-LABEL: define {{[^@]+}}@store_null_pointer_is_defined
131; CHECK-SAME: () #[[ATTR3:[0-9]+]] {
132; CHECK-NEXT:    store i32 5, i32* null, align 4294967296
133; CHECK-NEXT:    ret void
134;
135  store i32 5, i32* null
136  ret void
137}
138
139define void @store_null_propagated() {
140; ATTRIBUTOR-LABEL: @store_null_propagated(
141; ATTRIBUTOR-NEXT:    unreachable
142;
143; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
144; CHECK-LABEL: define {{[^@]+}}@store_null_propagated
145; CHECK-SAME: () #[[ATTR0]] {
146; CHECK-NEXT:    unreachable
147;
148  %ptr = call i32* @ret_null()
149  store i32 5, i32* %ptr
150  ret void
151}
152
153; -- AtomicRMW tests --
154
155define void @atomicrmw_wholly_unreachable() {
156; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn
157; CHECK-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable
158; CHECK-SAME: () #[[ATTR2]] {
159; CHECK-NEXT:    unreachable
160;
161  %a = atomicrmw add i32* null, i32 1 acquire
162  ret void
163}
164
165define void @atomicrmw_single_bb_unreachable(i1 %cond) {
166; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn
167; CHECK-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable
168; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR2]] {
169; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
170; CHECK:       t:
171; CHECK-NEXT:    unreachable
172; CHECK:       e:
173; CHECK-NEXT:    ret void
174;
175  br i1 %cond, label %t, label %e
176t:
177  %a = atomicrmw add i32* null, i32 1 acquire
178  br label %e
179e:
180  ret void
181}
182
183define void @atomicrmw_null_pointer_is_defined() null_pointer_is_valid {
184; CHECK: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn
185; CHECK-LABEL: define {{[^@]+}}@atomicrmw_null_pointer_is_defined
186; CHECK-SAME: () #[[ATTR4:[0-9]+]] {
187; CHECK-NEXT:    [[A:%.*]] = atomicrmw add i32* null, i32 1 acquire, align 4
188; CHECK-NEXT:    ret void
189;
190  %a = atomicrmw add i32* null, i32 1 acquire
191  ret void
192}
193
194define void @atomicrmw_null_propagated() {
195; ATTRIBUTOR-LABEL: @atomicrmw_null_propagated(
196; ATTRIBUTOR-NEXT:    unreachable
197;
198; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn
199; CHECK-LABEL: define {{[^@]+}}@atomicrmw_null_propagated
200; CHECK-SAME: () #[[ATTR2]] {
201; CHECK-NEXT:    unreachable
202;
203  %ptr = call i32* @ret_null()
204  %a = atomicrmw add i32* %ptr, i32 1 acquire
205  ret void
206}
207
208; -- AtomicCmpXchg tests --
209
210define void @atomiccmpxchg_wholly_unreachable() {
211; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn
212; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable
213; CHECK-SAME: () #[[ATTR2]] {
214; CHECK-NEXT:    unreachable
215;
216  %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic
217  ret void
218}
219
220define void @atomiccmpxchg_single_bb_unreachable(i1 %cond) {
221; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn
222; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable
223; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR2]] {
224; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
225; CHECK:       t:
226; CHECK-NEXT:    unreachable
227; CHECK:       e:
228; CHECK-NEXT:    ret void
229;
230  br i1 %cond, label %t, label %e
231t:
232  %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic
233  br label %e
234e:
235  ret void
236}
237
238define void @atomiccmpxchg_null_pointer_is_defined() null_pointer_is_valid {
239; CHECK: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn
240; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_null_pointer_is_defined
241; CHECK-SAME: () #[[ATTR4]] {
242; CHECK-NEXT:    [[A:%.*]] = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic, align 4
243; CHECK-NEXT:    ret void
244;
245  %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic
246  ret void
247}
248
249define void @atomiccmpxchg_null_propagated() {
250; ATTRIBUTOR-LABEL: @atomiccmpxchg_null_propagated(
251; ATTRIBUTOR-NEXT:    unreachable
252;
253; CHECK: Function Attrs: nofree norecurse nounwind readnone willreturn
254; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_null_propagated
255; CHECK-SAME: () #[[ATTR2]] {
256; CHECK-NEXT:    unreachable
257;
258  %ptr = call i32* @ret_null()
259  %a = cmpxchg i32* %ptr, i32 2, i32 3 acq_rel monotonic
260  ret void
261}
262
263; -- Conditional branching tests --
264
265; Note: The unreachable on %t and %e is _not_ from AAUndefinedBehavior
266
267define i32 @cond_br_on_undef() {
268; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
269; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef
270; CHECK-SAME: () #[[ATTR5:[0-9]+]] {
271; CHECK-NEXT:    unreachable
272; CHECK:       t:
273; CHECK-NEXT:    unreachable
274; CHECK:       e:
275; CHECK-NEXT:    unreachable
276;
277  br i1 undef, label %t, label %e
278t:
279  ret i32 1
280e:
281  ret i32 2
282}
283
284; More complicated branching
285  ; Valid branch - verify that this is not converted
286  ; to unreachable.
287define void @cond_br_on_undef2(i1 %cond) {
288; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
289; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef2
290; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] {
291; CHECK-NEXT:    br i1 [[COND]], label [[T1:%.*]], label [[E1:%.*]]
292; CHECK:       t1:
293; CHECK-NEXT:    unreachable
294; CHECK:       t2:
295; CHECK-NEXT:    unreachable
296; CHECK:       e2:
297; CHECK-NEXT:    unreachable
298; CHECK:       e1:
299; CHECK-NEXT:    ret void
300;
301  br i1 %cond, label %t1, label %e1
302t1:
303  br i1 undef, label %t2, label %e2
304t2:
305  ret void
306e2:
307  ret void
308e1:
309  ret void
310}
311
312define i1 @ret_undef() {
313; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
314; CHECK-LABEL: define {{[^@]+}}@ret_undef
315; CHECK-SAME: () #[[ATTR0]] {
316; CHECK-NEXT:    ret i1 undef
317;
318  ret i1 undef
319}
320
321define void @cond_br_on_undef_interproc() {
322; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
323; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc
324; CHECK-SAME: () #[[ATTR5]] {
325; CHECK-NEXT:    unreachable
326; CHECK:       t:
327; CHECK-NEXT:    unreachable
328; CHECK:       e:
329; CHECK-NEXT:    unreachable
330;
331  %cond = call i1 @ret_undef()
332  br i1 %cond, label %t, label %e
333t:
334  ret void
335e:
336  ret void
337}
338
339define i1 @ret_undef2() {
340; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
341; CHECK-LABEL: define {{[^@]+}}@ret_undef2
342; CHECK-SAME: () #[[ATTR0]] {
343; CHECK-NEXT:    br i1 true, label [[T:%.*]], label [[E:%.*]]
344; CHECK:       t:
345; CHECK-NEXT:    ret i1 undef
346; CHECK:       e:
347; CHECK-NEXT:    unreachable
348;
349  br i1 true, label %t, label %e
350t:
351  ret i1 undef
352e:
353  ret i1 undef
354}
355
356; More complicated interproc deduction of undef
357define void @cond_br_on_undef_interproc2() {
358; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
359; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc2
360; CHECK-SAME: () #[[ATTR5]] {
361; CHECK-NEXT:    unreachable
362; CHECK:       t:
363; CHECK-NEXT:    unreachable
364; CHECK:       e:
365; CHECK-NEXT:    unreachable
366;
367  %cond = call i1 @ret_undef2()
368  br i1 %cond, label %t, label %e
369t:
370  ret void
371e:
372  ret void
373}
374
375; Branch on undef that depends on propagation of
376; undef of a previous instruction.
377define i32 @cond_br_on_undef3() {
378; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
379; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef3
380; CHECK-SAME: () #[[ATTR0]] {
381; CHECK-NEXT:    br label [[T:%.*]]
382; CHECK:       t:
383; CHECK-NEXT:    ret i32 1
384; CHECK:       e:
385; CHECK-NEXT:    unreachable
386;
387  %cond = icmp ne i32 1, undef
388  br i1 %cond, label %t, label %e
389t:
390  ret i32 1
391e:
392  ret i32 2
393}
394
395; Branch on undef because of uninitialized value.
396; FIXME: Currently it doesn't propagate the undef.
397define i32 @cond_br_on_undef_uninit() {
398; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
399; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef_uninit
400; CHECK-SAME: () #[[ATTR5]] {
401; CHECK-NEXT:    unreachable
402; CHECK:       t:
403; CHECK-NEXT:    unreachable
404; CHECK:       e:
405; CHECK-NEXT:    unreachable
406;
407  %alloc = alloca i1
408  %cond = load i1, i1* %alloc
409  br i1 %cond, label %t, label %e
410t:
411  ret i32 1
412e:
413  ret i32 2
414}
415
416; Note that the `load` has UB (so it will be changed to unreachable)
417; and the branch is a terminator that can be constant-folded.
418; We want to test that doing both won't cause a segfault.
419; MODULE-NOT: @callee(
420define internal i32 @callee(i1 %C, i32* %A) {
421;
422; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
423; IS__CGSCC____-LABEL: define {{[^@]+}}@callee
424; IS__CGSCC____-SAME: () #[[ATTR0]] {
425; IS__CGSCC____-NEXT:  entry:
426; IS__CGSCC____-NEXT:    unreachable
427; IS__CGSCC____:       T:
428; IS__CGSCC____-NEXT:    unreachable
429; IS__CGSCC____:       F:
430; IS__CGSCC____-NEXT:    ret i32 1
431;
432entry:
433  %A.0 = load i32, i32* null
434  br i1 %C, label %T, label %F
435
436T:
437  ret i32 %A.0
438
439F:
440  ret i32 1
441}
442
443define i32 @foo() {
444; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
445; CHECK-LABEL: define {{[^@]+}}@foo
446; CHECK-SAME: () #[[ATTR0]] {
447; CHECK-NEXT:    ret i32 1
448;
449  %X = call i32 @callee(i1 false, i32* null)
450  ret i32 %X
451}
452
453; Tests for nonnull noundef attribute violation.
454;
455; Tests for argument position
456
457define void @arg_nonnull_1(i32* nonnull %a) {
458; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
459; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_1
460; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] {
461; CHECK-NEXT:    store i32 0, i32* [[A]], align 4
462; CHECK-NEXT:    ret void
463;
464  store i32 0, i32* %a
465  ret void
466}
467
468define void @arg_nonnull_1_noundef_1(i32* nonnull noundef %a) {
469; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
470; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_1_noundef_1
471; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6]] {
472; CHECK-NEXT:    store i32 0, i32* [[A]], align 4
473; CHECK-NEXT:    ret void
474;
475  store i32 0, i32* %a
476  ret void
477}
478
479define void @arg_nonnull_12(i32* nonnull %a, i32* nonnull %b, i32* %c) {
480; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
481; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_12
482; CHECK-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]]) #[[ATTR6]] {
483; CHECK-NEXT:    [[D:%.*]] = icmp eq i32* [[C]], null
484; CHECK-NEXT:    br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
485; CHECK:       t:
486; CHECK-NEXT:    store i32 0, i32* [[A]], align 4
487; CHECK-NEXT:    br label [[RET:%.*]]
488; CHECK:       f:
489; CHECK-NEXT:    store i32 1, i32* [[B]], align 4
490; CHECK-NEXT:    br label [[RET]]
491; CHECK:       ret:
492; CHECK-NEXT:    ret void
493;
494  %d = icmp eq i32* %c, null
495  br i1 %d, label %t, label %f
496t:
497  store i32 0, i32* %a
498  br label %ret
499f:
500  store i32 1, i32* %b
501  br label %ret
502ret:
503  ret void
504}
505
506define void @arg_nonnull_12_noundef_2(i32* nonnull %a, i32* noundef nonnull %b, i32* %c) {
507; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
508; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_12_noundef_2
509; CHECK-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree noundef nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]]) #[[ATTR6]] {
510; CHECK-NEXT:    [[D:%.*]] = icmp eq i32* [[C]], null
511; CHECK-NEXT:    br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
512; CHECK:       t:
513; CHECK-NEXT:    store i32 0, i32* [[A]], align 4
514; CHECK-NEXT:    br label [[RET:%.*]]
515; CHECK:       f:
516; CHECK-NEXT:    store i32 1, i32* [[B]], align 4
517; CHECK-NEXT:    br label [[RET]]
518; CHECK:       ret:
519; CHECK-NEXT:    ret void
520;
521  %d = icmp eq i32* %c, null
522  br i1 %d, label %t, label %f
523t:
524  store i32 0, i32* %a
525  br label %ret
526f:
527  store i32 1, i32* %b
528  br label %ret
529ret:
530  ret void
531}
532
533; Pass null directly to argument with nonnull attribute
534define void @arg_nonnull_violation1_1() {
535; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
536; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_violation1_1
537; CHECK-SAME: () #[[ATTR0]] {
538; CHECK-NEXT:    unreachable
539;
540  call void @arg_nonnull_1(i32* null)
541  ret void
542}
543
544define void @arg_nonnull_violation1_2() {
545; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
546; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_violation1_2
547; CHECK-SAME: () #[[ATTR0]] {
548; CHECK-NEXT:    unreachable
549;
550  call void @arg_nonnull_1_noundef_1(i32* null)
551  ret void
552}
553
554; A case that depends on value simplification
555define void @arg_nonnull_violation2_1(i1 %c) {
556; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
557; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_violation2_1
558; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
559; CHECK-NEXT:    unreachable
560;
561  %null = getelementptr i32, i32* null, i32 0
562  %mustnull = select i1 %c, i32* null, i32* %null
563  call void @arg_nonnull_1(i32* %mustnull)
564  ret void
565}
566
567define void @arg_nonnull_violation2_2(i1 %c) {
568; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
569; CHECK-LABEL: define {{[^@]+}}@arg_nonnull_violation2_2
570; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
571; CHECK-NEXT:    unreachable
572;
573  %null = getelementptr i32, i32* null, i32 0
574  %mustnull = select i1 %c, i32* null, i32* %null
575  call void @arg_nonnull_1_noundef_1(i32* %mustnull)
576  ret void
577}
578
579; Cases for single and multiple violation at a callsite
580define void @arg_nonnull_violation3_1(i1 %c) {
581; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
582; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_1
583; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
584; IS__TUNIT____-NEXT:    [[PTR:%.*]] = alloca i32, align 4
585; IS__TUNIT____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
586; IS__TUNIT____:       t:
587; IS__TUNIT____-NEXT:    call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR7:[0-9]+]]
588; IS__TUNIT____-NEXT:    call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR7]]
589; IS__TUNIT____-NEXT:    unreachable
590; IS__TUNIT____:       f:
591; IS__TUNIT____-NEXT:    unreachable
592; IS__TUNIT____:       ret:
593; IS__TUNIT____-NEXT:    ret void
594;
595; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
596; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_1
597; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
598; IS__CGSCC____-NEXT:    [[PTR:%.*]] = alloca i32, align 4
599; IS__CGSCC____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
600; IS__CGSCC____:       t:
601; IS__CGSCC____-NEXT:    call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR8:[0-9]+]]
602; IS__CGSCC____-NEXT:    call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR8]]
603; IS__CGSCC____-NEXT:    unreachable
604; IS__CGSCC____:       f:
605; IS__CGSCC____-NEXT:    unreachable
606; IS__CGSCC____:       ret:
607; IS__CGSCC____-NEXT:    ret void
608;
609  %ptr = alloca i32
610  br i1 %c, label %t, label %f
611t:
612  call void @arg_nonnull_12(i32* %ptr, i32* %ptr, i32* %ptr)
613  call void @arg_nonnull_12(i32* %ptr, i32* %ptr, i32* null)
614  call void @arg_nonnull_12(i32* %ptr, i32* null, i32* %ptr)
615  call void @arg_nonnull_12(i32* %ptr, i32* null, i32* null)
616  br label %ret
617f:
618  call void @arg_nonnull_12(i32* null, i32* %ptr, i32* %ptr)
619  call void @arg_nonnull_12(i32* null, i32* %ptr, i32* null)
620  call void @arg_nonnull_12(i32* null, i32* null, i32* %ptr)
621  call void @arg_nonnull_12(i32* null, i32* null, i32* null)
622  br label %ret
623ret:
624  ret void
625}
626
627define void @arg_nonnull_violation3_2(i1 %c) {
628; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
629; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_2
630; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
631; IS__TUNIT____-NEXT:    [[PTR:%.*]] = alloca i32, align 4
632; IS__TUNIT____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
633; IS__TUNIT____:       t:
634; IS__TUNIT____-NEXT:    call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR7]]
635; IS__TUNIT____-NEXT:    call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR7]]
636; IS__TUNIT____-NEXT:    unreachable
637; IS__TUNIT____:       f:
638; IS__TUNIT____-NEXT:    unreachable
639; IS__TUNIT____:       ret:
640; IS__TUNIT____-NEXT:    ret void
641;
642; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
643; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_2
644; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
645; IS__CGSCC____-NEXT:    [[PTR:%.*]] = alloca i32, align 4
646; IS__CGSCC____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
647; IS__CGSCC____:       t:
648; IS__CGSCC____-NEXT:    call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR8]]
649; IS__CGSCC____-NEXT:    call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR8]]
650; IS__CGSCC____-NEXT:    unreachable
651; IS__CGSCC____:       f:
652; IS__CGSCC____-NEXT:    unreachable
653; IS__CGSCC____:       ret:
654; IS__CGSCC____-NEXT:    ret void
655;
656  %ptr = alloca i32
657  br i1 %c, label %t, label %f
658t:
659  call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* %ptr, i32* %ptr)
660  call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* %ptr, i32* null)
661  call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* null, i32* %ptr)
662  call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* null, i32* null)
663  br label %ret
664f:
665  call void @arg_nonnull_12_noundef_2(i32* null, i32* %ptr, i32* %ptr)
666  call void @arg_nonnull_12_noundef_2(i32* null, i32* %ptr, i32* null)
667  call void @arg_nonnull_12_noundef_2(i32* null, i32* null, i32* %ptr)
668  call void @arg_nonnull_12_noundef_2(i32* null, i32* null, i32* null)
669  br label %ret
670ret:
671  ret void
672}
673
674; Tests for returned position
675
676define nonnull i32* @returned_nonnnull(i32 %c) {
677; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
678; CHECK-LABEL: define {{[^@]+}}@returned_nonnnull
679; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
680; CHECK-NEXT:    switch i32 [[C]], label [[ONDEFAULT:%.*]] [
681; CHECK-NEXT:    i32 0, label [[ONZERO:%.*]]
682; CHECK-NEXT:    i32 1, label [[ONONE:%.*]]
683; CHECK-NEXT:    ]
684; CHECK:       onzero:
685; CHECK-NEXT:    [[PTR:%.*]] = alloca i32, align 4
686; CHECK-NEXT:    ret i32* [[PTR]]
687; CHECK:       onone:
688; CHECK-NEXT:    ret i32* null
689; CHECK:       ondefault:
690; CHECK-NEXT:    ret i32* undef
691;
692  switch i32 %c, label %ondefault [ i32 0, label %onzero
693  i32 1, label %onone ]
694onzero:
695  %ptr = alloca i32
696  ret i32* %ptr
697onone:
698  ret i32* null
699ondefault:
700  ret i32* undef
701}
702
703define noundef i32* @returned_noundef(i32 %c) {
704; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
705; CHECK-LABEL: define {{[^@]+}}@returned_noundef
706; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
707; CHECK-NEXT:    switch i32 [[C]], label [[ONDEFAULT:%.*]] [
708; CHECK-NEXT:    i32 0, label [[ONZERO:%.*]]
709; CHECK-NEXT:    i32 1, label [[ONONE:%.*]]
710; CHECK-NEXT:    ]
711; CHECK:       onzero:
712; CHECK-NEXT:    [[PTR:%.*]] = alloca i32, align 4
713; CHECK-NEXT:    ret i32* [[PTR]]
714; CHECK:       onone:
715; CHECK-NEXT:    ret i32* null
716; CHECK:       ondefault:
717; CHECK-NEXT:    unreachable
718;
719  switch i32 %c, label %ondefault [ i32 0, label %onzero
720  i32 1, label %onone ]
721onzero:
722  %ptr = alloca i32
723  ret i32* %ptr
724onone:
725  ret i32* null
726ondefault:
727  ret i32* undef
728}
729
730define nonnull noundef i32* @returned_nonnnull_noundef(i32 %c) {
731; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
732; CHECK-LABEL: define {{[^@]+}}@returned_nonnnull_noundef
733; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
734; CHECK-NEXT:    switch i32 [[C]], label [[ONDEFAULT:%.*]] [
735; CHECK-NEXT:    i32 0, label [[ONZERO:%.*]]
736; CHECK-NEXT:    i32 1, label [[ONONE:%.*]]
737; CHECK-NEXT:    ]
738; CHECK:       onzero:
739; CHECK-NEXT:    [[PTR:%.*]] = alloca i32, align 4
740; CHECK-NEXT:    ret i32* [[PTR]]
741; CHECK:       onone:
742; CHECK-NEXT:    unreachable
743; CHECK:       ondefault:
744; CHECK-NEXT:    unreachable
745;
746  switch i32 %c, label %ondefault [ i32 0, label %onzero
747  i32 1, label %onone ]
748onzero:
749  %ptr = alloca i32
750  ret i32* %ptr
751onone:
752  ret i32* null
753ondefault:
754  ret i32* undef
755}
756
757define noundef i32 @returned_nonnnull_noundef_int() {
758; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
759; CHECK-LABEL: define {{[^@]+}}@returned_nonnnull_noundef_int
760; CHECK-SAME: () #[[ATTR0]] {
761; CHECK-NEXT:    ret i32 0
762;
763  ret i32 0
764}
765
766declare void @callee_int_arg(i32)
767
768define void @callsite_noundef_1() {
769; CHECK-LABEL: define {{[^@]+}}@callsite_noundef_1() {
770; CHECK-NEXT:    call void @callee_int_arg(i32 noundef 0)
771; CHECK-NEXT:    ret void
772;
773  call void @callee_int_arg(i32 noundef 0)
774  ret void
775}
776
777declare void @callee_ptr_arg(i32*)
778
779define void @callsite_noundef_2() {
780; CHECK-LABEL: define {{[^@]+}}@callsite_noundef_2() {
781; CHECK-NEXT:    unreachable
782;
783  call void @callee_ptr_arg(i32* noundef undef)
784  ret void
785}
786
787define i32 @argument_noundef1(i32 noundef %c) {
788; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
789; CHECK-LABEL: define {{[^@]+}}@argument_noundef1
790; CHECK-SAME: (i32 noundef returned [[C:%.*]]) #[[ATTR0]] {
791; CHECK-NEXT:    ret i32 [[C]]
792;
793  ret i32 %c
794}
795
796define i32 @violate_noundef_nonpointer() {
797; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
798; CHECK-LABEL: define {{[^@]+}}@violate_noundef_nonpointer
799; CHECK-SAME: () #[[ATTR0]] {
800; CHECK-NEXT:    ret i32 undef
801;
802  %ret = call i32 @argument_noundef1(i32 undef)
803  ret i32 %ret
804}
805
806define i32* @argument_noundef2(i32* noundef %c) {
807; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
808; CHECK-LABEL: define {{[^@]+}}@argument_noundef2
809; CHECK-SAME: (i32* nofree noundef readnone returned "no-capture-maybe-returned" [[C:%.*]]) #[[ATTR0]] {
810; CHECK-NEXT:    ret i32* [[C]]
811;
812  ret i32* %c
813}
814
815define i32* @violate_noundef_pointer() {
816; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
817; CHECK-LABEL: define {{[^@]+}}@violate_noundef_pointer
818; CHECK-SAME: () #[[ATTR0]] {
819; CHECK-NEXT:    ret i32* undef
820;
821  %ret = call i32* @argument_noundef2(i32* undef)
822  ret i32* %ret
823}
824
825define internal noundef i32 @assumed_undef_is_ok(i1 %c, i32 %arg) {
826; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
827; IS__CGSCC____-LABEL: define {{[^@]+}}@assumed_undef_is_ok
828; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR7:[0-9]+]] {
829; IS__CGSCC____-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[RET:%.*]]
830; IS__CGSCC____:       rec:
831; IS__CGSCC____-NEXT:    br label [[RET]]
832; IS__CGSCC____:       ret:
833; IS__CGSCC____-NEXT:    ret i32 0
834;
835  %stack = alloca i32
836  store i32 %arg, i32* %stack
837  br i1 %c, label %rec, label %ret
838rec:
839  %call = call i32 @assumed_undef_is_ok(i1 false, i32 0)
840  store i32 %call, i32* %stack
841  br label %ret
842ret:
843  %l = load i32, i32* %stack
844  ret i32 %l
845}
846
847define noundef i32 @assumed_undef_is_ok_caller(i1 %c) {
848; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
849; CHECK-LABEL: define {{[^@]+}}@assumed_undef_is_ok_caller
850; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
851; CHECK-NEXT:    ret i32 0
852;
853  %call = call i32 @assumed_undef_is_ok(i1 %c, i32 undef)
854  ret i32 %call
855}
856
857;.
858; IS__TUNIT____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
859; IS__TUNIT____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn }
860; IS__TUNIT____: attributes #[[ATTR2]] = { nofree norecurse nounwind readnone willreturn }
861; IS__TUNIT____: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly }
862; IS__TUNIT____: attributes #[[ATTR4]] = { nofree norecurse nounwind null_pointer_is_valid willreturn }
863; IS__TUNIT____: attributes #[[ATTR5]] = { nofree norecurse noreturn nosync nounwind readnone willreturn }
864; IS__TUNIT____: attributes #[[ATTR6]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
865; IS__TUNIT____: attributes #[[ATTR7]] = { nofree nosync nounwind willreturn writeonly }
866;.
867; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
868; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn }
869; IS__CGSCC____: attributes #[[ATTR2]] = { nofree norecurse nounwind readnone willreturn }
870; IS__CGSCC____: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly }
871; IS__CGSCC____: attributes #[[ATTR4]] = { nofree norecurse nounwind null_pointer_is_valid willreturn }
872; IS__CGSCC____: attributes #[[ATTR5]] = { nofree norecurse noreturn nosync nounwind readnone willreturn }
873; IS__CGSCC____: attributes #[[ATTR6]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
874; IS__CGSCC____: attributes #[[ATTR7]] = { nofree nosync nounwind readnone willreturn }
875; IS__CGSCC____: attributes #[[ATTR8]] = { nounwind willreturn writeonly }
876;.
877