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=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)
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)
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]]) #[[ATTR5:[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]]) #[[ATTR5]]
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]]) #[[ATTR6:[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]]) #[[ATTR6]]
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, i64)
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)
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; IS________OPM-LABEL: define {{[^@]+}}@test4() {
270; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
271; IS________OPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[TMP1]])
272; IS________OPM-NEXT:    ret void
273;
274; IS________NPM-LABEL: define {{[^@]+}}@test4() {
275; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
276; IS________NPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[DOTH2S]])
277; IS________NPM-NEXT:    ret void
278;
279  %1 = tail call noalias i8* @malloc(i64 4)
280  tail call void @nofree_func(i8* %1)
281  ret void
282}
283
284; TEST 5 - not all exit paths have a call to free, but all uses of malloc
285; are in nofree functions and are not captured
286
287define void @test5(i32, i8* %p) {
288; IS________OPM-LABEL: define {{[^@]+}}@test5
289; IS________OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) {
290; IS________OPM-NEXT:    [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
291; IS________OPM-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0
292; IS________OPM-NEXT:    br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
293; IS________OPM:       4:
294; IS________OPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]])
295; IS________OPM-NEXT:    br label [[TMP6:%.*]]
296; IS________OPM:       5:
297; IS________OPM-NEXT:    tail call void @nofree_arg_only(i8* nocapture nofree [[TMP2]], i8* nocapture [[P]])
298; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
299; IS________OPM-NEXT:    br label [[TMP6]]
300; IS________OPM:       6:
301; IS________OPM-NEXT:    ret void
302;
303; IS________NPM-LABEL: define {{[^@]+}}@test5
304; IS________NPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) {
305; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
306; IS________NPM-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0
307; IS________NPM-NEXT:    br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
308; IS________NPM:       3:
309; IS________NPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[DOTH2S]])
310; IS________NPM-NEXT:    br label [[TMP5:%.*]]
311; IS________NPM:       4:
312; IS________NPM-NEXT:    tail call void @nofree_arg_only(i8* noalias nocapture nofree [[DOTH2S]], i8* nocapture [[P]])
313; IS________NPM-NEXT:    br label [[TMP5]]
314; IS________NPM:       5:
315; IS________NPM-NEXT:    ret void
316;
317  %2 = tail call noalias i8* @malloc(i64 4)
318  %3 = icmp eq i32 %0, 0
319  br i1 %3, label %5, label %4
320
3214:                                                ; preds = %1
322  tail call void @nofree_func(i8* %2)
323  br label %6
324
3255:                                                ; preds = %1
326  tail call void @nofree_arg_only(i8* %2, i8* %p)
327  tail call void @free(i8* %2)
328  br label %6
329
3306:                                                ; preds = %5, %4
331  ret void
332}
333
334; TEST 6 - all exit paths have a call to free
335
336define void @test6(i32) {
337; IS________OPM-LABEL: define {{[^@]+}}@test6
338; IS________OPM-SAME: (i32 [[TMP0:%.*]]) {
339; IS________OPM-NEXT:    [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
340; IS________OPM-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0
341; IS________OPM-NEXT:    br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]]
342; IS________OPM:       4:
343; IS________OPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]])
344; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
345; IS________OPM-NEXT:    br label [[TMP6:%.*]]
346; IS________OPM:       5:
347; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture [[TMP2]])
348; IS________OPM-NEXT:    br label [[TMP6]]
349; IS________OPM:       6:
350; IS________OPM-NEXT:    ret void
351;
352; IS________NPM-LABEL: define {{[^@]+}}@test6
353; IS________NPM-SAME: (i32 [[TMP0:%.*]]) {
354; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
355; IS________NPM-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0
356; IS________NPM-NEXT:    br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]]
357; IS________NPM:       3:
358; IS________NPM-NEXT:    tail call void @nofree_func(i8* noalias nocapture nofree [[DOTH2S]])
359; IS________NPM-NEXT:    br label [[TMP5:%.*]]
360; IS________NPM:       4:
361; IS________NPM-NEXT:    br label [[TMP5]]
362; IS________NPM:       5:
363; IS________NPM-NEXT:    ret void
364;
365  %2 = tail call noalias i8* @malloc(i64 4)
366  %3 = icmp eq i32 %0, 0
367  br i1 %3, label %5, label %4
368
3694:                                                ; preds = %1
370  tail call void @nofree_func(i8* %2)
371  tail call void @free(i8* %2)
372  br label %6
373
3745:                                                ; preds = %1
375  tail call void @free(i8* %2)
376  br label %6
377
3786:                                                ; preds = %5, %4
379  ret void
380}
381
382; TEST 7 - free is dead.
383
384define void @test7() {
385; IS________OPM-LABEL: define {{[^@]+}}@test7() {
386; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
387; IS________OPM-NEXT:    [[TMP2:%.*]] = tail call i32 @no_return_call() #[[ATTR3:[0-9]+]]
388; IS________OPM-NEXT:    unreachable
389;
390; IS________NPM-LABEL: define {{[^@]+}}@test7() {
391; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
392; IS________NPM-NEXT:    [[TMP1:%.*]] = tail call i32 @no_return_call() #[[ATTR3:[0-9]+]]
393; IS________NPM-NEXT:    unreachable
394;
395  %1 = tail call noalias i8* @malloc(i64 4)
396  tail call i32 @no_return_call()
397  tail call void @free(i8* %1)
398  ret void
399}
400
401; TEST 8 - Negative: bitcast pointer used in capture function
402
403define void @test8() {
404; CHECK-LABEL: define {{[^@]+}}@test8() {
405; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
406; CHECK-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
407; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
408; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
409; CHECK-NEXT:    tail call void @foo(i32* noundef align 4 [[TMP2]])
410; CHECK-NEXT:    tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
411; CHECK-NEXT:    ret void
412;
413  %1 = tail call noalias i8* @malloc(i64 4)
414  tail call void @no_sync_func(i8* %1)
415  %2 = bitcast i8* %1 to i32*
416  store i32 10, i32* %2
417  %3 = load i32, i32* %2
418  tail call void @foo(i32* %2)
419  tail call void @free(i8* %1)
420  ret void
421}
422
423; TEST 9 - FIXME: malloc should be converted.
424define void @test9() {
425; IS________OPM-LABEL: define {{[^@]+}}@test9() {
426; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
427; IS________OPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
428; IS________OPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
429; IS________OPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
430; IS________OPM-NEXT:    tail call void @foo_nounw(i32* nofree noundef align 4 [[TMP2]]) #[[ATTR5]]
431; IS________OPM-NEXT:    tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
432; IS________OPM-NEXT:    ret void
433;
434; IS________NPM-LABEL: define {{[^@]+}}@test9() {
435; IS________NPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
436; IS________NPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
437; IS________NPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
438; IS________NPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
439; IS________NPM-NEXT:    tail call void @foo_nounw(i32* nofree noundef align 4 [[TMP2]]) #[[ATTR6]]
440; IS________NPM-NEXT:    tail call void @free(i8* nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
441; IS________NPM-NEXT:    ret void
442;
443  %1 = tail call noalias i8* @malloc(i64 4)
444  tail call void @no_sync_func(i8* %1)
445  %2 = bitcast i8* %1 to i32*
446  store i32 10, i32* %2
447  %3 = load i32, i32* %2
448  tail call void @foo_nounw(i32* %2)
449  tail call void @free(i8* %1)
450  ret void
451}
452
453; TEST 10 - 1 malloc, 1 free
454
455define i32 @test10() {
456; IS________OPM-LABEL: define {{[^@]+}}@test10() {
457; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
458; IS________OPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
459; IS________OPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
460; IS________OPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
461; IS________OPM-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
462; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
463; IS________OPM-NEXT:    ret i32 [[TMP3]]
464;
465; IS________NPM-LABEL: define {{[^@]+}}@test10() {
466; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
467; IS________NPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]])
468; IS________NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[DOTH2S]] to i32*
469; IS________NPM-NEXT:    store i32 10, i32* [[TMP1]], align 4
470; IS________NPM-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
471; IS________NPM-NEXT:    ret i32 [[TMP2]]
472;
473  %1 = tail call noalias i8* @malloc(i64 4)
474  tail call void @no_sync_func(i8* %1)
475  %2 = bitcast i8* %1 to i32*
476  store i32 10, i32* %2
477  %3 = load i32, i32* %2
478  tail call void @free(i8* %1)
479  ret i32 %3
480}
481
482define i32 @test_lifetime() {
483; IS________OPM-LABEL: define {{[^@]+}}@test_lifetime() {
484; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
485; IS________OPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
486; IS________OPM-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[TMP1]])
487; IS________OPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
488; IS________OPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
489; IS________OPM-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
490; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
491; IS________OPM-NEXT:    ret i32 [[TMP3]]
492;
493; IS________NPM-LABEL: define {{[^@]+}}@test_lifetime() {
494; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
495; IS________NPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[DOTH2S]])
496; IS________NPM-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[DOTH2S]])
497; IS________NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[DOTH2S]] to i32*
498; IS________NPM-NEXT:    store i32 10, i32* [[TMP1]], align 4
499; IS________NPM-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
500; IS________NPM-NEXT:    ret i32 [[TMP2]]
501;
502  %1 = tail call noalias i8* @malloc(i64 4)
503  tail call void @no_sync_func(i8* %1)
504  call void @llvm.lifetime.start.p0i8(i64 4, i8* %1)
505  %2 = bitcast i8* %1 to i32*
506  store i32 10, i32* %2
507  %3 = load i32, i32* %2
508  tail call void @free(i8* %1)
509  ret i32 %3
510}
511
512; TEST 11
513
514define void @test11() {
515; IS________OPM-LABEL: define {{[^@]+}}@test11() {
516; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
517; IS________OPM-NEXT:    tail call void @sync_will_return(i8* [[TMP1]]) #[[ATTR5]]
518; IS________OPM-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
519; IS________OPM-NEXT:    ret void
520;
521; IS________NPM-LABEL: define {{[^@]+}}@test11() {
522; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
523; IS________NPM-NEXT:    tail call void @sync_will_return(i8* [[DOTH2S]]) #[[ATTR6]]
524; IS________NPM-NEXT:    ret void
525;
526  %1 = tail call noalias i8* @malloc(i64 4)
527  tail call void @sync_will_return(i8* %1)
528  tail call void @free(i8* %1)
529  ret void
530}
531
532; TEST 12
533define i32 @irreducible_cfg(i32 %0) {
534; IS________OPM-LABEL: define {{[^@]+}}@irreducible_cfg
535; IS________OPM-SAME: (i32 [[TMP0:%.*]]) {
536; IS________OPM-NEXT:    [[TMP2:%.*]] = call noalias i8* @malloc(i64 noundef 4)
537; IS________OPM-NEXT:    [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32*
538; IS________OPM-NEXT:    store i32 10, i32* [[TMP3]], align 4
539; IS________OPM-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1
540; IS________OPM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]]
541; IS________OPM:       5:
542; IS________OPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5
543; IS________OPM-NEXT:    br label [[TMP13:%.*]]
544; IS________OPM:       7:
545; IS________OPM-NEXT:    br label [[TMP8:%.*]]
546; IS________OPM:       8:
547; IS________OPM-NEXT:    [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ]
548; IS________OPM-NEXT:    [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4
549; IS________OPM-NEXT:    [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1
550; IS________OPM-NEXT:    store i32 [[TMP10]], i32* [[TMP3]], align 4
551; IS________OPM-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0
552; IS________OPM-NEXT:    br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]]
553; IS________OPM:       12:
554; IS________OPM-NEXT:    br label [[TMP13]]
555; IS________OPM:       13:
556; IS________OPM-NEXT:    [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ]
557; IS________OPM-NEXT:    [[TMP14]] = add nsw i32 [[DOT1]], 1
558; IS________OPM-NEXT:    br label [[TMP8]]
559; IS________OPM:       15:
560; IS________OPM-NEXT:    [[TMP16:%.*]] = load i32, i32* [[TMP3]], align 4
561; IS________OPM-NEXT:    [[TMP17:%.*]] = bitcast i32* [[TMP3]] to i8*
562; IS________OPM-NEXT:    call void @free(i8* nocapture noundef [[TMP17]])
563; IS________OPM-NEXT:    [[TMP18:%.*]] = load i32, i32* [[TMP3]], align 4
564; IS________OPM-NEXT:    ret i32 [[TMP18]]
565;
566; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg
567; IS________NPM-SAME: (i32 [[TMP0:%.*]]) {
568; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
569; IS________NPM-NEXT:    [[TMP2:%.*]] = bitcast i8* [[DOTH2S]] to i32*
570; IS________NPM-NEXT:    store i32 10, i32* [[TMP2]], align 4
571; IS________NPM-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 1
572; IS________NPM-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
573; IS________NPM:       4:
574; IS________NPM-NEXT:    [[TMP5:%.*]] = add nsw i32 [[TMP0]], 5
575; IS________NPM-NEXT:    br label [[TMP12:%.*]]
576; IS________NPM:       6:
577; IS________NPM-NEXT:    br label [[TMP7:%.*]]
578; IS________NPM:       7:
579; IS________NPM-NEXT:    [[DOT0:%.*]] = phi i32 [ [[TMP13:%.*]], [[TMP12]] ], [ 1, [[TMP6]] ]
580; IS________NPM-NEXT:    [[TMP8:%.*]] = load i32, i32* [[TMP2]], align 4
581; IS________NPM-NEXT:    [[TMP9:%.*]] = add nsw i32 [[TMP8]], -1
582; IS________NPM-NEXT:    store i32 [[TMP9]], i32* [[TMP2]], align 4
583; IS________NPM-NEXT:    [[TMP10:%.*]] = icmp ne i32 [[TMP8]], 0
584; IS________NPM-NEXT:    br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP14:%.*]]
585; IS________NPM:       11:
586; IS________NPM-NEXT:    br label [[TMP12]]
587; IS________NPM:       12:
588; IS________NPM-NEXT:    [[DOT1:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[DOT0]], [[TMP11]] ]
589; IS________NPM-NEXT:    [[TMP13]] = add nsw i32 [[DOT1]], 1
590; IS________NPM-NEXT:    br label [[TMP7]]
591; IS________NPM:       14:
592; IS________NPM-NEXT:    [[TMP15:%.*]] = load i32, i32* [[TMP2]], align 4
593; IS________NPM-NEXT:    ret i32 [[TMP15]]
594;
595  %2 = call noalias i8* @malloc(i64 4)
596  %3 = bitcast i8* %2 to i32*
597  store i32 10, i32* %3, align 4
598  %4 = icmp eq i32 %0, 1
599  br i1 %4, label %5, label %7
600
6015:                                                ; preds = %1
602  %6 = add nsw i32 %0, 5
603  br label %13
604
6057:                                                ; preds = %1
606  br label %8
607
6088:                                                ; preds = %13, %7
609  %.0 = phi i32 [ %14, %13 ], [ 1, %7 ]
610  %9 = load i32, i32* %3, align 4
611  %10 = add nsw i32 %9, -1
612  store i32 %10, i32* %3, align 4
613  %11 = icmp ne i32 %9, 0
614  br i1 %11, label %12, label %15
615
61612:                                               ; preds = %8
617  br label %13
618
61913:                                               ; preds = %12, %5
620  %.1 = phi i32 [ %6, %5 ], [ %.0, %12 ]
621  %14 = add nsw i32 %.1, 1
622  br label %8
623
62415:                                               ; preds = %8
625  %16 = load i32, i32* %3, align 4
626  %17 = bitcast i32* %3 to i8*
627  call void @free(i8* %17)
628  %18 = load i32, i32* %3, align 4
629  ret i32 %18
630}
631
632
633define i32 @malloc_in_loop(i32 %0) {
634; IS________OPM-LABEL: define {{[^@]+}}@malloc_in_loop
635; IS________OPM-SAME: (i32 [[TMP0:%.*]]) {
636; IS________OPM-NEXT:    [[TMP2:%.*]] = alloca i32, align 4
637; IS________OPM-NEXT:    [[TMP3:%.*]] = alloca i32*, align 8
638; IS________OPM-NEXT:    store i32 [[TMP0]], i32* [[TMP2]], align 4
639; IS________OPM-NEXT:    br label [[TMP4:%.*]]
640; IS________OPM:       4:
641; IS________OPM-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP2]], align 4
642; IS________OPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP5]], -1
643; IS________OPM-NEXT:    store i32 [[TMP6]], i32* [[TMP2]], align 4
644; IS________OPM-NEXT:    [[TMP7:%.*]] = icmp sgt i32 [[TMP6]], 0
645; IS________OPM-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP11:%.*]]
646; IS________OPM:       8:
647; IS________OPM-NEXT:    [[TMP9:%.*]] = call noalias i8* @malloc(i64 noundef 4)
648; IS________OPM-NEXT:    [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32*
649; IS________OPM-NEXT:    br label [[TMP4]]
650; IS________OPM:       11:
651; IS________OPM-NEXT:    ret i32 5
652;
653; IS________NPM-LABEL: define {{[^@]+}}@malloc_in_loop
654; IS________NPM-SAME: (i32 [[TMP0:%.*]]) {
655; IS________NPM-NEXT:    [[TMP2:%.*]] = alloca i32, align 4
656; IS________NPM-NEXT:    [[TMP3:%.*]] = alloca i32*, align 8
657; IS________NPM-NEXT:    store i32 [[TMP0]], i32* [[TMP2]], align 4
658; IS________NPM-NEXT:    br label [[TMP4:%.*]]
659; IS________NPM:       4:
660; IS________NPM-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP2]], align 4
661; IS________NPM-NEXT:    [[TMP6:%.*]] = add nsw i32 [[TMP5]], -1
662; IS________NPM-NEXT:    store i32 [[TMP6]], i32* [[TMP2]], align 4
663; IS________NPM-NEXT:    [[TMP7:%.*]] = icmp sgt i32 [[TMP6]], 0
664; IS________NPM-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP10:%.*]]
665; IS________NPM:       8:
666; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
667; IS________NPM-NEXT:    [[TMP9:%.*]] = bitcast i8* [[DOTH2S]] to i32*
668; IS________NPM-NEXT:    br label [[TMP4]]
669; IS________NPM:       10:
670; IS________NPM-NEXT:    ret i32 5
671;
672  %2 = alloca i32, align 4
673  %3 = alloca i32*, align 8
674  store i32 %0, i32* %2, align 4
675  br label %4
676
6774:                                                ; preds = %8, %1
678  %5 = load i32, i32* %2, align 4
679  %6 = add nsw i32 %5, -1
680  store i32 %6, i32* %2, align 4
681  %7 = icmp sgt i32 %6, 0
682  br i1 %7, label %8, label %11
683
6848:                                                ; preds = %4
685  %9 = call noalias i8* @malloc(i64 4)
686  %10 = bitcast i8* %9 to i32*
687  store i32 1, i32* %10, align 8
688  br label %4
689
69011:                                               ; preds = %4
691  ret i32 5
692}
693
694; Malloc/Calloc too large
695define i32 @test13() {
696; CHECK-LABEL: define {{[^@]+}}@test13() {
697; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 256)
698; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
699; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
700; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
701; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
702; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
703; CHECK-NEXT:    ret i32 [[TMP3]]
704;
705  %1 = tail call noalias i8* @malloc(i64 256)
706  tail call void @no_sync_func(i8* %1)
707  %2 = bitcast i8* %1 to i32*
708  store i32 10, i32* %2
709  %3 = load i32, i32* %2
710  tail call void @free(i8* %1)
711  ret i32 %3
712}
713
714define i32 @test_sle() {
715; CHECK-LABEL: define {{[^@]+}}@test_sle() {
716; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef -1)
717; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
718; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
719; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
720; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
721; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
722; CHECK-NEXT:    ret i32 [[TMP3]]
723;
724  %1 = tail call noalias i8* @malloc(i64 -1)
725  tail call void @no_sync_func(i8* %1)
726  %2 = bitcast i8* %1 to i32*
727  store i32 10, i32* %2
728  %3 = load i32, i32* %2
729  tail call void @free(i8* %1)
730  ret i32 %3
731}
732
733define i32 @test_overflow() {
734; CHECK-LABEL: define {{[^@]+}}@test_overflow() {
735; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 65537, i64 noundef 65537)
736; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
737; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
738; CHECK-NEXT:    store i32 10, i32* [[TMP2]], align 4
739; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
740; CHECK-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull align 4 dereferenceable(4) [[TMP1]])
741; CHECK-NEXT:    ret i32 [[TMP3]]
742;
743  %1 = tail call noalias i8* @calloc(i64 65537, i64 65537)
744  tail call void @no_sync_func(i8* %1)
745  %2 = bitcast i8* %1 to i32*
746  store i32 10, i32* %2
747  %3 = load i32, i32* %2
748  tail call void @free(i8* %1)
749  ret i32 %3
750}
751
752define void @test14() {
753; CHECK-LABEL: define {{[^@]+}}@test14() {
754; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 noundef 64, i64 noundef 4)
755; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
756; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
757; CHECK-NEXT:    ret void
758;
759  %1 = tail call noalias i8* @calloc(i64 64, i64 4)
760  tail call void @no_sync_func(i8* %1)
761  tail call void @free(i8* %1)
762  ret void
763}
764
765define void @test15(i64 %S) {
766; CHECK-LABEL: define {{[^@]+}}@test15
767; CHECK-SAME: (i64 [[S:%.*]]) {
768; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 [[S]])
769; CHECK-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
770; CHECK-NEXT:    tail call void @free(i8* noalias nocapture [[TMP1]])
771; CHECK-NEXT:    ret void
772;
773  %1 = tail call noalias i8* @malloc(i64 %S)
774  tail call void @no_sync_func(i8* %1)
775  tail call void @free(i8* %1)
776  ret void
777}
778
779define void @test16a(i8 %v, i8** %P) {
780; IS________OPM-LABEL: define {{[^@]+}}@test16a
781; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) {
782; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
783; IS________OPM-NEXT:    store i8 [[V]], i8* [[TMP1]], align 1
784; IS________OPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[TMP1]])
785; IS________OPM-NEXT:    tail call void @free(i8* noalias nocapture noundef nonnull dereferenceable(1) [[TMP1]])
786; IS________OPM-NEXT:    ret void
787;
788; IS________NPM-LABEL: define {{[^@]+}}@test16a
789; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) {
790; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
791; IS________NPM-NEXT:    store i8 [[V]], i8* [[DOTH2S]], align 1
792; IS________NPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[DOTH2S]])
793; IS________NPM-NEXT:    ret void
794;
795  %1 = tail call noalias i8* @malloc(i64 4)
796  store i8 %v, i8* %1
797  tail call void @no_sync_func(i8* %1)
798  tail call void @free(i8* nonnull dereferenceable(1) %1)
799  ret void
800}
801
802define void @test16b(i8 %v, i8** %P) {
803; CHECK-LABEL: define {{[^@]+}}@test16b
804; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
805; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
806; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
807; CHECK-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]])
808; CHECK-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
809; CHECK-NEXT:    ret void
810;
811  %1 = tail call noalias i8* @malloc(i64 4)
812  store i8* %1, i8** %P
813  tail call void @no_sync_func(i8* %1)
814  tail call void @free(i8* %1)
815  ret void
816}
817
818define void @test16c(i8 %v, i8** %P) {
819; IS________OPM-LABEL: define {{[^@]+}}@test16c
820; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
821; IS________OPM-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
822; IS________OPM-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
823; IS________OPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) #[[ATTR5]]
824; IS________OPM-NEXT:    tail call void @free(i8* nocapture [[TMP1]])
825; IS________OPM-NEXT:    ret void
826;
827; IS________NPM-LABEL: define {{[^@]+}}@test16c
828; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
829; IS________NPM-NEXT:    [[DOTH2S:%.*]] = alloca i8, i64 4, align 1
830; IS________NPM-NEXT:    store i8* [[DOTH2S]], i8** [[P]], align 8
831; IS________NPM-NEXT:    tail call void @no_sync_func(i8* nocapture nofree [[DOTH2S]]) #[[ATTR6]]
832; IS________NPM-NEXT:    ret void
833;
834  %1 = tail call noalias i8* @malloc(i64 4)
835  store i8* %1, i8** %P
836  tail call void @no_sync_func(i8* %1) nounwind
837  tail call void @free(i8* %1)
838  ret void
839}
840
841define void @test16d(i8 %v, i8** %P) {
842; CHECK-LABEL: define {{[^@]+}}@test16d
843; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture nofree writeonly [[P:%.*]]) {
844; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 noundef 4)
845; CHECK-NEXT:    store i8* [[TMP1]], i8** [[P]], align 8
846; CHECK-NEXT:    ret void
847;
848  %1 = tail call noalias i8* @malloc(i64 4)
849  store i8* %1, i8** %P
850  ret void
851}
852;.
853; IS________OPM: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn }
854; IS________OPM: attributes #[[ATTR1:[0-9]+]] = { nofree nosync willreturn }
855; IS________OPM: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind }
856; IS________OPM: attributes #[[ATTR3]] = { noreturn }
857; IS________OPM: attributes #[[ATTR4:[0-9]+]] = { argmemonly nocallback nofree nosync nounwind willreturn }
858; IS________OPM: attributes #[[ATTR5]] = { nounwind }
859;.
860; IS________NPM: attributes #[[ATTR0:[0-9]+]] = { nounwind willreturn }
861; IS________NPM: attributes #[[ATTR1:[0-9]+]] = { nofree nosync willreturn }
862; IS________NPM: attributes #[[ATTR2:[0-9]+]] = { nofree nounwind }
863; IS________NPM: attributes #[[ATTR3]] = { noreturn }
864; IS________NPM: attributes #[[ATTR4:[0-9]+]] = { argmemonly nocallback nofree nosync nounwind willreturn }
865; IS________NPM: attributes #[[ATTR5:[0-9]+]] = { argmemonly nofree nounwind willreturn writeonly }
866; IS________NPM: attributes #[[ATTR6]] = { nounwind }
867;.
868