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