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