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
7 target triple = "amdgcn-amd-amdhsa"
9 declare noalias i8* @malloc(i64)
11 declare void @nocapture_func_frees_pointer(i8* nocapture)
13 declare void @func_throws(...)
15 declare void @sync_func(i8* %p)
17 declare void @sync_will_return(i8* %p) willreturn nounwind
19 declare void @no_sync_func(i8* nocapture %p) nofree nosync willreturn
21 declare void @nofree_func(i8* nocapture %p) nofree nosync willreturn
23 declare void @foo(i32* %p)
25 declare void @foo_nounw(i32* %p) nounwind nofree
27 declare i32 @no_return_call() noreturn
29 declare void @free(i8* nocapture)
31 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
33 define 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
40 tail call void @free(i8* %p2)
41 tail call void @nofree_func(i8* %p1)
45 ; TEST 1 - negative, pointer freed in another function.
47 define 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
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)
62 ; TEST 2 - negative, call to a sync function.
64 define 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
71 %1 = tail call noalias i8* @malloc(i64 4)
72 tail call void @sync_func(i8* %1)
73 tail call void @free(i8* %1)
77 ; TEST 3 - 1 malloc, 1 free
79 define 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
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)
92 define 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
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
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)
113 declare noalias i8* @aligned_alloc(i64, i64)
115 define 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
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
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)
136 ; leave alone non-constant alignments.
137 define 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
144 %1 = tail call noalias i8* @aligned_alloc(i64 %alignment, i64 128)
145 tail call void @free(i8* %1)
149 declare noalias i8* @calloc(i64, i64)
151 define 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
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)
165 define 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
171 %1 = tail call noalias i8* @malloc(i64 4)
172 tail call void @nofree_func(i8* %1)
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
179 define 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:%.*]]
186 ; IS________OPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]])
187 ; IS________OPM-NEXT: br label [[TMP6:%.*]]
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]]
193 ; IS________OPM-NEXT: ret void
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:%.*]]
201 ; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]])
202 ; IS________NPM-NEXT: br label [[TMP6:%.*]]
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]]
208 ; IS________NPM-NEXT: ret void
210 %2 = tail call noalias i8* @malloc(i64 4)
211 %3 = icmp eq i32 %0, 0
212 br i1 %3, label %5, label %4
215 tail call void @nofree_func(i8* %2)
219 tail call void @nofree_arg_only(i8* %2, i8* %p)
220 tail call void @free(i8* %2)
227 ; TEST 6 - all exit paths have a call to free
229 define 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:%.*]]
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:%.*]]
240 ; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP2]])
241 ; CHECK-NEXT: br label [[TMP6]]
243 ; CHECK-NEXT: ret void
245 %2 = tail call noalias i8* @malloc(i64 4)
246 %3 = icmp eq i32 %0, 0
247 br i1 %3, label %5, label %4
250 tail call void @nofree_func(i8* %2)
251 tail call void @free(i8* %2)
255 tail call void @free(i8* %2)
262 ; TEST 7 - free is dead.
264 define 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
272 %1 = tail call noalias i8* @malloc(i64 4)
273 tail call i32 @no_return_call()
274 tail call void @free(i8* %1)
278 ; TEST 8 - Negative: bitcast pointer used in capture function
280 define 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
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)
300 ; TEST 9 - FIXME: malloc should be converted.
301 define 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
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)
321 ; TEST 10 - 1 malloc, 1 free
323 define 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]]
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)
342 define 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]]
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)
365 define 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
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)
379 define 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:%.*]]
388 ; IS________OPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5
389 ; IS________OPM-NEXT: br label [[TMP13:%.*]]
391 ; IS________OPM-NEXT: br label [[TMP8:%.*]]
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:%.*]]
400 ; IS________OPM-NEXT: br label [[TMP13]]
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]]
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]]
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:%.*]]
420 ; IS________NPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5
421 ; IS________NPM-NEXT: br label [[TMP13:%.*]]
423 ; IS________NPM-NEXT: br label [[TMP8:%.*]]
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:%.*]]
432 ; IS________NPM-NEXT: br label [[TMP13]]
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]]
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]]
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
450 %6 = add nsw i32 %0, 5
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
467 13: ; preds = %12, %5
468 %.1 = phi i32 [ %6, %5 ], [ %.0, %12 ]
469 %14 = add nsw i32 %.1, 1
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
481 define 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:%.*]]
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:%.*]]
495 ; CHECK-NEXT: [[TMP9:%.*]] = call noalias i8* @malloc(i64 noundef 4)
496 ; CHECK-NEXT: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32*
497 ; CHECK-NEXT: store i32 1, i32* [[TMP10]], align 8
498 ; CHECK-NEXT: br label [[TMP4]]
500 ; CHECK-NEXT: ret i32 5
502 %2 = alloca i32, align 4
503 %3 = alloca i32*, align 8
504 store i32 %0, i32* %2, align 4
508 %5 = load i32, i32* %2, align 4
509 %6 = add nsw i32 %5, -1
510 store i32 %6, i32* %2, align 4
511 %7 = icmp sgt i32 %6, 0
512 br i1 %7, label %8, label %11
515 %9 = call noalias i8* @malloc(i64 4)
516 %10 = bitcast i8* %9 to i32*
517 store i32 1, i32* %10, align 8
524 ; Malloc/Calloc too large
525 define i32 @test13() {
526 ; CHECK-LABEL: define {{[^@]+}}@test13() {
527 ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 256)
528 ; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
529 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
530 ; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4
531 ; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
532 ; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
533 ; CHECK-NEXT: ret i32 [[TMP3]]
535 %1 = tail call noalias i8* @malloc(i64 256)
536 tail call void @no_sync_func(i8* %1)
537 %2 = bitcast i8* %1 to i32*
538 store i32 10, i32* %2
539 %3 = load i32, i32* %2
540 tail call void @free(i8* %1)
544 define i32 @test_sle() {
545 ; CHECK-LABEL: define {{[^@]+}}@test_sle() {
546 ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef -1)
547 ; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
548 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
549 ; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4
550 ; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
551 ; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
552 ; CHECK-NEXT: ret i32 [[TMP3]]
554 %1 = tail call noalias i8* @malloc(i64 -1)
555 tail call void @no_sync_func(i8* %1)
556 %2 = bitcast i8* %1 to i32*
557 store i32 10, i32* %2
558 %3 = load i32, i32* %2
559 tail call void @free(i8* %1)
563 define i32 @test_overflow() {
564 ; CHECK-LABEL: define {{[^@]+}}@test_overflow() {
565 ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 65537, i64 noundef 65537)
566 ; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
567 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
568 ; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4
569 ; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
570 ; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
571 ; CHECK-NEXT: ret i32 [[TMP3]]
573 %1 = tail call noalias i8* @calloc(i64 65537, i64 65537)
574 tail call void @no_sync_func(i8* %1)
575 %2 = bitcast i8* %1 to i32*
576 store i32 10, i32* %2
577 %3 = load i32, i32* %2
578 tail call void @free(i8* %1)
582 define void @test14() {
583 ; CHECK-LABEL: define {{[^@]+}}@test14() {
584 ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 64, i64 noundef 4)
585 ; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
586 ; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]])
587 ; CHECK-NEXT: ret void
589 %1 = tail call noalias i8* @calloc(i64 64, i64 4)
590 tail call void @no_sync_func(i8* %1)
591 tail call void @free(i8* %1)
595 define void @test15(i64 %S) {
596 ; CHECK-LABEL: define {{[^@]+}}@test15
597 ; CHECK-SAME: (i64 [[S:%.*]]) {
598 ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 [[S]])
599 ; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
600 ; CHECK-NEXT: tail call void @free(i8* noalias nocapture [[TMP1]])
601 ; CHECK-NEXT: ret void
603 %1 = tail call noalias i8* @malloc(i64 %S)
604 tail call void @no_sync_func(i8* %1)
605 tail call void @free(i8* %1)
609 define void @test16a(i8 %v, i8** %P) {
610 ; CHECK-LABEL: define {{[^@]+}}@test16a
611 ; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) {
612 ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
613 ; CHECK-NEXT: store i8 [[V]], i8* [[TMP1]], align 1
614 ; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[TMP1]])
615 ; CHECK-NEXT: tail call void @free(i8* noalias nocapture noundef nonnull dereferenceable(1) [[TMP1]])
616 ; CHECK-NEXT: ret void
618 %1 = tail call noalias i8* @malloc(i64 4)
620 tail call void @no_sync_func(i8* %1)
621 tail call void @free(i8* nonnull dereferenceable(1) %1)
625 define void @test16b(i8 %v, i8** %P) {
626 ; CHECK-LABEL: define {{[^@]+}}@test16b
627 ; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
628 ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
629 ; CHECK-NEXT: store i8* [[TMP1]], i8** [[P]], align 8
630 ; CHECK-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
631 ; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP1]])
632 ; CHECK-NEXT: ret void
634 %1 = tail call noalias i8* @malloc(i64 4)
635 store i8* %1, i8** %P
636 tail call void @no_sync_func(i8* %1)
637 tail call void @free(i8* %1)
641 define void @test16c(i8 %v, i8** %P) {
642 ; CHECK-LABEL: define {{[^@]+}}@test16c
643 ; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
644 ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
645 ; CHECK-NEXT: store i8* [[TMP1]], i8** [[P]], align 8
646 ; CHECK-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) #[[ATTR5]]
647 ; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP1]])
648 ; CHECK-NEXT: ret void
650 %1 = tail call noalias i8* @malloc(i64 4)
651 store i8* %1, i8** %P
652 tail call void @no_sync_func(i8* %1) nounwind
653 tail call void @free(i8* %1)
657 define void @test16d(i8 %v, i8** %P) {
658 ; CHECK-LABEL: define {{[^@]+}}@test16d
659 ; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
660 ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
661 ; CHECK-NEXT: store i8* [[TMP1]], i8** [[P]], align 8
662 ; CHECK-NEXT: ret void
664 %1 = tail call noalias i8* @malloc(i64 4)
665 store i8* %1, i8** %P
669 ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn }
670 ; CHECK: attributes #[[ATTR1:[0-9]+]] = { nofree nosync willreturn }
671 ; CHECK: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind }
672 ; CHECK: attributes #[[ATTR3]] = { noreturn }
673 ; CHECK: attributes #[[ATTR4:[0-9]+]] = { argmemonly nofree nosync nounwind willreturn }
674 ; CHECK: attributes #[[ATTR5]] = { nounwind }