1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
6
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:    br label [[TMP4]]
502; CHECK:       11:
503; CHECK-NEXT:    ret i32 5
504;
505  %2 = alloca i32, align 4
506  %3 = alloca i32*, align 8
507  store i32 %0, i32* %2, align 4
508  br label %4
509
5104:                                                ; preds = %8, %1
511  %5 = load i32, i32* %2, align 4
512  %6 = add nsw i32 %5, -1
513  store i32 %6, i32* %2, align 4
514  %7 = icmp sgt i32 %6, 0
515  br i1 %7, label %8, label %11
516
5178:                                                ; preds = %4
518  %9 = call noalias i8* @malloc(i64 4)
519  %10 = bitcast i8* %9 to i32*
520  store i32 1, i32* %10, align 8
521  br label %4
522
52311:                                               ; preds = %4
524  ret i32 5
525}
526
527; Malloc/Calloc too large
528define i32 @test13() {
529; CHECK-LABEL: define {{[^@]+}}@test13() {
530; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 256)
531; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
532; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
533; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
534; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
535; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
536; CHECK-NEXT:    ret i32 [[TMP3]]
537;
538  %1 = tail call noalias i8* @malloc(i64 256)
539  tail call void @no_sync_func(i8* %1)
540  %2 = bitcast i8* %1 to i32*
541  store i32 10, i32* %2
542  %3 = load i32, i32* %2
543  tail call void @free(i8* %1)
544  ret i32 %3
545}
546
547define i32 @test_sle() {
548; CHECK-LABEL: define {{[^@]+}}@test_sle() {
549; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef -1)
550; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
551; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
552; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
553; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
554; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
555; CHECK-NEXT:    ret i32 [[TMP3]]
556;
557  %1 = tail call noalias i8* @malloc(i64 -1)
558  tail call void @no_sync_func(i8* %1)
559  %2 = bitcast i8* %1 to i32*
560  store i32 10, i32* %2
561  %3 = load i32, i32* %2
562  tail call void @free(i8* %1)
563  ret i32 %3
564}
565
566define i32 @test_overflow() {
567; CHECK-LABEL: define {{[^@]+}}@test_overflow() {
568; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 65537, i64 noundef 65537)
569; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
570; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
571; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
572; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
573; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
574; CHECK-NEXT:    ret i32 [[TMP3]]
575;
576  %1 = tail call noalias i8* @calloc(i64 65537, i64 65537)
577  tail call void @no_sync_func(i8* %1)
578  %2 = bitcast i8* %1 to i32*
579  store i32 10, i32* %2
580  %3 = load i32, i32* %2
581  tail call void @free(i8* %1)
582  ret i32 %3
583}
584
585define void @test14() {
586; CHECK-LABEL: define {{[^@]+}}@test14() {
587; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 64, i64 noundef 4)
588; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
589; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
590; CHECK-NEXT:    ret void
591;
592  %1 = tail call noalias i8* @calloc(i64 64, i64 4)
593  tail call void @no_sync_func(i8* %1)
594  tail call void @free(i8* %1)
595  ret void
596}
597
598define void @test15(i64 %S) {
599; CHECK-LABEL: define {{[^@]+}}@test15
600; CHECK-SAME: (i64 [[S:%.*]]) {
601; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 [[S]])
602; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
603; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
604; CHECK-NEXT:    ret void
605;
606  %1 = tail call noalias i8* @malloc(i64 %S)
607  tail call void @no_sync_func(i8* %1)
608  tail call void @free(i8* %1)
609  ret void
610}
611
612define void @test16a(i8 %v, i8** %P) {
613; CHECK-LABEL: define {{[^@]+}}@test16a
614; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) {
615; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
616; CHECK-NEXT:    store i8 [[V]], i8* [[TMP1]], align 1
617; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[TMP1]])
618; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull dereferenceable(1) [[TMP1]])
619; CHECK-NEXT:    ret void
620;
621  %1 = tail call noalias i8* @malloc(i64 4)
622  store i8 %v, i8* %1
623  tail call void @no_sync_func(i8* %1)
624  tail call void @free(i8* nonnull dereferenceable(1) %1)
625  ret void
626}
627
628define void @test16b(i8 %v, i8** %P) {
629; CHECK-LABEL: define {{[^@]+}}@test16b
630; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
631; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
632; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
633; CHECK-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
634; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
635; CHECK-NEXT:    ret void
636;
637  %1 = tail call noalias i8* @malloc(i64 4)
638  store i8* %1, i8** %P
639  tail call void @no_sync_func(i8* %1)
640  tail call void @free(i8* %1)
641  ret void
642}
643
644define void @test16c(i8 %v, i8** %P) {
645; CHECK-LABEL: define {{[^@]+}}@test16c
646; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
647; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
648; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
649; CHECK-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) #[[ATTR5]]
650; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
651; CHECK-NEXT:    ret void
652;
653  %1 = tail call noalias i8* @malloc(i64 4)
654  store i8* %1, i8** %P
655  tail call void @no_sync_func(i8* %1) nounwind
656  tail call void @free(i8* %1)
657  ret void
658}
659
660define void @test16d(i8 %v, i8** %P) {
661; CHECK-LABEL: define {{[^@]+}}@test16d
662; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
663; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
664; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
665; CHECK-NEXT:    ret void
666;
667  %1 = tail call noalias i8* @malloc(i64 4)
668  store i8* %1, i8** %P
669  ret void
670}
671
672declare i8* @__kmpc_alloc_shared(i64)
673declare void @__kmpc_free_shared(i8* nocapture, i64)
674
675define void @test17() {
676; IS________OPM-LABEL: define {{[^@]+}}@test17() {
677; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @__kmpc_alloc_shared(i64 noundef 4)
678; IS________OPM-NEXT:    tail call void @usei8(i8* noalias nocapture nofree [[TMP1]]) #[[ATTR6:[0-9]+]]
679; IS________OPM-NEXT:    tail call void @__kmpc_free_shared(i8* noalias nocapture [[TMP1]], i64 noundef 4)
680; IS________OPM-NEXT:    ret void
681;
682; IS________NPM-LABEL: define {{[^@]+}}@test17() {
683; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1, addrspace(5)
684; IS________NPM-NEXT:    [[MALLOC_CAST:%.*]] = addrspacecast i8 addrspace(5)* [[DOTH2S]] to i8*
685; IS________NPM-NEXT:    tail call void @usei8(i8* noalias nocapture nofree [[MALLOC_CAST]]) #[[ATTR6:[0-9]+]]
686; IS________NPM-NEXT:    ret void
687;
688  %1 = tail call noalias i8* @__kmpc_alloc_shared(i64 4)
689  tail call void @usei8(i8* nocapture nofree %1) willreturn nounwind nosync
690  tail call void @__kmpc_free_shared(i8* %1, i64 4)
691  ret void
692}
693
694define void @test17b() {
695; CHECK-LABEL: define {{[^@]+}}@test17b() {
696; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @__kmpc_alloc_shared(i64 noundef 4)
697; CHECK-NEXT:    tail call void @usei8(i8* nofree [[TMP1]]) #[[ATTR6:[0-9]+]]
698; CHECK-NEXT:    tail call void @__kmpc_free_shared(i8* nocapture [[TMP1]], i64 noundef 4)
699; CHECK-NEXT:    ret void
700;
701  %1 = tail call noalias i8* @__kmpc_alloc_shared(i64 4)
702  tail call void @usei8(i8* nofree %1) willreturn nounwind nosync
703  tail call void @__kmpc_free_shared(i8* %1, i64 4)
704  ret void
705}
706
707define void @move_alloca() {
708; IS________OPM-LABEL: define {{[^@]+}}@move_alloca() {
709; IS________OPM-NEXT:  entry:
710; IS________OPM-NEXT:    br label [[NOT_ENTRY:%.*]]
711; IS________OPM:       not_entry:
712; IS________OPM-NEXT:    [[TMP0:%.*]] = tail call noalias i8* @__kmpc_alloc_shared(i64 noundef 4)
713; IS________OPM-NEXT:    tail call void @usei8(i8* noalias nocapture nofree [[TMP0]]) #[[ATTR6]]
714; IS________OPM-NEXT:    tail call void @__kmpc_free_shared(i8* noalias nocapture [[TMP0]], i64 noundef 4)
715; IS________OPM-NEXT:    ret void
716;
717; IS________NPM-LABEL: define {{[^@]+}}@move_alloca() {
718; IS________NPM-NEXT:  entry:
719; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1, addrspace(5)
720; IS________NPM-NEXT:    br label [[NOT_ENTRY:%.*]]
721; IS________NPM:       not_entry:
722; IS________NPM-NEXT:    [[MALLOC_CAST:%.*]] = addrspacecast i8 addrspace(5)* [[DOTH2S]] to i8*
723; IS________NPM-NEXT:    tail call void @usei8(i8* noalias nocapture nofree [[MALLOC_CAST]]) #[[ATTR6]]
724; IS________NPM-NEXT:    ret void
725;
726entry:
727  br label %not_entry
728
729not_entry:
730  %0 = tail call noalias i8* @__kmpc_alloc_shared(i64 4)
731  tail call void @usei8(i8* nocapture nofree %0) willreturn nounwind nosync
732  tail call void @__kmpc_free_shared(i8* %0, i64 4)
733  ret void
734}
735
736
737;.
738; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn }
739; CHECK: attributes #[[ATTR1:[0-9]+]] = { nofree nosync willreturn }
740; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind }
741; CHECK: attributes #[[ATTR3]] = { noreturn }
742; CHECK: attributes #[[ATTR4:[0-9]+]] = { argmemonly nocallback nofree nosync nounwind willreturn }
743; CHECK: attributes #[[ATTR5]] = { nounwind }
744; CHECK: attributes #[[ATTR6]] = { nosync nounwind willreturn }
745;.
746