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