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=9 -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=9 -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 triple = "amdgcn-amd-amdhsa"
8
9declare noalias i8* @malloc(i64)
10
11declare void @nocapture_func_frees_pointer(i8* nocapture)
12
13declare void @func_throws(...)
14
15declare void @sync_func(i8* %p)
16
17declare void @sync_will_return(i8* %p) willreturn nounwind
18
19declare void @no_sync_func(i8* nocapture %p) nofree nosync willreturn
20
21declare void @nofree_func(i8* nocapture %p) nofree  nosync willreturn
22
23declare void @foo(i32* %p)
24
25declare void @foo_nounw(i32* %p) nounwind nofree
26
27declare i32 @no_return_call() noreturn
28
29declare void @free(i8* nocapture)
30
31declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
32
33define void @nofree_arg_only(i8* %p1, i8* %p2) {
34; CHECK-LABEL: define {{[^@]+}}@nofree_arg_only
35; CHECK-SAME: (i8* nocapture nofree [[P1:%.*]], i8* nocapture [[P2:%.*]]) {
36; CHECK-NEXT:    tail call void @free(i8* nocapture [[P2]])
37; CHECK-NEXT:    tail call void @nofree_func(i8* nocapture nofree [[P1]])
38; CHECK-NEXT:    ret void
39;
40  tail call void @free(i8* %p2)
41  tail call void @nofree_func(i8* %p1)
42  ret void
43}
44
45; TEST 1 - negative, pointer freed in another function.
46
47define void @test1() {
48; CHECK-LABEL: define {{[^@]+}}@test1() {
49; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
50; CHECK-NEXT:    tail call void @nocapture_func_frees_pointer(i8* noalias nocapture [[TMP1]])
51; CHECK-NEXT:    tail call void (...) @func_throws()
52; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
53; CHECK-NEXT:    ret void
54;
55  %1 = tail call noalias i8* @malloc(i64 4)
56  tail call void @nocapture_func_frees_pointer(i8* %1)
57  tail call void (...) @func_throws()
58  tail call void @free(i8* %1)
59  ret void
60}
61
62; TEST 2 - negative, call to a sync function.
63
64define void @test2() {
65; CHECK-LABEL: define {{[^@]+}}@test2() {
66; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
67; CHECK-NEXT:    tail call void @sync_func(i8* [[TMP1]])
68; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
69; CHECK-NEXT:    ret void
70;
71  %1 = tail call noalias i8* @malloc(i64 4)
72  tail call void @sync_func(i8* %1)
73  tail call void @free(i8* %1)
74  ret void
75}
76
77; TEST 3 - 1 malloc, 1 free
78
79define void @test3() {
80; CHECK-LABEL: define {{[^@]+}}@test3() {
81; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
82; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
83; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
84; CHECK-NEXT:    ret void
85;
86  %1 = tail call noalias i8* @malloc(i64 4)
87  tail call void @no_sync_func(i8* %1)
88  tail call void @free(i8* %1)
89  ret void
90}
91
92define void @test3a(i8* %p) {
93; IS________OPM-LABEL: define {{[^@]+}}@test3a
94; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) {
95; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
96; IS________OPM-NEXT:    tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]])
97; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
98; IS________OPM-NEXT:    ret void
99;
100; IS________NPM-LABEL: define {{[^@]+}}@test3a
101; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) {
102; IS________NPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
103; IS________NPM-NEXT:    tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]])
104; IS________NPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
105; IS________NPM-NEXT:    ret void
106;
107  %1 = tail call noalias i8* @malloc(i64 4)
108  tail call void @nofree_arg_only(i8* %1, i8* %p)
109  tail call void @free(i8* %1)
110  ret void
111}
112
113declare noalias i8* @aligned_alloc(i64, i64)
114
115define void @test3b(i8* %p) {
116; IS________OPM-LABEL: define {{[^@]+}}@test3b
117; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) {
118; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 32, i64 noundef 128)
119; IS________OPM-NEXT:    tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]])
120; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
121; IS________OPM-NEXT:    ret void
122;
123; IS________NPM-LABEL: define {{[^@]+}}@test3b
124; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) {
125; IS________NPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 32, i64 noundef 128)
126; IS________NPM-NEXT:    tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]])
127; IS________NPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
128; IS________NPM-NEXT:    ret void
129;
130  %1 = tail call noalias i8* @aligned_alloc(i64 32, i64 128)
131  tail call void @nofree_arg_only(i8* %1, i8* %p)
132  tail call void @free(i8* %1)
133  ret void
134}
135
136; leave alone non-constant alignments.
137define void @test3c(i64 %alignment) {
138; CHECK-LABEL: define {{[^@]+}}@test3c
139; CHECK-SAME: (i64 [[ALIGNMENT:%.*]]) {
140; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 [[ALIGNMENT]], i64 noundef 128)
141; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
142; CHECK-NEXT:    ret void
143;
144  %1 = tail call noalias i8* @aligned_alloc(i64 %alignment, i64 128)
145  tail call void @free(i8* %1)
146  ret void
147}
148
149declare noalias i8* @calloc(i64, i64)
150
151define void @test0() {
152; CHECK-LABEL: define {{[^@]+}}@test0() {
153; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 2, i64 noundef 4)
154; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
155; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
156; CHECK-NEXT:    ret void
157;
158  %1 = tail call noalias i8* @calloc(i64 2, i64 4)
159  tail call void @no_sync_func(i8* %1)
160  tail call void @free(i8* %1)
161  ret void
162}
163
164; TEST 4
165define void @test4() {
166; CHECK-LABEL: define {{[^@]+}}@test4() {
167; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
168; CHECK-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[TMP1]])
169; CHECK-NEXT:    ret void
170;
171  %1 = tail call noalias i8* @malloc(i64 4)
172  tail call void @nofree_func(i8* %1)
173  ret void
174}
175
176; TEST 5 - not all exit paths have a call to free, but all uses of malloc
177; are in nofree functions and are not captured
178
179define void @test5(i32, i8* %p) {
180; IS________OPM-LABEL: define {{[^@]+}}@test5
181; IS________OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) {
182; IS________OPM-NEXT:    [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
183; IS________OPM-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0
184; IS________OPM-NEXT:    br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
185; IS________OPM:       4:
186; IS________OPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]])
187; IS________OPM-NEXT:    br label [[TMP6:%.*]]
188; IS________OPM:       5:
189; IS________OPM-NEXT:    tail call void @nofree_arg_only(i8* nocapture nofree [[TMP2]], i8* nocapture [[P]])
190; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
191; IS________OPM-NEXT:    br label [[TMP6]]
192; IS________OPM:       6:
193; IS________OPM-NEXT:    ret void
194;
195; IS________NPM-LABEL: define {{[^@]+}}@test5
196; IS________NPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) {
197; IS________NPM-NEXT:    [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
198; IS________NPM-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0
199; IS________NPM-NEXT:    br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
200; IS________NPM:       4:
201; IS________NPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]])
202; IS________NPM-NEXT:    br label [[TMP6:%.*]]
203; IS________NPM:       5:
204; IS________NPM-NEXT:    tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP2]], i8* nocapture [[P]])
205; IS________NPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
206; IS________NPM-NEXT:    br label [[TMP6]]
207; IS________NPM:       6:
208; IS________NPM-NEXT:    ret void
209;
210  %2 = tail call noalias i8* @malloc(i64 4)
211  %3 = icmp eq i32 %0, 0
212  br i1 %3, label %5, label %4
213
2144:                                                ; preds = %1
215  tail call void @nofree_func(i8* %2)
216  br label %6
217
2185:                                                ; preds = %1
219  tail call void @nofree_arg_only(i8* %2, i8* %p)
220  tail call void @free(i8* %2)
221  br label %6
222
2236:                                                ; preds = %5, %4
224  ret void
225}
226
227; TEST 6 - all exit paths have a call to free
228
229define void @test6(i32) {
230; CHECK-LABEL: define {{[^@]+}}@test6
231; CHECK-SAME: (i32 [[TMP0:%.*]]) {
232; CHECK-NEXT:    [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
233; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0
234; CHECK-NEXT:    br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
235; CHECK:       4:
236; CHECK-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]])
237; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
238; CHECK-NEXT:    br label [[TMP6:%.*]]
239; CHECK:       5:
240; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
241; CHECK-NEXT:    br label [[TMP6]]
242; CHECK:       6:
243; CHECK-NEXT:    ret void
244;
245  %2 = tail call noalias i8* @malloc(i64 4)
246  %3 = icmp eq i32 %0, 0
247  br i1 %3, label %5, label %4
248
2494:                                                ; preds = %1
250  tail call void @nofree_func(i8* %2)
251  tail call void @free(i8* %2)
252  br label %6
253
2545:                                                ; preds = %1
255  tail call void @free(i8* %2)
256  br label %6
257
2586:                                                ; preds = %5, %4
259  ret void
260}
261
262; TEST 7 - free is dead.
263
264define void @test7() {
265; CHECK: Function Attrs: noreturn
266; CHECK-LABEL: define {{[^@]+}}@test7
267; CHECK-SAME: () #[[ATTR3:[0-9]+]] {
268; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
269; CHECK-NEXT:    [[TMP2:%.*]] = tail call i32 @no_return_call() #[[ATTR3]]
270; CHECK-NEXT:    unreachable
271;
272  %1 = tail call noalias i8* @malloc(i64 4)
273  tail call i32 @no_return_call()
274  tail call void @free(i8* %1)
275  ret void
276}
277
278; TEST 8 - Negative: bitcast pointer used in capture function
279
280define void @test8() {
281; CHECK-LABEL: define {{[^@]+}}@test8() {
282; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
283; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
284; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
285; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
286; CHECK-NEXT:    tail call void @foo(i32* noundef align 4 [[TMP2]])
287; CHECK-NEXT:    tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
288; CHECK-NEXT:    ret void
289;
290  %1 = tail call noalias i8* @malloc(i64 4)
291  tail call void @no_sync_func(i8* %1)
292  %2 = bitcast i8* %1 to i32*
293  store i32 10, i32* %2
294  %3 = load i32, i32* %2
295  tail call void @foo(i32* %2)
296  tail call void @free(i8* %1)
297  ret void
298}
299
300; TEST 9 - FIXME: malloc should be converted.
301define void @test9() {
302; CHECK-LABEL: define {{[^@]+}}@test9() {
303; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
304; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
305; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
306; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
307; CHECK-NEXT:    tail call void @foo_nounw(i32* nofree noundef align 4 [[TMP2]]) #[[ATTR5:[0-9]+]]
308; CHECK-NEXT:    tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
309; CHECK-NEXT:    ret void
310;
311  %1 = tail call noalias i8* @malloc(i64 4)
312  tail call void @no_sync_func(i8* %1)
313  %2 = bitcast i8* %1 to i32*
314  store i32 10, i32* %2
315  %3 = load i32, i32* %2
316  tail call void @foo_nounw(i32* %2)
317  tail call void @free(i8* %1)
318  ret void
319}
320
321; TEST 10 - 1 malloc, 1 free
322
323define i32 @test10() {
324; CHECK-LABEL: define {{[^@]+}}@test10() {
325; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
326; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
327; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
328; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
329; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
330; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
331; CHECK-NEXT:    ret i32 [[TMP3]]
332;
333  %1 = tail call noalias i8* @malloc(i64 4)
334  tail call void @no_sync_func(i8* %1)
335  %2 = bitcast i8* %1 to i32*
336  store i32 10, i32* %2
337  %3 = load i32, i32* %2
338  tail call void @free(i8* %1)
339  ret i32 %3
340}
341
342define i32 @test_lifetime() {
343; CHECK-LABEL: define {{[^@]+}}@test_lifetime() {
344; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
345; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
346; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[TMP1]])
347; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
348; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
349; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
350; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
351; CHECK-NEXT:    ret i32 [[TMP3]]
352;
353  %1 = tail call noalias i8* @malloc(i64 4)
354  tail call void @no_sync_func(i8* %1)
355  call void @llvm.lifetime.start.p0i8(i64 4, i8* %1)
356  %2 = bitcast i8* %1 to i32*
357  store i32 10, i32* %2
358  %3 = load i32, i32* %2
359  tail call void @free(i8* %1)
360  ret i32 %3
361}
362
363; TEST 11
364
365define void @test11() {
366; CHECK-LABEL: define {{[^@]+}}@test11() {
367; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
368; CHECK-NEXT:    tail call void @sync_will_return(i8* [[TMP1]]) #[[ATTR5]]
369; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
370; CHECK-NEXT:    ret void
371;
372  %1 = tail call noalias i8* @malloc(i64 4)
373  tail call void @sync_will_return(i8* %1)
374  tail call void @free(i8* %1)
375  ret void
376}
377
378; TEST 12
379define i32 @irreducible_cfg(i32 %0) {
380; IS________OPM-LABEL: define {{[^@]+}}@irreducible_cfg
381; IS________OPM-SAME: (i32 [[TMP0:%.*]]) {
382; IS________OPM-NEXT:    [[TMP2:%.*]] = call noalias i8* @malloc(i64 noundef 4)
383; IS________OPM-NEXT:    [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32*
384; IS________OPM-NEXT:    store i32 10, i32* [[TMP3]], align 4
385; IS________OPM-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1
386; IS________OPM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]]
387; IS________OPM:       5:
388; IS________OPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5
389; IS________OPM-NEXT:    br label [[TMP13:%.*]]
390; IS________OPM:       7:
391; IS________OPM-NEXT:    br label [[TMP8:%.*]]
392; IS________OPM:       8:
393; IS________OPM-NEXT:    [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ]
394; IS________OPM-NEXT:    [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4
395; IS________OPM-NEXT:    [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1
396; IS________OPM-NEXT:    store i32 [[TMP10]], i32* [[TMP3]], align 4
397; IS________OPM-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0
398; IS________OPM-NEXT:    br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]]
399; IS________OPM:       12:
400; IS________OPM-NEXT:    br label [[TMP13]]
401; IS________OPM:       13:
402; IS________OPM-NEXT:    [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ]
403; IS________OPM-NEXT:    [[TMP14]] = add nsw i32 [[DOT1]], 1
404; IS________OPM-NEXT:    br label [[TMP8]]
405; IS________OPM:       15:
406; IS________OPM-NEXT:    [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4
407; IS________OPM-NEXT:    [[TMP17:%.*]] = bitcast i32* [[TMP3]] to i8*
408; IS________OPM-NEXT:    call void @free(i8* nocapture noundef [[TMP17]])
409; IS________OPM-NEXT:    [[TMP18:%.*]] = load i32, i32* [[TMP3]], align 4
410; IS________OPM-NEXT:    ret i32 [[TMP18]]
411;
412; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg
413; IS________NPM-SAME: (i32 [[TMP0:%.*]]) {
414; IS________NPM-NEXT:    [[TMP2:%.*]] = call noalias i8* @malloc(i64 noundef 4)
415; IS________NPM-NEXT:    [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32*
416; IS________NPM-NEXT:    store i32 10, i32* [[TMP3]], align 4
417; IS________NPM-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1
418; IS________NPM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]]
419; IS________NPM:       5:
420; IS________NPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5
421; IS________NPM-NEXT:    br label [[TMP13:%.*]]
422; IS________NPM:       7:
423; IS________NPM-NEXT:    br label [[TMP8:%.*]]
424; IS________NPM:       8:
425; IS________NPM-NEXT:    [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ]
426; IS________NPM-NEXT:    [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4
427; IS________NPM-NEXT:    [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1
428; IS________NPM-NEXT:    store i32 [[TMP10]], i32* [[TMP3]], align 4
429; IS________NPM-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0
430; IS________NPM-NEXT:    br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]]
431; IS________NPM:       12:
432; IS________NPM-NEXT:    br label [[TMP13]]
433; IS________NPM:       13:
434; IS________NPM-NEXT:    [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ]
435; IS________NPM-NEXT:    [[TMP14]] = add nsw i32 [[DOT1]], 1
436; IS________NPM-NEXT:    br label [[TMP8]]
437; IS________NPM:       15:
438; IS________NPM-NEXT:    [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4
439; IS________NPM-NEXT:    call void @free(i8* nocapture noundef [[TMP2]])
440; IS________NPM-NEXT:    [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4
441; IS________NPM-NEXT:    ret i32 [[TMP17]]
442;
443  %2 = call noalias i8* @malloc(i64 4)
444  %3 = bitcast i8* %2 to i32*
445  store i32 10, i32* %3, align 4
446  %4 = icmp eq i32 %0, 1
447  br i1 %4, label %5, label %7
448
4495:                                                ; preds = %1
450  %6 = add nsw i32 %0, 5
451  br label %13
452
4537:                                                ; preds = %1
454  br label %8
455
4568:                                                ; preds = %13, %7
457  %.0 = phi i32 [ %14, %13 ], [ 1, %7 ]
458  %9 = load i32, i32* %3, align 4
459  %10 = add nsw i32 %9, -1
460  store i32 %10, i32* %3, align 4
461  %11 = icmp ne i32 %9, 0
462  br i1 %11, label %12, label %15
463
46412:                                               ; preds = %8
465  br label %13
466
46713:                                               ; preds = %12, %5
468  %.1 = phi i32 [ %6, %5 ], [ %.0, %12 ]
469  %14 = add nsw i32 %.1, 1
470  br label %8
471
47215:                                               ; preds = %8
473  %16 = load i32, i32* %3, align 4
474  %17 = bitcast i32* %3 to i8*
475  call void @free(i8* %17)
476  %18 = load i32, i32* %3, align 4
477  ret i32 %18
478}
479
480
481define i32 @malloc_in_loop(i32 %0) {
482; CHECK-LABEL: define {{[^@]+}}@malloc_in_loop
483; CHECK-SAME: (i32 [[TMP0:%.*]]) {
484; CHECK-NEXT:    [[TMP2:%.*]] = alloca i32, align 4
485; CHECK-NEXT:    [[TMP3:%.*]] = alloca i32*, align 8
486; CHECK-NEXT:    store i32 [[TMP0]], i32* [[TMP2]], align 4
487; CHECK-NEXT:    br label [[TMP4:%.*]]
488; CHECK:       4:
489; CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP2]], align 4
490; CHECK-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP5]], -1
491; CHECK-NEXT:    store i32 [[TMP6]], i32* [[TMP2]], align 4
492; CHECK-NEXT:    [[TMP7:%.*]] = icmp sgt i32 [[TMP6]], 0
493; CHECK-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP11:%.*]]
494; CHECK:       8:
495; CHECK-NEXT:    [[TMP9:%.*]] = call noalias i8* @malloc(i64 noundef 4)
496; CHECK-NEXT:    [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32*
497; CHECK-NEXT:    br label [[TMP4]]
498; CHECK:       11:
499; CHECK-NEXT:    ret i32 5
500;
501  %2 = alloca i32, align 4
502  %3 = alloca i32*, align 8
503  store i32 %0, i32* %2, align 4
504  br label %4
505
5064:                                                ; preds = %8, %1
507  %5 = load i32, i32* %2, align 4
508  %6 = add nsw i32 %5, -1
509  store i32 %6, i32* %2, align 4
510  %7 = icmp sgt i32 %6, 0
511  br i1 %7, label %8, label %11
512
5138:                                                ; preds = %4
514  %9 = call noalias i8* @malloc(i64 4)
515  %10 = bitcast i8* %9 to i32*
516  store i32 1, i32* %10, align 8
517  br label %4
518
51911:                                               ; preds = %4
520  ret i32 5
521}
522
523; Malloc/Calloc too large
524define i32 @test13() {
525; CHECK-LABEL: define {{[^@]+}}@test13() {
526; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 256)
527; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
528; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
529; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
530; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
531; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
532; CHECK-NEXT:    ret i32 [[TMP3]]
533;
534  %1 = tail call noalias i8* @malloc(i64 256)
535  tail call void @no_sync_func(i8* %1)
536  %2 = bitcast i8* %1 to i32*
537  store i32 10, i32* %2
538  %3 = load i32, i32* %2
539  tail call void @free(i8* %1)
540  ret i32 %3
541}
542
543define i32 @test_sle() {
544; CHECK-LABEL: define {{[^@]+}}@test_sle() {
545; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef -1)
546; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
547; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
548; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
549; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
550; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
551; CHECK-NEXT:    ret i32 [[TMP3]]
552;
553  %1 = tail call noalias i8* @malloc(i64 -1)
554  tail call void @no_sync_func(i8* %1)
555  %2 = bitcast i8* %1 to i32*
556  store i32 10, i32* %2
557  %3 = load i32, i32* %2
558  tail call void @free(i8* %1)
559  ret i32 %3
560}
561
562define i32 @test_overflow() {
563; CHECK-LABEL: define {{[^@]+}}@test_overflow() {
564; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 65537, i64 noundef 65537)
565; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
566; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
567; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
568; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
569; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
570; CHECK-NEXT:    ret i32 [[TMP3]]
571;
572  %1 = tail call noalias i8* @calloc(i64 65537, i64 65537)
573  tail call void @no_sync_func(i8* %1)
574  %2 = bitcast i8* %1 to i32*
575  store i32 10, i32* %2
576  %3 = load i32, i32* %2
577  tail call void @free(i8* %1)
578  ret i32 %3
579}
580
581define void @test14() {
582; CHECK-LABEL: define {{[^@]+}}@test14() {
583; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 64, i64 noundef 4)
584; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
585; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
586; CHECK-NEXT:    ret void
587;
588  %1 = tail call noalias i8* @calloc(i64 64, i64 4)
589  tail call void @no_sync_func(i8* %1)
590  tail call void @free(i8* %1)
591  ret void
592}
593
594define void @test15(i64 %S) {
595; CHECK-LABEL: define {{[^@]+}}@test15
596; CHECK-SAME: (i64 [[S:%.*]]) {
597; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 [[S]])
598; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
599; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
600; CHECK-NEXT:    ret void
601;
602  %1 = tail call noalias i8* @malloc(i64 %S)
603  tail call void @no_sync_func(i8* %1)
604  tail call void @free(i8* %1)
605  ret void
606}
607
608define void @test16a(i8 %v, i8** %P) {
609; CHECK-LABEL: define {{[^@]+}}@test16a
610; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) {
611; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
612; CHECK-NEXT:    store i8 [[V]], i8* [[TMP1]], align 1
613; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[TMP1]])
614; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull dereferenceable(1) [[TMP1]])
615; CHECK-NEXT:    ret void
616;
617  %1 = tail call noalias i8* @malloc(i64 4)
618  store i8 %v, i8* %1
619  tail call void @no_sync_func(i8* %1)
620  tail call void @free(i8* nonnull dereferenceable(1) %1)
621  ret void
622}
623
624define void @test16b(i8 %v, i8** %P) {
625; CHECK-LABEL: define {{[^@]+}}@test16b
626; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
627; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
628; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
629; CHECK-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
630; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
631; CHECK-NEXT:    ret void
632;
633  %1 = tail call noalias i8* @malloc(i64 4)
634  store i8* %1, i8** %P
635  tail call void @no_sync_func(i8* %1)
636  tail call void @free(i8* %1)
637  ret void
638}
639
640define void @test16c(i8 %v, i8** %P) {
641; CHECK-LABEL: define {{[^@]+}}@test16c
642; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
643; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
644; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
645; CHECK-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) #[[ATTR5]]
646; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
647; CHECK-NEXT:    ret void
648;
649  %1 = tail call noalias i8* @malloc(i64 4)
650  store i8* %1, i8** %P
651  tail call void @no_sync_func(i8* %1) nounwind
652  tail call void @free(i8* %1)
653  ret void
654}
655
656define void @test16d(i8 %v, i8** %P) {
657; CHECK-LABEL: define {{[^@]+}}@test16d
658; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
659; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
660; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
661; CHECK-NEXT:    ret void
662;
663  %1 = tail call noalias i8* @malloc(i64 4)
664  store i8* %1, i8** %P
665  ret void
666}
667;.
668; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn }
669; CHECK: attributes #[[ATTR1:[0-9]+]] = { nofree nosync willreturn }
670; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind }
671; CHECK: attributes #[[ATTR3]] = { noreturn }
672; CHECK: attributes #[[ATTR4:[0-9]+]] = { argmemonly nofree nosync nounwind willreturn }
673; CHECK: attributes #[[ATTR5]] = { nounwind }
674;.
675