xref: /llvm-project/llvm/test/Transforms/Attributor/heap_to_stack.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
5declare noalias ptr @malloc(i64) allockind("alloc,uninitialized") allocsize(0)
6
7declare void @nocapture_func_frees_pointer(ptr nocapture)
8
9declare void @func_throws(...)
10
11declare void @sync_func(ptr %p)
12
13declare void @sync_will_return(ptr %p) willreturn nounwind
14
15declare void @no_sync_func(ptr nocapture %p) nofree nosync willreturn
16
17declare void @nofree_func(ptr nocapture %p) nofree  nosync willreturn
18
19declare void @foo(ptr %p)
20
21declare void @foo_nounw(ptr %p) nounwind nofree
22
23declare void @usei8(i8)
24declare void @usei8p(ptr nocapture)
25
26declare i32 @no_return_call() noreturn
27
28declare void @free(ptr nocapture) allockind("free")
29
30declare void @llvm.lifetime.start.p0(i64, ptr nocapture) nounwind
31
32;.
33; CHECK: @G = internal global ptr undef, align 4
34;.
35define void @h2s_value_simplify_interaction(i1 %c, ptr %A) {
36; CHECK-LABEL: define {{[^@]+}}@h2s_value_simplify_interaction
37; CHECK-SAME: (i1 [[C:%.*]], ptr nofree readnone captures(none) [[A:%.*]]) {
38; CHECK-NEXT:  entry:
39; CHECK-NEXT:    [[ADD:%.*]] = add i64 2, 2
40; CHECK-NEXT:    [[M:%.*]] = tail call noalias align 16 ptr @malloc(i64 noundef [[ADD]])
41; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
42; CHECK:       t:
43; CHECK-NEXT:    br i1 false, label [[DEAD:%.*]], label [[F2:%.*]]
44; CHECK:       f:
45; CHECK-NEXT:    br label [[J:%.*]]
46; CHECK:       f2:
47; CHECK-NEXT:    [[L:%.*]] = load i8, ptr [[M]], align 16
48; CHECK-NEXT:    call void @usei8(i8 [[L]])
49; CHECK-NEXT:    call void @no_sync_func(ptr noalias nofree noundef nonnull align 16 captures(none) dereferenceable(1) [[M]]) #[[ATTR11:[0-9]+]]
50; CHECK-NEXT:    br label [[J]]
51; CHECK:       dead:
52; CHECK-NEXT:    unreachable
53; CHECK:       j:
54; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[M]], [[F]] ], [ null, [[F2]] ]
55; CHECK-NEXT:    tail call void @no_sync_func(ptr nofree noundef align 16 captures(none) [[PHI]]) #[[ATTR11]]
56; CHECK-NEXT:    ret void
57;
58entry:
59  %add = add i64 2, 2
60  %m = tail call noalias align 16 ptr @malloc(i64 %add)
61  br i1 %c, label %t, label %f
62
63t:
64  br i1 false, label %dead, label %f2
65
66f:
67  br label %j
68
69f2:
70  %l = load i8, ptr %m, align 1
71  call void @usei8(i8 %l)
72  call void @no_sync_func(ptr noundef %m) nounwind
73  br label %j
74
75dead:
76  br label %j
77
78j:
79  %phi = phi ptr [ %m, %f ], [ null, %f2 ], [ %A, %dead ]
80  tail call void @no_sync_func(ptr noundef %phi) nounwind
81  ret void
82}
83
84define void @nofree_arg_only(ptr %p1, ptr %p2) {
85; CHECK-LABEL: define {{[^@]+}}@nofree_arg_only
86; CHECK-SAME: (ptr nofree captures(none) [[P1:%.*]], ptr captures(none) [[P2:%.*]]) {
87; CHECK-NEXT:  bb:
88; CHECK-NEXT:    tail call void @free(ptr captures(none) [[P2]])
89; CHECK-NEXT:    tail call void @nofree_func(ptr nofree captures(none) [[P1]])
90; CHECK-NEXT:    ret void
91;
92bb:
93  tail call void @free(ptr %p2)
94  tail call void @nofree_func(ptr %p1)
95  ret void
96}
97
98; TEST 1 - negative, pointer freed in another function.
99
100define void @test1() {
101; CHECK-LABEL: define {{[^@]+}}@test1() {
102; CHECK-NEXT:  bb:
103; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
104; CHECK-NEXT:    tail call void @nocapture_func_frees_pointer(ptr noalias captures(none) [[I]])
105; CHECK-NEXT:    tail call void (...) @func_throws()
106; CHECK-NEXT:    tail call void @free(ptr noalias captures(none) [[I]])
107; CHECK-NEXT:    ret void
108;
109bb:
110  %i = tail call noalias ptr @malloc(i64 4)
111  tail call void @nocapture_func_frees_pointer(ptr %i)
112  tail call void (...) @func_throws()
113  tail call void @free(ptr %i)
114  ret void
115}
116
117; TEST 2 - negative, call to a sync function.
118
119define void @test2() {
120; CHECK-LABEL: define {{[^@]+}}@test2() {
121; CHECK-NEXT:  bb:
122; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
123; CHECK-NEXT:    tail call void @sync_func(ptr [[I]])
124; CHECK-NEXT:    tail call void @free(ptr captures(none) [[I]])
125; CHECK-NEXT:    ret void
126;
127bb:
128  %i = tail call noalias ptr @malloc(i64 4)
129  tail call void @sync_func(ptr %i)
130  tail call void @free(ptr %i)
131  ret void
132}
133
134; TEST 3 - 1 malloc, 1 free
135
136define void @test3() {
137; CHECK-LABEL: define {{[^@]+}}@test3() {
138; CHECK-NEXT:  bb:
139; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
140; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree captures(none) [[I_H2S]])
141; CHECK-NEXT:    ret void
142;
143bb:
144  %i = tail call noalias ptr @malloc(i64 4)
145  tail call void @no_sync_func(ptr %i)
146  tail call void @free(ptr %i)
147  ret void
148}
149
150define void @test3a(ptr %p) {
151; CHECK-LABEL: define {{[^@]+}}@test3a
152; CHECK-SAME: (ptr captures(none) [[P:%.*]]) {
153; CHECK-NEXT:  bb:
154; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
155; CHECK-NEXT:    tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I_H2S]], ptr captures(none) [[P]])
156; CHECK-NEXT:    ret void
157;
158bb:
159  %i = tail call noalias ptr @malloc(i64 4)
160  tail call void @nofree_arg_only(ptr %i, ptr %p)
161  tail call void @free(ptr %i)
162  ret void
163}
164
165declare noalias ptr @aligned_alloc(i64 allocalign, i64) allockind("alloc,uninitialized,aligned") allocsize(1)
166
167define void @test3b(ptr %p) {
168; CHECK-LABEL: define {{[^@]+}}@test3b
169; CHECK-SAME: (ptr captures(none) [[P:%.*]]) {
170; CHECK-NEXT:  bb:
171; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 128, align 32
172; CHECK-NEXT:    tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I_H2S]], ptr captures(none) [[P]])
173; CHECK-NEXT:    ret void
174;
175bb:
176  %i = tail call noalias ptr @aligned_alloc(i64 32, i64 128)
177  tail call void @nofree_arg_only(ptr %i, ptr %p)
178  tail call void @free(ptr %i)
179  ret void
180}
181
182; leave alone non-constant alignments.
183define void @test3c(i64 %alignment) {
184; CHECK-LABEL: define {{[^@]+}}@test3c
185; CHECK-SAME: (i64 [[ALIGNMENT:%.*]]) {
186; CHECK-NEXT:  bb:
187; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @aligned_alloc(i64 [[ALIGNMENT]], i64 noundef 128)
188; CHECK-NEXT:    tail call void @free(ptr noalias captures(none) [[I]])
189; CHECK-NEXT:    ret void
190;
191bb:
192  %i = tail call noalias ptr @aligned_alloc(i64 %alignment, i64 128)
193  tail call void @free(ptr %i)
194  ret void
195}
196
197; leave alone a constant-but-invalid alignment
198define void @test3d(ptr %p) {
199; CHECK-LABEL: define {{[^@]+}}@test3d
200; CHECK-SAME: (ptr captures(none) [[P:%.*]]) {
201; CHECK-NEXT:  bb:
202; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @aligned_alloc(i64 noundef 33, i64 noundef 128)
203; CHECK-NEXT:    tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I]], ptr captures(none) [[P]])
204; CHECK-NEXT:    tail call void @free(ptr noalias captures(none) [[I]])
205; CHECK-NEXT:    ret void
206;
207bb:
208  %i = tail call noalias ptr @aligned_alloc(i64 33, i64 128)
209  tail call void @nofree_arg_only(ptr %i, ptr %p)
210  tail call void @free(ptr %i)
211  ret void
212}
213
214declare noalias ptr @calloc(i64, i64) allockind("alloc,zeroed") allocsize(0,1)
215
216define void @test0() {
217; CHECK-LABEL: define {{[^@]+}}@test0() {
218; CHECK-NEXT:  bb:
219; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 8, align 1
220; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[I_H2S]], i8 0, i64 8, i1 false)
221; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree captures(none) [[I_H2S]])
222; CHECK-NEXT:    ret void
223;
224bb:
225  %i = tail call noalias ptr @calloc(i64 2, i64 4)
226  tail call void @no_sync_func(ptr %i)
227  tail call void @free(ptr %i)
228  ret void
229}
230
231; TEST 4
232define void @test4() {
233; CHECK-LABEL: define {{[^@]+}}@test4() {
234; CHECK-NEXT:  bb:
235; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
236; CHECK-NEXT:    tail call void @nofree_func(ptr noalias nofree captures(none) [[I_H2S]])
237; CHECK-NEXT:    ret void
238;
239bb:
240  %i = tail call noalias ptr @malloc(i64 4)
241  tail call void @nofree_func(ptr %i)
242  ret void
243}
244
245; TEST 5 - not all exit paths have a call to free, but all uses of malloc
246; are in nofree functions and are not captured
247
248define void @test5(i32 %arg, ptr %p) {
249; CHECK-LABEL: define {{[^@]+}}@test5
250; CHECK-SAME: (i32 [[ARG:%.*]], ptr captures(none) [[P:%.*]]) {
251; CHECK-NEXT:  bb:
252; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
253; CHECK-NEXT:    [[I1:%.*]] = icmp eq i32 [[ARG]], 0
254; CHECK-NEXT:    br i1 [[I1]], label [[BB3:%.*]], label [[BB2:%.*]]
255; CHECK:       bb2:
256; CHECK-NEXT:    tail call void @nofree_func(ptr noalias nofree captures(none) [[I_H2S]])
257; CHECK-NEXT:    br label [[BB4:%.*]]
258; CHECK:       bb3:
259; CHECK-NEXT:    tail call void @nofree_arg_only(ptr noalias nofree captures(none) [[I_H2S]], ptr captures(none) [[P]])
260; CHECK-NEXT:    br label [[BB4]]
261; CHECK:       bb4:
262; CHECK-NEXT:    ret void
263;
264bb:
265  %i = tail call noalias ptr @malloc(i64 4)
266  %i1 = icmp eq i32 %arg, 0
267  br i1 %i1, label %bb3, label %bb2
268
269bb2:
270  tail call void @nofree_func(ptr %i)
271  br label %bb4
272
273bb3:
274  tail call void @nofree_arg_only(ptr %i, ptr %p)
275  tail call void @free(ptr %i)
276  br label %bb4
277
278bb4:
279  ret void
280}
281
282; TEST 6 - all exit paths have a call to free
283
284define void @test6(i32 %arg) {
285; CHECK-LABEL: define {{[^@]+}}@test6
286; CHECK-SAME: (i32 [[ARG:%.*]]) {
287; CHECK-NEXT:  bb:
288; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
289; CHECK-NEXT:    [[I1:%.*]] = icmp eq i32 [[ARG]], 0
290; CHECK-NEXT:    br i1 [[I1]], label [[BB3:%.*]], label [[BB2:%.*]]
291; CHECK:       bb2:
292; CHECK-NEXT:    tail call void @nofree_func(ptr noalias nofree captures(none) [[I_H2S]])
293; CHECK-NEXT:    br label [[BB4:%.*]]
294; CHECK:       bb3:
295; CHECK-NEXT:    br label [[BB4]]
296; CHECK:       bb4:
297; CHECK-NEXT:    ret void
298;
299bb:
300  %i = tail call noalias ptr @malloc(i64 4)
301  %i1 = icmp eq i32 %arg, 0
302  br i1 %i1, label %bb3, label %bb2
303
304bb2:
305  tail call void @nofree_func(ptr %i)
306  tail call void @free(ptr %i)
307  br label %bb4
308
309bb3:
310  tail call void @free(ptr %i)
311  br label %bb4
312
313bb4:
314  ret void
315}
316
317; TEST 7 - free is dead.
318
319define void @test7() {
320; CHECK-LABEL: define {{[^@]+}}@test7() {
321; CHECK-NEXT:  bb:
322; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
323; CHECK-NEXT:    [[I1:%.*]] = tail call i32 @no_return_call() #[[ATTR4:[0-9]+]]
324; CHECK-NEXT:    unreachable
325;
326bb:
327  %i = tail call noalias ptr @malloc(i64 4)
328  %i1 = tail call i32 @no_return_call()
329  tail call void @free(ptr %i)
330  ret void
331}
332
333; TEST 8 - Negative: bitcast pointer used in capture function
334
335define void @test8() {
336; CHECK-LABEL: define {{[^@]+}}@test8() {
337; CHECK-NEXT:  bb:
338; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
339; CHECK-NEXT:    tail call void @no_sync_func(ptr nofree captures(none) [[I]])
340; CHECK-NEXT:    store i32 10, ptr [[I]], align 4
341; CHECK-NEXT:    tail call void @foo(ptr nonnull align 4 dereferenceable(4) [[I]])
342; CHECK-NEXT:    tail call void @free(ptr nonnull align 4 captures(none) dereferenceable(4) [[I]])
343; CHECK-NEXT:    ret void
344;
345bb:
346  %i = tail call noalias ptr @malloc(i64 4)
347  tail call void @no_sync_func(ptr %i)
348  store i32 10, ptr %i, align 4
349  %i2 = load i32, ptr %i, align 4
350  tail call void @foo(ptr %i)
351  tail call void @free(ptr %i)
352  ret void
353}
354
355; TEST 9 - FIXME: malloc should be converted.
356define void @test9() {
357; CHECK-LABEL: define {{[^@]+}}@test9() {
358; CHECK-NEXT:  bb:
359; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
360; CHECK-NEXT:    tail call void @no_sync_func(ptr nofree captures(none) [[I]])
361; CHECK-NEXT:    store i32 10, ptr [[I]], align 4
362; CHECK-NEXT:    tail call void @foo_nounw(ptr nofree nonnull align 4 dereferenceable(4) [[I]]) #[[ATTR11]]
363; CHECK-NEXT:    tail call void @free(ptr nonnull align 4 captures(none) dereferenceable(4) [[I]])
364; CHECK-NEXT:    ret void
365;
366bb:
367  %i = tail call noalias ptr @malloc(i64 4)
368  tail call void @no_sync_func(ptr %i)
369  store i32 10, ptr %i, align 4
370  %i2 = load i32, ptr %i, align 4
371  tail call void @foo_nounw(ptr %i)
372  tail call void @free(ptr %i)
373  ret void
374}
375
376; TEST 10 - 1 malloc, 1 free
377
378define i32 @test10() {
379; CHECK-LABEL: define {{[^@]+}}@test10() {
380; CHECK-NEXT:  bb:
381; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
382; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree captures(none) [[I_H2S]])
383; CHECK-NEXT:    store i32 10, ptr [[I_H2S]], align 4
384; CHECK-NEXT:    [[I2:%.*]] = load i32, ptr [[I_H2S]], align 4
385; CHECK-NEXT:    ret i32 [[I2]]
386;
387bb:
388  %i = tail call noalias ptr @malloc(i64 4)
389  tail call void @no_sync_func(ptr %i)
390  store i32 10, ptr %i, align 4
391  %i2 = load i32, ptr %i, align 4
392  tail call void @free(ptr %i)
393  ret i32 %i2
394}
395
396define i32 @test_lifetime() {
397; CHECK-LABEL: define {{[^@]+}}@test_lifetime() {
398; CHECK-NEXT:  bb:
399; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
400; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree captures(none) [[I_H2S]])
401; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nofree nonnull align 4 captures(none) dereferenceable(4) [[I_H2S]])
402; CHECK-NEXT:    store i32 10, ptr [[I_H2S]], align 4
403; CHECK-NEXT:    [[I2:%.*]] = load i32, ptr [[I_H2S]], align 4
404; CHECK-NEXT:    ret i32 [[I2]]
405;
406bb:
407  %i = tail call noalias ptr @malloc(i64 4)
408  tail call void @no_sync_func(ptr %i)
409  call void @llvm.lifetime.start.p0(i64 4, ptr %i)
410  store i32 10, ptr %i, align 4
411  %i2 = load i32, ptr %i, align 4
412  tail call void @free(ptr %i)
413  ret i32 %i2
414}
415
416; TEST 11
417
418define void @test11() {
419; CHECK-LABEL: define {{[^@]+}}@test11() {
420; CHECK-NEXT:  bb:
421; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
422; CHECK-NEXT:    tail call void @sync_will_return(ptr [[I_H2S]]) #[[ATTR11]]
423; CHECK-NEXT:    ret void
424;
425bb:
426  %i = tail call noalias ptr @malloc(i64 4)
427  tail call void @sync_will_return(ptr %i)
428  tail call void @free(ptr %i)
429  ret void
430}
431
432; TEST 12
433define i32 @irreducible_cfg(i32 %arg) {
434; CHECK-LABEL: define {{[^@]+}}@irreducible_cfg
435; CHECK-SAME: (i32 [[ARG:%.*]]) {
436; CHECK-NEXT:  bb:
437; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
438; CHECK-NEXT:    store i32 10, ptr [[I_H2S]], align 4
439; CHECK-NEXT:    [[I2:%.*]] = icmp eq i32 [[ARG]], 1
440; CHECK-NEXT:    br i1 [[I2]], label [[BB3:%.*]], label [[BB5:%.*]]
441; CHECK:       bb3:
442; CHECK-NEXT:    [[I4:%.*]] = add nsw i32 [[ARG]], 5
443; CHECK-NEXT:    br label [[BB11:%.*]]
444; CHECK:       bb5:
445; CHECK-NEXT:    br label [[BB6:%.*]]
446; CHECK:       bb6:
447; CHECK-NEXT:    [[DOT0:%.*]] = phi i32 [ [[I12:%.*]], [[BB11]] ], [ 1, [[BB5]] ]
448; CHECK-NEXT:    [[I7:%.*]] = load i32, ptr [[I_H2S]], align 4
449; CHECK-NEXT:    [[I8:%.*]] = add nsw i32 [[I7]], -1
450; CHECK-NEXT:    store i32 [[I8]], ptr [[I_H2S]], align 4
451; CHECK-NEXT:    [[I9:%.*]] = icmp ne i32 [[I7]], 0
452; CHECK-NEXT:    br i1 [[I9]], label [[BB10:%.*]], label [[BB13:%.*]]
453; CHECK:       bb10:
454; CHECK-NEXT:    br label [[BB11]]
455; CHECK:       bb11:
456; CHECK-NEXT:    [[DOT1:%.*]] = phi i32 [ [[I4]], [[BB3]] ], [ [[DOT0]], [[BB10]] ]
457; CHECK-NEXT:    [[I12]] = add nsw i32 [[DOT1]], 1
458; CHECK-NEXT:    br label [[BB6]]
459; CHECK:       bb13:
460; CHECK-NEXT:    [[I16:%.*]] = load i32, ptr [[I_H2S]], align 4
461; CHECK-NEXT:    ret i32 [[I16]]
462;
463bb:
464  %i = call noalias ptr @malloc(i64 4)
465  store i32 10, ptr %i, align 4
466  %i2 = icmp eq i32 %arg, 1
467  br i1 %i2, label %bb3, label %bb5
468
469bb3:
470  %i4 = add nsw i32 %arg, 5
471  br label %bb11
472
473bb5:
474  br label %bb6
475
476bb6:
477  %.0 = phi i32 [ %i12, %bb11 ], [ 1, %bb5 ]
478  %i7 = load i32, ptr %i, align 4
479  %i8 = add nsw i32 %i7, -1
480  store i32 %i8, ptr %i, align 4
481  %i9 = icmp ne i32 %i7, 0
482  br i1 %i9, label %bb10, label %bb13
483
484bb10:
485  br label %bb11
486
487bb11:
488  %.1 = phi i32 [ %i4, %bb3 ], [ %.0, %bb10 ]
489  %i12 = add nsw i32 %.1, 1
490  br label %bb6
491
492bb13:
493  %i14 = load i32, ptr %i, align 4
494  call void @free(ptr %i)
495  %i16 = load i32, ptr %i, align 4
496  ret i32 %i16
497}
498
499
500define i32 @malloc_in_loop(i32 %arg) {
501; CHECK-LABEL: define {{[^@]+}}@malloc_in_loop
502; CHECK-SAME: (i32 [[ARG:%.*]]) {
503; CHECK-NEXT:  bb:
504; CHECK-NEXT:    [[I:%.*]] = alloca i32, align 4
505; CHECK-NEXT:    [[I1:%.*]] = alloca ptr, align 8
506; CHECK-NEXT:    [[I11:%.*]] = alloca i8, i32 0, align 8
507; CHECK-NEXT:    store i32 [[ARG]], ptr [[I]], align 4
508; CHECK-NEXT:    br label [[BB2:%.*]]
509; CHECK:       bb2:
510; CHECK-NEXT:    [[I3:%.*]] = load i32, ptr [[I]], align 4
511; CHECK-NEXT:    [[I4:%.*]] = add nsw i32 [[I3]], -1
512; CHECK-NEXT:    store i32 [[I4]], ptr [[I]], align 4
513; CHECK-NEXT:    [[I5:%.*]] = icmp sgt i32 [[I4]], 0
514; CHECK-NEXT:    br i1 [[I5]], label [[BB6:%.*]], label [[BB9:%.*]]
515; CHECK:       bb6:
516; CHECK-NEXT:    [[I7_H2S:%.*]] = alloca i8, i64 4, align 1
517; CHECK-NEXT:    br label [[BB2]]
518; CHECK:       bb9:
519; CHECK-NEXT:    ret i32 5
520;
521bb:
522  %i = alloca i32, align 4
523  %i1 = alloca ptr, align 8
524  store i32 %arg, ptr %i, align 4
525  br label %bb2
526
527bb2:
528  %i3 = load i32, ptr %i, align 4
529  %i4 = add nsw i32 %i3, -1
530  store i32 %i4, ptr %i, align 4
531  %i5 = icmp sgt i32 %i4, 0
532  br i1 %i5, label %bb6, label %bb9
533
534bb6:
535  %i7 = call noalias ptr @malloc(i64 4)
536  store i32 1, ptr %i7, align 8
537  br label %bb2
538
539bb9:
540  ret i32 5
541}
542
543; Malloc/Calloc too large
544define i32 @test13() {
545; CHECK-LABEL: define {{[^@]+}}@test13() {
546; CHECK-NEXT:  bb:
547; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 256)
548; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])
549; CHECK-NEXT:    store i32 10, ptr [[I]], align 4
550; CHECK-NEXT:    [[I2:%.*]] = load i32, ptr [[I]], align 4
551; CHECK-NEXT:    tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]])
552; CHECK-NEXT:    ret i32 [[I2]]
553;
554bb:
555  %i = tail call noalias ptr @malloc(i64 256)
556  tail call void @no_sync_func(ptr %i)
557  store i32 10, ptr %i, align 4
558  %i2 = load i32, ptr %i, align 4
559  tail call void @free(ptr %i)
560  ret i32 %i2
561}
562
563define i32 @test_sle() {
564; CHECK-LABEL: define {{[^@]+}}@test_sle() {
565; CHECK-NEXT:  bb:
566; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef -1)
567; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])
568; CHECK-NEXT:    store i32 10, ptr [[I]], align 4
569; CHECK-NEXT:    [[I2:%.*]] = load i32, ptr [[I]], align 4
570; CHECK-NEXT:    tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]])
571; CHECK-NEXT:    ret i32 [[I2]]
572;
573bb:
574  %i = tail call noalias ptr @malloc(i64 -1)
575  tail call void @no_sync_func(ptr %i)
576  store i32 10, ptr %i, align 4
577  %i2 = load i32, ptr %i, align 4
578  tail call void @free(ptr %i)
579  ret i32 %i2
580}
581
582define i32 @test_overflow() {
583; CHECK-LABEL: define {{[^@]+}}@test_overflow() {
584; CHECK-NEXT:  bb:
585; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @calloc(i64 noundef 65537, i64 noundef 65537)
586; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])
587; CHECK-NEXT:    store i32 10, ptr [[I]], align 4
588; CHECK-NEXT:    [[I2:%.*]] = load i32, ptr [[I]], align 4
589; CHECK-NEXT:    tail call void @free(ptr noalias nonnull align 4 captures(none) dereferenceable(4) [[I]])
590; CHECK-NEXT:    ret i32 [[I2]]
591;
592bb:
593  %i = tail call noalias ptr @calloc(i64 65537, i64 65537)
594  tail call void @no_sync_func(ptr %i)
595  store i32 10, ptr %i, align 4
596  %i2 = load i32, ptr %i, align 4
597  tail call void @free(ptr %i)
598  ret i32 %i2
599}
600
601define void @test14() {
602; CHECK-LABEL: define {{[^@]+}}@test14() {
603; CHECK-NEXT:  bb:
604; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @calloc(i64 noundef 64, i64 noundef 4)
605; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])
606; CHECK-NEXT:    tail call void @free(ptr noalias captures(none) [[I]])
607; CHECK-NEXT:    ret void
608;
609bb:
610  %i = tail call noalias ptr @calloc(i64 64, i64 4)
611  tail call void @no_sync_func(ptr %i)
612  tail call void @free(ptr %i)
613  ret void
614}
615
616define void @test15(i64 %S) {
617; CHECK-LABEL: define {{[^@]+}}@test15
618; CHECK-SAME: (i64 [[S:%.*]]) {
619; CHECK-NEXT:  bb:
620; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @malloc(i64 [[S]])
621; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree captures(none) [[I]])
622; CHECK-NEXT:    tail call void @free(ptr noalias captures(none) [[I]])
623; CHECK-NEXT:    ret void
624;
625bb:
626  %i = tail call noalias ptr @malloc(i64 %S)
627  tail call void @no_sync_func(ptr %i)
628  tail call void @free(ptr %i)
629  ret void
630}
631
632define void @test16a(i8 %v, ptr %P) {
633; CHECK-LABEL: define {{[^@]+}}@test16a
634; CHECK-SAME: (i8 [[V:%.*]], ptr nofree readnone captures(none) [[P:%.*]]) {
635; CHECK-NEXT:  bb:
636; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
637; CHECK-NEXT:    store i8 [[V]], ptr [[I_H2S]], align 1
638; CHECK-NEXT:    tail call void @no_sync_func(ptr noalias nofree noundef nonnull captures(none) dereferenceable(1) [[I_H2S]])
639; CHECK-NEXT:    ret void
640;
641bb:
642  %i = tail call noalias ptr @malloc(i64 4)
643  store i8 %v, ptr %i, align 1
644  tail call void @no_sync_func(ptr %i)
645  tail call void @free(ptr nonnull dereferenceable(1) %i)
646  ret void
647}
648
649define void @test16b(i8 %v, ptr %P) {
650; CHECK-LABEL: define {{[^@]+}}@test16b
651; CHECK-SAME: (i8 [[V:%.*]], ptr nofree writeonly captures(none) [[P:%.*]]) {
652; CHECK-NEXT:  bb:
653; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
654; CHECK-NEXT:    store ptr [[I]], ptr [[P]], align 8
655; CHECK-NEXT:    tail call void @no_sync_func(ptr nofree captures(none) [[I]])
656; CHECK-NEXT:    tail call void @free(ptr captures(none) [[I]])
657; CHECK-NEXT:    ret void
658;
659bb:
660  %i = tail call noalias ptr @malloc(i64 4)
661  store ptr %i, ptr %P, align 8
662  tail call void @no_sync_func(ptr %i)
663  tail call void @free(ptr %i)
664  ret void
665}
666
667define void @test16c(i8 %v, ptr %P) {
668; CHECK-LABEL: define {{[^@]+}}@test16c
669; CHECK-SAME: (i8 [[V:%.*]], ptr nofree writeonly captures(none) [[P:%.*]]) {
670; CHECK-NEXT:  bb:
671; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
672; CHECK-NEXT:    store ptr [[I_H2S]], ptr [[P]], align 8
673; CHECK-NEXT:    tail call void @no_sync_func(ptr nofree captures(none) [[I_H2S]]) #[[ATTR11]]
674; CHECK-NEXT:    ret void
675;
676bb:
677  %i = tail call noalias ptr @malloc(i64 4)
678  store ptr %i, ptr %P, align 8
679  tail call void @no_sync_func(ptr %i) nounwind
680  tail call void @free(ptr %i)
681  ret void
682}
683
684define void @test16d(i8 %v, ptr %P) {
685; CHECK-LABEL: define {{[^@]+}}@test16d
686; CHECK-SAME: (i8 [[V:%.*]], ptr nofree writeonly captures(none) [[P:%.*]]) {
687; CHECK-NEXT:  bb:
688; CHECK-NEXT:    [[I:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
689; CHECK-NEXT:    store ptr [[I]], ptr [[P]], align 8
690; CHECK-NEXT:    ret void
691;
692bb:
693  %i = tail call noalias ptr @malloc(i64 4)
694  store ptr %i, ptr %P, align 8
695  ret void
696}
697
698@G = internal global ptr undef, align 4
699define void @test16e(i8 %v) norecurse {
700; CHECK: Function Attrs: norecurse
701; CHECK-LABEL: define {{[^@]+}}@test16e
702; CHECK-SAME: (i8 [[V:%.*]]) #[[ATTR9:[0-9]+]] {
703; CHECK-NEXT:  bb:
704; CHECK-NEXT:    [[I_H2S:%.*]] = alloca i8, i64 4, align 1
705; CHECK-NEXT:    store ptr [[I_H2S]], ptr @G, align 8
706; CHECK-NEXT:    call void @usei8p(ptr nofree captures(none) [[I_H2S]]) #[[ATTR12:[0-9]+]]
707; CHECK-NEXT:    ret void
708;
709bb:
710  %i = tail call noalias ptr @malloc(i64 4)
711  store ptr %i, ptr @G, align 8
712  %i1 = load ptr, ptr @G, align 8
713  call void @usei8p(ptr nocapture nofree %i1) nocallback nosync nounwind willreturn
714  call void @free(ptr %i)
715  ret void
716}
717
718;.
719; CHECK: attributes #[[ATTR0:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) }
720; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn }
721; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nosync willreturn }
722; CHECK: attributes #[[ATTR3:[0-9]+]] = { nofree nounwind }
723; CHECK: attributes #[[ATTR4]] = { noreturn }
724; CHECK: attributes #[[ATTR5:[0-9]+]] = { allockind("free") }
725; CHECK: attributes #[[ATTR6:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
726; CHECK: attributes #[[ATTR7:[0-9]+]] = { allockind("alloc,uninitialized,aligned") allocsize(1) }
727; CHECK: attributes #[[ATTR8:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) }
728; CHECK: attributes #[[ATTR9]] = { norecurse }
729; CHECK: attributes #[[ATTR10:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
730; CHECK: attributes #[[ATTR11]] = { nounwind }
731; CHECK: attributes #[[ATTR12]] = { nocallback nosync nounwind willreturn }
732;.
733;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
734; CGSCC: {{.*}}
735; TUNIT: {{.*}}
736