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=8 -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=8 -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
7declare noalias i8* @malloc(i64) allockind("alloc,uninitialized") allocsize(0)
8
9declare void @nocapture_func_frees_pointer(i8* nocapture)
10
11declare void @func_throws(...)
12
13declare void @sync_func(i8* %p)
14
15declare void @sync_will_return(i8* %p) willreturn nounwind
16
17declare void @no_sync_func(i8* nocapture %p) nofree nosync willreturn
18
19declare void @nofree_func(i8* nocapture %p) nofree  nosync willreturn
20
21declare void @foo(i32* %p)
22
23declare void @foo_nounw(i32* %p) nounwind nofree
24
25declare void @usei8(i8)
26
27declare i32 @no_return_call() noreturn
28
29declare void @free(i8* nocapture) allockind("free")
30
31declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
32
33define void @h2s_value_simplify_interaction(i1 %c, i8* %A) {
34; IS________OPM-LABEL: define {{[^@]+}}@h2s_value_simplify_interaction
35; IS________OPM-SAME: (i1 [[C:%.*]], i8* nocapture nofree readnone [[A:%.*]]) {
36; IS________OPM-NEXT:  entry:
37; IS________OPM-NEXT:    [[ADD:%.*]] = add i64 2, 2
38; IS________OPM-NEXT:    [[M:%.*]] = tail call noalias align 16 i8* @malloc(i64 noundef [[ADD]])
39; IS________OPM-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
40; IS________OPM:       t:
41; IS________OPM-NEXT:    br i1 false, label [[DEAD:%.*]], label [[F2:%.*]]
42; IS________OPM:       f:
43; IS________OPM-NEXT:    br label [[J:%.*]]
44; IS________OPM:       f2:
45; IS________OPM-NEXT:    [[C1:%.*]] = bitcast i8* [[M]] to i32*
46; IS________OPM-NEXT:    [[C2:%.*]] = bitcast i32* [[C1]] to i8*
47; IS________OPM-NEXT:    [[L:%.*]] = load i8, i8* [[C2]], align 16
48; IS________OPM-NEXT:    call void @usei8(i8 [[L]])
49; IS________OPM-NEXT:    call void @no_sync_func(i8* nocapture nofree noundef align 16 [[C2]]) #[[ATTR9:[0-9]+]]
50; IS________OPM-NEXT:    br label [[J]]
51; IS________OPM:       dead:
52; IS________OPM-NEXT:    unreachable
53; IS________OPM:       j:
54; IS________OPM-NEXT:    [[PHI:%.*]] = phi i8* [ [[M]], [[F]] ], [ null, [[F2]] ]
55; IS________OPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree noundef align 16 [[PHI]]) #[[ATTR9]]
56; IS________OPM-NEXT:    ret void
57;
58; IS________NPM-LABEL: define {{[^@]+}}@h2s_value_simplify_interaction
59; IS________NPM-SAME: (i1 [[C:%.*]], i8* nocapture nofree readnone [[A:%.*]]) {
60; IS________NPM-NEXT:  entry:
61; IS________NPM-NEXT:    [[ADD:%.*]] = add i64 2, 2
62; IS________NPM-NEXT:    [[M:%.*]] = tail call noalias align 16 i8* @malloc(i64 noundef [[ADD]])
63; IS________NPM-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
64; IS________NPM:       t:
65; IS________NPM-NEXT:    br i1 false, label [[DEAD:%.*]], label [[F2:%.*]]
66; IS________NPM:       f:
67; IS________NPM-NEXT:    br label [[J:%.*]]
68; IS________NPM:       f2:
69; IS________NPM-NEXT:    [[L:%.*]] = load i8, i8* [[M]], align 16
70; IS________NPM-NEXT:    call void @usei8(i8 [[L]])
71; IS________NPM-NEXT:    call void @no_sync_func(i8* nocapture nofree noundef align 16 [[M]]) #[[ATTR10:[0-9]+]]
72; IS________NPM-NEXT:    br label [[J]]
73; IS________NPM:       dead:
74; IS________NPM-NEXT:    unreachable
75; IS________NPM:       j:
76; IS________NPM-NEXT:    [[PHI:%.*]] = phi i8* [ [[M]], [[F]] ], [ null, [[F2]] ]
77; IS________NPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree noundef align 16 [[PHI]]) #[[ATTR10]]
78; IS________NPM-NEXT:    ret void
79;
80entry:
81  %add = add i64 2, 2
82  %m = tail call align 16 noalias i8* @malloc(i64 %add)
83  br i1 %c, label %t, label %f
84t:
85  br i1 false, label %dead, label %f2
86f:
87  br label %j
88f2:
89  %c1 = bitcast i8* %m to i32*
90  %c2 = bitcast i32* %c1 to i8*
91  %l = load i8, i8* %c2
92  call void @usei8(i8 %l)
93  call void @no_sync_func(i8* noundef %c2) nounwind
94  br label %j
95dead:
96  br label %j
97j:
98  %phi = phi i8* [ %m, %f ], [ null, %f2 ], [ %A, %dead ]
99  tail call void @no_sync_func(i8* noundef %phi) nounwind
100  ;tail call void @free(i8* %m)
101  ret void
102}
103
104define void @nofree_arg_only(i8* %p1, i8* %p2) {
105; CHECK-LABEL: define {{[^@]+}}@nofree_arg_only
106; CHECK-SAME: (i8* nocapture nofree [[P1:%.*]], i8* nocapture [[P2:%.*]]) {
107; CHECK-NEXT:    tail call void @free(i8* nocapture [[P2]])
108; CHECK-NEXT:    tail call void @nofree_func(i8* nocapture nofree [[P1]])
109; CHECK-NEXT:    ret void
110;
111  tail call void @free(i8* %p2)
112  tail call void @nofree_func(i8* %p1)
113  ret void
114}
115
116; TEST 1 - negative, pointer freed in another function.
117
118define void @test1() {
119; CHECK-LABEL: define {{[^@]+}}@test1() {
120; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
121; CHECK-NEXT:    tail call void @nocapture_func_frees_pointer(i8* noalias nocapture [[TMP1]])
122; CHECK-NEXT:    tail call void (...) @func_throws()
123; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
124; CHECK-NEXT:    ret void
125;
126  %1 = tail call noalias i8* @malloc(i64 4)
127  tail call void @nocapture_func_frees_pointer(i8* %1)
128  tail call void (...) @func_throws()
129  tail call void @free(i8* %1)
130  ret void
131}
132
133; TEST 2 - negative, call to a sync function.
134
135define void @test2() {
136; CHECK-LABEL: define {{[^@]+}}@test2() {
137; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
138; CHECK-NEXT:    tail call void @sync_func(i8* [[TMP1]])
139; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
140; CHECK-NEXT:    ret void
141;
142  %1 = tail call noalias i8* @malloc(i64 4)
143  tail call void @sync_func(i8* %1)
144  tail call void @free(i8* %1)
145  ret void
146}
147
148; TEST 3 - 1 malloc, 1 free
149
150define void @test3() {
151; IS________OPM-LABEL: define {{[^@]+}}@test3() {
152; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
153; IS________OPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
154; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
155; IS________OPM-NEXT:    ret void
156;
157; IS________NPM-LABEL: define {{[^@]+}}@test3() {
158; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
159; IS________NPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]])
160; IS________NPM-NEXT:    ret void
161;
162  %1 = tail call noalias i8* @malloc(i64 4)
163  tail call void @no_sync_func(i8* %1)
164  tail call void @free(i8* %1)
165  ret void
166}
167
168define void @test3a(i8* %p) {
169; IS________OPM-LABEL: define {{[^@]+}}@test3a
170; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) {
171; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
172; IS________OPM-NEXT:    tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]])
173; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
174; IS________OPM-NEXT:    ret void
175;
176; IS________NPM-LABEL: define {{[^@]+}}@test3a
177; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) {
178; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
179; IS________NPM-NEXT:    tail call void @nofree_arg_only(i8* noalias nocapture nofree [[DOTH2S]], i8* nocapture [[P]])
180; IS________NPM-NEXT:    ret void
181;
182  %1 = tail call noalias i8* @malloc(i64 4)
183  tail call void @nofree_arg_only(i8* %1, i8* %p)
184  tail call void @free(i8* %1)
185  ret void
186}
187
188declare noalias i8* @aligned_alloc(i64 allocalign, i64) allockind("alloc,uninitialized,aligned") allocsize(1)
189
190define void @test3b(i8* %p) {
191; IS________OPM-LABEL: define {{[^@]+}}@test3b
192; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) {
193; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 32, i64 noundef 128)
194; IS________OPM-NEXT:    tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]])
195; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
196; IS________OPM-NEXT:    ret void
197;
198; IS________NPM-LABEL: define {{[^@]+}}@test3b
199; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) {
200; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 128, align 32
201; IS________NPM-NEXT:    tail call void @nofree_arg_only(i8* noalias nocapture nofree [[DOTH2S]], i8* nocapture [[P]])
202; IS________NPM-NEXT:    ret void
203;
204  %1 = tail call noalias i8* @aligned_alloc(i64 32, i64 128)
205  tail call void @nofree_arg_only(i8* %1, i8* %p)
206  tail call void @free(i8* %1)
207  ret void
208}
209
210; leave alone non-constant alignments.
211define void @test3c(i64 %alignment) {
212; CHECK-LABEL: define {{[^@]+}}@test3c
213; CHECK-SAME: (i64 [[ALIGNMENT:%.*]]) {
214; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 [[ALIGNMENT]], i64 noundef 128)
215; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
216; CHECK-NEXT:    ret void
217;
218  %1 = tail call noalias i8* @aligned_alloc(i64 %alignment, i64 128)
219  tail call void @free(i8* %1)
220  ret void
221}
222
223; leave alone a constant-but-invalid alignment
224define void @test3d(i8* %p) {
225; IS________OPM-LABEL: define {{[^@]+}}@test3d
226; IS________OPM-SAME: (i8* nocapture [[P:%.*]]) {
227; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 33, i64 noundef 128)
228; IS________OPM-NEXT:    tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]])
229; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
230; IS________OPM-NEXT:    ret void
231;
232; IS________NPM-LABEL: define {{[^@]+}}@test3d
233; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) {
234; IS________NPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 noundef 33, i64 noundef 128)
235; IS________NPM-NEXT:    tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]])
236; IS________NPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
237; IS________NPM-NEXT:    ret void
238;
239; CHECK-SAME; (i8* nocapture [[P:%.*]]) {
240  %1 = tail call noalias i8* @aligned_alloc(i64 33, i64 128)
241  tail call void @nofree_arg_only(i8* %1, i8* %p)
242  tail call void @free(i8* %1)
243  ret void
244}
245
246declare noalias i8* @calloc(i64, i64) allockind("alloc,zeroed") allocsize(0,1)
247
248define void @test0() {
249; IS________OPM-LABEL: define {{[^@]+}}@test0() {
250; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 2, i64 noundef 4)
251; IS________OPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
252; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
253; IS________OPM-NEXT:    ret void
254;
255; IS________NPM-LABEL: define {{[^@]+}}@test0() {
256; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 8, align 1
257; IS________NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[DOTH2S]], i8 0, i64 8, i1 false)
258; IS________NPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]])
259; IS________NPM-NEXT:    ret void
260;
261  %1 = tail call noalias i8* @calloc(i64 2, i64 4)
262  tail call void @no_sync_func(i8* %1)
263  tail call void @free(i8* %1)
264  ret void
265}
266
267; TEST 4
268define void @test4() {
269; CHECK-LABEL: define {{[^@]+}}@test4() {
270; CHECK-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
271; CHECK-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[DOTH2S]])
272; CHECK-NEXT:    ret void
273;
274  %1 = tail call noalias i8* @malloc(i64 4)
275  tail call void @nofree_func(i8* %1)
276  ret void
277}
278
279; TEST 5 - not all exit paths have a call to free, but all uses of malloc
280; are in nofree functions and are not captured
281
282define void @test5(i32, i8* %p) {
283; IS________OPM-LABEL: define {{[^@]+}}@test5
284; IS________OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) {
285; IS________OPM-NEXT:    [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
286; IS________OPM-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0
287; IS________OPM-NEXT:    br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
288; IS________OPM:       4:
289; IS________OPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]])
290; IS________OPM-NEXT:    br label [[TMP6:%.*]]
291; IS________OPM:       5:
292; IS________OPM-NEXT:    tail call void @nofree_arg_only(i8* nocapture nofree [[TMP2]], i8* nocapture [[P]])
293; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
294; IS________OPM-NEXT:    br label [[TMP6]]
295; IS________OPM:       6:
296; IS________OPM-NEXT:    ret void
297;
298; IS________NPM-LABEL: define {{[^@]+}}@test5
299; IS________NPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) {
300; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
301; IS________NPM-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0
302; IS________NPM-NEXT:    br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
303; IS________NPM:       3:
304; IS________NPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[DOTH2S]])
305; IS________NPM-NEXT:    br label [[TMP5:%.*]]
306; IS________NPM:       4:
307; IS________NPM-NEXT:    tail call void @nofree_arg_only(i8* noalias nocapture nofree [[DOTH2S]], i8* nocapture [[P]])
308; IS________NPM-NEXT:    br label [[TMP5]]
309; IS________NPM:       5:
310; IS________NPM-NEXT:    ret void
311;
312  %2 = tail call noalias i8* @malloc(i64 4)
313  %3 = icmp eq i32 %0, 0
314  br i1 %3, label %5, label %4
315
3164:                                                ; preds = %1
317  tail call void @nofree_func(i8* %2)
318  br label %6
319
3205:                                                ; preds = %1
321  tail call void @nofree_arg_only(i8* %2, i8* %p)
322  tail call void @free(i8* %2)
323  br label %6
324
3256:                                                ; preds = %5, %4
326  ret void
327}
328
329; TEST 6 - all exit paths have a call to free
330
331define void @test6(i32) {
332; IS________OPM-LABEL: define {{[^@]+}}@test6
333; IS________OPM-SAME: (i32 [[TMP0:%.*]]) {
334; IS________OPM-NEXT:    [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
335; IS________OPM-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0
336; IS________OPM-NEXT:    br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
337; IS________OPM:       4:
338; IS________OPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]])
339; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
340; IS________OPM-NEXT:    br label [[TMP6:%.*]]
341; IS________OPM:       5:
342; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
343; IS________OPM-NEXT:    br label [[TMP6]]
344; IS________OPM:       6:
345; IS________OPM-NEXT:    ret void
346;
347; IS________NPM-LABEL: define {{[^@]+}}@test6
348; IS________NPM-SAME: (i32 [[TMP0:%.*]]) {
349; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
350; IS________NPM-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0
351; IS________NPM-NEXT:    br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
352; IS________NPM:       3:
353; IS________NPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[DOTH2S]])
354; IS________NPM-NEXT:    br label [[TMP5:%.*]]
355; IS________NPM:       4:
356; IS________NPM-NEXT:    br label [[TMP5]]
357; IS________NPM:       5:
358; IS________NPM-NEXT:    ret void
359;
360  %2 = tail call noalias i8* @malloc(i64 4)
361  %3 = icmp eq i32 %0, 0
362  br i1 %3, label %5, label %4
363
3644:                                                ; preds = %1
365  tail call void @nofree_func(i8* %2)
366  tail call void @free(i8* %2)
367  br label %6
368
3695:                                                ; preds = %1
370  tail call void @free(i8* %2)
371  br label %6
372
3736:                                                ; preds = %5, %4
374  ret void
375}
376
377; TEST 7 - free is dead.
378
379define void @test7() {
380; IS________OPM-LABEL: define {{[^@]+}}@test7() {
381; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
382; IS________OPM-NEXT:    [[TMP2:%.*]] = tail call i32 @no_return_call() #[[ATTR4:[0-9]+]]
383; IS________OPM-NEXT:    unreachable
384;
385; IS________NPM-LABEL: define {{[^@]+}}@test7() {
386; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
387; IS________NPM-NEXT:    [[TMP1:%.*]] = tail call i32 @no_return_call() #[[ATTR4:[0-9]+]]
388; IS________NPM-NEXT:    unreachable
389;
390  %1 = tail call noalias i8* @malloc(i64 4)
391  tail call i32 @no_return_call()
392  tail call void @free(i8* %1)
393  ret void
394}
395
396; TEST 8 - Negative: bitcast pointer used in capture function
397
398define void @test8() {
399; CHECK-LABEL: define {{[^@]+}}@test8() {
400; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
401; CHECK-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
402; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
403; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
404; CHECK-NEXT:    tail call void @foo(i32* noundef align 4 [[TMP2]])
405; CHECK-NEXT:    tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
406; CHECK-NEXT:    ret void
407;
408  %1 = tail call noalias i8* @malloc(i64 4)
409  tail call void @no_sync_func(i8* %1)
410  %2 = bitcast i8* %1 to i32*
411  store i32 10, i32* %2
412  %3 = load i32, i32* %2
413  tail call void @foo(i32* %2)
414  tail call void @free(i8* %1)
415  ret void
416}
417
418; TEST 9 - FIXME: malloc should be converted.
419define void @test9() {
420; IS________OPM-LABEL: define {{[^@]+}}@test9() {
421; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
422; IS________OPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
423; IS________OPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
424; IS________OPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
425; IS________OPM-NEXT:    tail call void @foo_nounw(i32* nofree noundef align 4 [[TMP2]]) #[[ATTR9]]
426; IS________OPM-NEXT:    tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
427; IS________OPM-NEXT:    ret void
428;
429; IS________NPM-LABEL: define {{[^@]+}}@test9() {
430; IS________NPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
431; IS________NPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
432; IS________NPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
433; IS________NPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
434; IS________NPM-NEXT:    tail call void @foo_nounw(i32* nofree noundef align 4 [[TMP2]]) #[[ATTR10]]
435; IS________NPM-NEXT:    tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
436; IS________NPM-NEXT:    ret void
437;
438  %1 = tail call noalias i8* @malloc(i64 4)
439  tail call void @no_sync_func(i8* %1)
440  %2 = bitcast i8* %1 to i32*
441  store i32 10, i32* %2
442  %3 = load i32, i32* %2
443  tail call void @foo_nounw(i32* %2)
444  tail call void @free(i8* %1)
445  ret void
446}
447
448; TEST 10 - 1 malloc, 1 free
449
450define i32 @test10() {
451; IS________OPM-LABEL: define {{[^@]+}}@test10() {
452; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
453; IS________OPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
454; IS________OPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
455; IS________OPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
456; IS________OPM-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
457; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
458; IS________OPM-NEXT:    ret i32 [[TMP3]]
459;
460; IS________NPM-LABEL: define {{[^@]+}}@test10() {
461; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
462; IS________NPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]])
463; IS________NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[DOTH2S]] to i32*
464; IS________NPM-NEXT:    store i32 10, i32* [[TMP1]], align 4
465; IS________NPM-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
466; IS________NPM-NEXT:    ret i32 [[TMP2]]
467;
468  %1 = tail call noalias i8* @malloc(i64 4)
469  tail call void @no_sync_func(i8* %1)
470  %2 = bitcast i8* %1 to i32*
471  store i32 10, i32* %2
472  %3 = load i32, i32* %2
473  tail call void @free(i8* %1)
474  ret i32 %3
475}
476
477define i32 @test_lifetime() {
478; IS________OPM-LABEL: define {{[^@]+}}@test_lifetime() {
479; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
480; IS________OPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
481; IS________OPM-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[TMP1]])
482; IS________OPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
483; IS________OPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
484; IS________OPM-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
485; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
486; IS________OPM-NEXT:    ret i32 [[TMP3]]
487;
488; IS________NPM-LABEL: define {{[^@]+}}@test_lifetime() {
489; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
490; IS________NPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]])
491; IS________NPM-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTH2S]])
492; IS________NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[DOTH2S]] to i32*
493; IS________NPM-NEXT:    store i32 10, i32* [[TMP1]], align 4
494; IS________NPM-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
495; IS________NPM-NEXT:    ret i32 [[TMP2]]
496;
497  %1 = tail call noalias i8* @malloc(i64 4)
498  tail call void @no_sync_func(i8* %1)
499  call void @llvm.lifetime.start.p0i8(i64 4, i8* %1)
500  %2 = bitcast i8* %1 to i32*
501  store i32 10, i32* %2
502  %3 = load i32, i32* %2
503  tail call void @free(i8* %1)
504  ret i32 %3
505}
506
507; TEST 11
508
509define void @test11() {
510; IS________OPM-LABEL: define {{[^@]+}}@test11() {
511; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
512; IS________OPM-NEXT:    tail call void @sync_will_return(i8* [[TMP1]]) #[[ATTR9]]
513; IS________OPM-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
514; IS________OPM-NEXT:    ret void
515;
516; IS________NPM-LABEL: define {{[^@]+}}@test11() {
517; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
518; IS________NPM-NEXT:    tail call void @sync_will_return(i8* [[DOTH2S]]) #[[ATTR10]]
519; IS________NPM-NEXT:    ret void
520;
521  %1 = tail call noalias i8* @malloc(i64 4)
522  tail call void @sync_will_return(i8* %1)
523  tail call void @free(i8* %1)
524  ret void
525}
526
527; TEST 12
528define i32 @irreducible_cfg(i32 %0) {
529; IS________OPM-LABEL: define {{[^@]+}}@irreducible_cfg
530; IS________OPM-SAME: (i32 [[TMP0:%.*]]) {
531; IS________OPM-NEXT:    [[TMP2:%.*]] = call noalias i8* @malloc(i64 noundef 4)
532; IS________OPM-NEXT:    [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32*
533; IS________OPM-NEXT:    store i32 10, i32* [[TMP3]], align 4
534; IS________OPM-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1
535; IS________OPM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]]
536; IS________OPM:       5:
537; IS________OPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5
538; IS________OPM-NEXT:    br label [[TMP13:%.*]]
539; IS________OPM:       7:
540; IS________OPM-NEXT:    br label [[TMP8:%.*]]
541; IS________OPM:       8:
542; IS________OPM-NEXT:    [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ]
543; IS________OPM-NEXT:    [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4
544; IS________OPM-NEXT:    [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1
545; IS________OPM-NEXT:    store i32 [[TMP10]], i32* [[TMP3]], align 4
546; IS________OPM-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0
547; IS________OPM-NEXT:    br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]]
548; IS________OPM:       12:
549; IS________OPM-NEXT:    br label [[TMP13]]
550; IS________OPM:       13:
551; IS________OPM-NEXT:    [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ]
552; IS________OPM-NEXT:    [[TMP14]] = add nsw i32 [[DOT1]], 1
553; IS________OPM-NEXT:    br label [[TMP8]]
554; IS________OPM:       15:
555; IS________OPM-NEXT:    [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8*
556; IS________OPM-NEXT:    call void @free(i8* nocapture noundef [[TMP16]])
557; IS________OPM-NEXT:    [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4
558; IS________OPM-NEXT:    ret i32 [[TMP17]]
559;
560; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg
561; IS________NPM-SAME: (i32 [[TMP0:%.*]]) {
562; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
563; IS________NPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[DOTH2S]] to i32*
564; IS________NPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
565; IS________NPM-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 1
566; IS________NPM-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
567; IS________NPM:       4:
568; IS________NPM-NEXT:    [[TMP5:%.*]] = add nsw i32 [[TMP0]], 5
569; IS________NPM-NEXT:    br label [[TMP12:%.*]]
570; IS________NPM:       6:
571; IS________NPM-NEXT:    br label [[TMP7:%.*]]
572; IS________NPM:       7:
573; IS________NPM-NEXT:    [[DOT0:%.*]] = phi i32 [ [[TMP13:%.*]], [[TMP12]] ], [ 1, [[TMP6]] ]
574; IS________NPM-NEXT:    [[TMP8:%.*]] = load i32, i32* [[TMP2]], align 4
575; IS________NPM-NEXT:    [[TMP9:%.*]] = add nsw i32 [[TMP8]], -1
576; IS________NPM-NEXT:    store i32 [[TMP9]], i32* [[TMP2]], align 4
577; IS________NPM-NEXT:    [[TMP10:%.*]] = icmp ne i32 [[TMP8]], 0
578; IS________NPM-NEXT:    br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP14:%.*]]
579; IS________NPM:       11:
580; IS________NPM-NEXT:    br label [[TMP12]]
581; IS________NPM:       12:
582; IS________NPM-NEXT:    [[DOT1:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[DOT0]], [[TMP11]] ]
583; IS________NPM-NEXT:    [[TMP13]] = add nsw i32 [[DOT1]], 1
584; IS________NPM-NEXT:    br label [[TMP7]]
585; IS________NPM:       14:
586; IS________NPM-NEXT:    [[TMP15:%.*]] = load i32, i32* [[TMP2]], align 4
587; IS________NPM-NEXT:    ret i32 [[TMP15]]
588;
589  %2 = call noalias i8* @malloc(i64 4)
590  %3 = bitcast i8* %2 to i32*
591  store i32 10, i32* %3, align 4
592  %4 = icmp eq i32 %0, 1
593  br i1 %4, label %5, label %7
594
5955:                                                ; preds = %1
596  %6 = add nsw i32 %0, 5
597  br label %13
598
5997:                                                ; preds = %1
600  br label %8
601
6028:                                                ; preds = %13, %7
603  %.0 = phi i32 [ %14, %13 ], [ 1, %7 ]
604  %9 = load i32, i32* %3, align 4
605  %10 = add nsw i32 %9, -1
606  store i32 %10, i32* %3, align 4
607  %11 = icmp ne i32 %9, 0
608  br i1 %11, label %12, label %15
609
61012:                                               ; preds = %8
611  br label %13
612
61313:                                               ; preds = %12, %5
614  %.1 = phi i32 [ %6, %5 ], [ %.0, %12 ]
615  %14 = add nsw i32 %.1, 1
616  br label %8
617
61815:                                               ; preds = %8
619  %16 = load i32, i32* %3, align 4
620  %17 = bitcast i32* %3 to i8*
621  call void @free(i8* %17)
622  %18 = load i32, i32* %3, align 4
623  ret i32 %18
624}
625
626
627define i32 @malloc_in_loop(i32 %0) {
628; CHECK-LABEL: define {{[^@]+}}@malloc_in_loop
629; CHECK-SAME: (i32 [[TMP0:%.*]]) {
630; CHECK-NEXT:    [[TMP2:%.*]] = alloca i32, align 4
631; CHECK-NEXT:    [[TMP3:%.*]] = alloca i32*, align 8
632; CHECK-NEXT:    store i32 [[TMP0]], i32* [[TMP2]], align 4
633; CHECK-NEXT:    br label [[TMP4:%.*]]
634; CHECK:       4:
635; CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP2]], align 4
636; CHECK-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP5]], -1
637; CHECK-NEXT:    store i32 [[TMP6]], i32* [[TMP2]], align 4
638; CHECK-NEXT:    [[TMP7:%.*]] = icmp sgt i32 [[TMP6]], 0
639; CHECK-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP10:%.*]]
640; CHECK:       8:
641; CHECK-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
642; CHECK-NEXT:    [[TMP9:%.*]] = bitcast i8* [[DOTH2S]] to i32*
643; CHECK-NEXT:    br label [[TMP4]]
644; CHECK:       10:
645; CHECK-NEXT:    ret i32 5
646;
647  %2 = alloca i32, align 4
648  %3 = alloca i32*, align 8
649  store i32 %0, i32* %2, align 4
650  br label %4
651
6524:                                                ; preds = %8, %1
653  %5 = load i32, i32* %2, align 4
654  %6 = add nsw i32 %5, -1
655  store i32 %6, i32* %2, align 4
656  %7 = icmp sgt i32 %6, 0
657  br i1 %7, label %8, label %11
658
6598:                                                ; preds = %4
660  %9 = call noalias i8* @malloc(i64 4)
661  %10 = bitcast i8* %9 to i32*
662  store i32 1, i32* %10, align 8
663  br label %4
664
66511:                                               ; preds = %4
666  ret i32 5
667}
668
669; Malloc/Calloc too large
670define i32 @test13() {
671; CHECK-LABEL: define {{[^@]+}}@test13() {
672; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 256)
673; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
674; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
675; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
676; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
677; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
678; CHECK-NEXT:    ret i32 [[TMP3]]
679;
680  %1 = tail call noalias i8* @malloc(i64 256)
681  tail call void @no_sync_func(i8* %1)
682  %2 = bitcast i8* %1 to i32*
683  store i32 10, i32* %2
684  %3 = load i32, i32* %2
685  tail call void @free(i8* %1)
686  ret i32 %3
687}
688
689define i32 @test_sle() {
690; CHECK-LABEL: define {{[^@]+}}@test_sle() {
691; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef -1)
692; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
693; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
694; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
695; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
696; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
697; CHECK-NEXT:    ret i32 [[TMP3]]
698;
699  %1 = tail call noalias i8* @malloc(i64 -1)
700  tail call void @no_sync_func(i8* %1)
701  %2 = bitcast i8* %1 to i32*
702  store i32 10, i32* %2
703  %3 = load i32, i32* %2
704  tail call void @free(i8* %1)
705  ret i32 %3
706}
707
708define i32 @test_overflow() {
709; CHECK-LABEL: define {{[^@]+}}@test_overflow() {
710; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 65537, i64 noundef 65537)
711; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
712; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
713; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
714; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
715; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
716; CHECK-NEXT:    ret i32 [[TMP3]]
717;
718  %1 = tail call noalias i8* @calloc(i64 65537, i64 65537)
719  tail call void @no_sync_func(i8* %1)
720  %2 = bitcast i8* %1 to i32*
721  store i32 10, i32* %2
722  %3 = load i32, i32* %2
723  tail call void @free(i8* %1)
724  ret i32 %3
725}
726
727define void @test14() {
728; CHECK-LABEL: define {{[^@]+}}@test14() {
729; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 64, i64 noundef 4)
730; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
731; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
732; CHECK-NEXT:    ret void
733;
734  %1 = tail call noalias i8* @calloc(i64 64, i64 4)
735  tail call void @no_sync_func(i8* %1)
736  tail call void @free(i8* %1)
737  ret void
738}
739
740define void @test15(i64 %S) {
741; CHECK-LABEL: define {{[^@]+}}@test15
742; CHECK-SAME: (i64 [[S:%.*]]) {
743; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 [[S]])
744; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
745; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
746; CHECK-NEXT:    ret void
747;
748  %1 = tail call noalias i8* @malloc(i64 %S)
749  tail call void @no_sync_func(i8* %1)
750  tail call void @free(i8* %1)
751  ret void
752}
753
754define void @test16a(i8 %v, i8** %P) {
755; IS________OPM-LABEL: define {{[^@]+}}@test16a
756; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) {
757; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
758; IS________OPM-NEXT:    store i8 [[V]], i8* [[TMP1]], align 1
759; IS________OPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[TMP1]])
760; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull dereferenceable(1) [[TMP1]])
761; IS________OPM-NEXT:    ret void
762;
763; IS________NPM-LABEL: define {{[^@]+}}@test16a
764; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) {
765; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
766; IS________NPM-NEXT:    store i8 [[V]], i8* [[DOTH2S]], align 1
767; IS________NPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[DOTH2S]])
768; IS________NPM-NEXT:    ret void
769;
770  %1 = tail call noalias i8* @malloc(i64 4)
771  store i8 %v, i8* %1
772  tail call void @no_sync_func(i8* %1)
773  tail call void @free(i8* nonnull dereferenceable(1) %1)
774  ret void
775}
776
777define void @test16b(i8 %v, i8** %P) {
778; CHECK-LABEL: define {{[^@]+}}@test16b
779; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
780; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
781; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
782; CHECK-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
783; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
784; CHECK-NEXT:    ret void
785;
786  %1 = tail call noalias i8* @malloc(i64 4)
787  store i8* %1, i8** %P
788  tail call void @no_sync_func(i8* %1)
789  tail call void @free(i8* %1)
790  ret void
791}
792
793define void @test16c(i8 %v, i8** %P) {
794; IS________OPM-LABEL: define {{[^@]+}}@test16c
795; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
796; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
797; IS________OPM-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
798; IS________OPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) #[[ATTR9]]
799; IS________OPM-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
800; IS________OPM-NEXT:    ret void
801;
802; IS________NPM-LABEL: define {{[^@]+}}@test16c
803; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
804; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
805; IS________NPM-NEXT:    store i8* [[DOTH2S]], i8** [[P]], align 8
806; IS________NPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[DOTH2S]]) #[[ATTR10]]
807; IS________NPM-NEXT:    ret void
808;
809  %1 = tail call noalias i8* @malloc(i64 4)
810  store i8* %1, i8** %P
811  tail call void @no_sync_func(i8* %1) nounwind
812  tail call void @free(i8* %1)
813  ret void
814}
815
816define void @test16d(i8 %v, i8** %P) {
817; CHECK-LABEL: define {{[^@]+}}@test16d
818; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
819; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
820; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
821; CHECK-NEXT:    ret void
822;
823  %1 = tail call noalias i8* @malloc(i64 4)
824  store i8* %1, i8** %P
825  ret void
826}
827;.
828; IS________OPM: attributes #[[ATTR0:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) }
829; IS________OPM: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn }
830; IS________OPM: attributes #[[ATTR2:[0-9]+]] = { nofree nosync willreturn }
831; IS________OPM: attributes #[[ATTR3:[0-9]+]] = { nofree nounwind }
832; IS________OPM: attributes #[[ATTR4]] = { noreturn }
833; IS________OPM: attributes #[[ATTR5:[0-9]+]] = { allockind("free") }
834; IS________OPM: attributes #[[ATTR6:[0-9]+]] = { argmemonly nocallback nofree nosync nounwind willreturn }
835; IS________OPM: attributes #[[ATTR7:[0-9]+]] = { allockind("alloc,uninitialized,aligned") allocsize(1) }
836; IS________OPM: attributes #[[ATTR8:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) }
837; IS________OPM: attributes #[[ATTR9]] = { nounwind }
838;.
839; IS________NPM: attributes #[[ATTR0:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) }
840; IS________NPM: attributes #[[ATTR1:[0-9]+]] = { nounwind willreturn }
841; IS________NPM: attributes #[[ATTR2:[0-9]+]] = { nofree nosync willreturn }
842; IS________NPM: attributes #[[ATTR3:[0-9]+]] = { nofree nounwind }
843; IS________NPM: attributes #[[ATTR4]] = { noreturn }
844; IS________NPM: attributes #[[ATTR5:[0-9]+]] = { allockind("free") }
845; IS________NPM: attributes #[[ATTR6:[0-9]+]] = { argmemonly nocallback nofree nosync nounwind willreturn }
846; IS________NPM: attributes #[[ATTR7:[0-9]+]] = { allockind("alloc,uninitialized,aligned") allocsize(1) }
847; IS________NPM: attributes #[[ATTR8:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) }
848; IS________NPM: attributes #[[ATTR9:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn writeonly }
849; IS________NPM: attributes #[[ATTR10]] = { nounwind }
850;.
851