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