xref: /llvm-project/llvm/test/Transforms/Attributor/noalias.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
4
5; TEST 1 - negative.
6
7; void *G;
8; void *foo(){
9;   void *V = malloc(4);
10;   G = V;
11;   return V;
12; }
13
14@G = external global ptr
15
16;.
17; CHECK: @G = external global ptr
18; CHECK: @alias_of_p = external global ptr
19;.
20define ptr @foo() {
21; CHECK-LABEL: define {{[^@]+}}@foo() {
22; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
23; CHECK-NEXT:    store ptr [[TMP1]], ptr @G, align 8
24; CHECK-NEXT:    ret ptr [[TMP1]]
25;
26  %1 = tail call noalias ptr @malloc(i64 4)
27  store ptr %1, ptr @G, align 8
28  ret ptr %1
29}
30
31declare noalias ptr @malloc(i64)
32
33; TEST 2
34; call noalias function in return instruction.
35
36define ptr @return_noalias(){
37; CHECK-LABEL: define {{[^@]+}}@return_noalias() {
38; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
39; CHECK-NEXT:    ret ptr [[TMP1]]
40;
41  %1 = tail call noalias ptr @malloc(i64 4)
42  ret ptr %1
43}
44
45define void @nocapture(ptr %a){
46; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
47; CHECK-LABEL: define {{[^@]+}}@nocapture
48; CHECK-SAME: (ptr nofree readnone captures(none) [[A:%.*]]) #[[ATTR0:[0-9]+]] {
49; CHECK-NEXT:    ret void
50;
51  ret void
52}
53
54define ptr @return_noalias_looks_like_capture(){
55; CHECK-LABEL: define {{[^@]+}}@return_noalias_looks_like_capture() {
56; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
57; CHECK-NEXT:    ret ptr [[TMP1]]
58;
59  %1 = tail call noalias ptr @malloc(i64 4)
60  call void @nocapture(ptr %1)
61  ret ptr %1
62}
63
64define ptr @return_noalias_casted(){
65; CHECK-LABEL: define {{[^@]+}}@return_noalias_casted() {
66; CHECK-NEXT:    [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
67; CHECK-NEXT:    ret ptr [[TMP1]]
68;
69  %1 = tail call noalias ptr @malloc(i64 4)
70  ret ptr %1
71}
72
73declare ptr @alias()
74
75; TEST 3
76define ptr @call_alias(){
77; CHECK-LABEL: define {{[^@]+}}@call_alias() {
78; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @alias()
79; CHECK-NEXT:    ret ptr [[TMP1]]
80;
81  %1 = tail call ptr @alias()
82  ret ptr %1
83}
84
85; TEST 4
86; void *baz();
87; void *foo(int a);
88;
89; void *bar()  {
90;   foo(0);
91;    return baz();
92; }
93;
94; void *foo(int a)  {
95;   if (a)
96;   bar();
97;   return malloc(4);
98; }
99
100define ptr @bar() nounwind uwtable {
101; TUNIT: Function Attrs: nounwind uwtable
102; TUNIT-LABEL: define {{[^@]+}}@bar
103; TUNIT-SAME: () #[[ATTR1:[0-9]+]] {
104; TUNIT-NEXT:    [[TMP1:%.*]] = tail call ptr (...) @baz() #[[ATTR2:[0-9]+]]
105; TUNIT-NEXT:    ret ptr [[TMP1]]
106;
107; CGSCC: Function Attrs: nounwind uwtable
108; CGSCC-LABEL: define {{[^@]+}}@bar
109; CGSCC-SAME: () #[[ATTR1:[0-9]+]] {
110; CGSCC-NEXT:    [[TMP1:%.*]] = tail call ptr (...) @baz() #[[ATTR3:[0-9]+]]
111; CGSCC-NEXT:    ret ptr [[TMP1]]
112;
113  %1 = tail call ptr (...) @baz()
114  ret ptr %1
115}
116
117define ptr @foo1(i32 %0) nounwind uwtable {
118; TUNIT: Function Attrs: nounwind uwtable
119; TUNIT-LABEL: define {{[^@]+}}@foo1
120; TUNIT-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
121; TUNIT-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0
122; TUNIT-NEXT:    br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
123; TUNIT:       3:
124; TUNIT-NEXT:    [[TMP4:%.*]] = tail call ptr (...) @baz() #[[ATTR2]]
125; TUNIT-NEXT:    br label [[TMP5]]
126; TUNIT:       5:
127; TUNIT-NEXT:    [[TMP6:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
128; TUNIT-NEXT:    ret ptr [[TMP6]]
129;
130; CGSCC: Function Attrs: nounwind uwtable
131; CGSCC-LABEL: define {{[^@]+}}@foo1
132; CGSCC-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
133; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0
134; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
135; CGSCC:       3:
136; CGSCC-NEXT:    [[TMP4:%.*]] = tail call ptr (...) @baz() #[[ATTR3]]
137; CGSCC-NEXT:    br label [[TMP5]]
138; CGSCC:       5:
139; CGSCC-NEXT:    [[TMP6:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
140; CGSCC-NEXT:    ret ptr [[TMP6]]
141;
142  %2 = icmp eq i32 %0, 0
143  br i1 %2, label %5, label %3
144
1453:                                                ; preds = %1
146  %4 = tail call ptr (...) @baz()
147  br label %5
148
1495:                                                ; preds = %1, %3
150  %6 = tail call noalias ptr @malloc(i64 4)
151  ret ptr %6
152}
153
154declare ptr @baz(...) nounwind uwtable
155
156; TEST 5
157
158; Returning global pointer. Should not be noalias.
159define ptr @getter() {
160; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
161; CHECK-LABEL: define {{[^@]+}}@getter
162; CHECK-SAME: () #[[ATTR0]] {
163; CHECK-NEXT:    ret ptr @G
164;
165  ret ptr @G
166}
167
168; Returning global pointer. Should not be noalias.
169define ptr @calle1(){
170; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
171; TUNIT-LABEL: define {{[^@]+}}@calle1
172; TUNIT-SAME: () #[[ATTR0]] {
173; TUNIT-NEXT:    ret ptr @G
174;
175; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
176; CGSCC-LABEL: define {{[^@]+}}@calle1
177; CGSCC-SAME: () #[[ATTR2:[0-9]+]] {
178; CGSCC-NEXT:    [[TMP1:%.*]] = call noundef nonnull align 8 dereferenceable(8) ptr @getter() #[[ATTR12:[0-9]+]]
179; CGSCC-NEXT:    ret ptr [[TMP1]]
180;
181  %1 = call ptr @getter()
182  ret ptr %1
183}
184
185; TEST 6
186declare noalias ptr @strdup(ptr nocapture) nounwind
187
188define ptr @test6() nounwind uwtable ssp {
189; TUNIT: Function Attrs: nounwind ssp uwtable
190; TUNIT-LABEL: define {{[^@]+}}@test6
191; TUNIT-SAME: () #[[ATTR3:[0-9]+]] {
192; TUNIT-NEXT:    [[X:%.*]] = alloca [2 x i8], align 1
193; TUNIT-NEXT:    store i8 97, ptr [[X]], align 1
194; TUNIT-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8], ptr [[X]], i64 0, i64 1
195; TUNIT-NEXT:    store i8 0, ptr [[ARRAYIDX1]], align 1
196; TUNIT-NEXT:    [[CALL:%.*]] = call noalias ptr @strdup(ptr noalias noundef nonnull captures(none) dereferenceable(2) [[X]]) #[[ATTR2]]
197; TUNIT-NEXT:    ret ptr [[CALL]]
198;
199; CGSCC: Function Attrs: nounwind ssp uwtable
200; CGSCC-LABEL: define {{[^@]+}}@test6
201; CGSCC-SAME: () #[[ATTR4:[0-9]+]] {
202; CGSCC-NEXT:    [[X:%.*]] = alloca [2 x i8], align 1
203; CGSCC-NEXT:    store i8 97, ptr [[X]], align 1
204; CGSCC-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8], ptr [[X]], i64 0, i64 1
205; CGSCC-NEXT:    store i8 0, ptr [[ARRAYIDX1]], align 1
206; CGSCC-NEXT:    [[CALL:%.*]] = call noalias ptr @strdup(ptr noalias noundef nonnull captures(none) dereferenceable(2) [[X]]) #[[ATTR3]]
207; CGSCC-NEXT:    ret ptr [[CALL]]
208;
209  %x = alloca [2 x i8], align 1
210  store i8 97, ptr %x, align 1
211  %arrayidx1 = getelementptr inbounds [2 x i8], ptr %x, i64 0, i64 1
212  store i8 0, ptr %arrayidx1, align 1
213  %call = call noalias ptr @strdup(ptr %x) nounwind
214  ret ptr %call
215}
216
217; TEST 7
218
219define ptr @test7() nounwind {
220; TUNIT: Function Attrs: nounwind
221; TUNIT-LABEL: define {{[^@]+}}@test7
222; TUNIT-SAME: () #[[ATTR2]] {
223; TUNIT-NEXT:  entry:
224; TUNIT-NEXT:    [[A:%.*]] = call noalias ptr @malloc(i64 noundef 4) #[[ATTR2]]
225; TUNIT-NEXT:    [[TOBOOL:%.*]] = icmp eq ptr [[A]], null
226; TUNIT-NEXT:    br i1 [[TOBOOL]], label [[RETURN:%.*]], label [[IF_END:%.*]]
227; TUNIT:       if.end:
228; TUNIT-NEXT:    store i8 7, ptr [[A]], align 1
229; TUNIT-NEXT:    br label [[RETURN]]
230; TUNIT:       return:
231; TUNIT-NEXT:    [[RETVAL_0:%.*]] = phi ptr [ [[A]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ]
232; TUNIT-NEXT:    ret ptr [[RETVAL_0]]
233;
234; CGSCC: Function Attrs: nounwind
235; CGSCC-LABEL: define {{[^@]+}}@test7
236; CGSCC-SAME: () #[[ATTR3]] {
237; CGSCC-NEXT:  entry:
238; CGSCC-NEXT:    [[A:%.*]] = call noalias ptr @malloc(i64 noundef 4) #[[ATTR3]]
239; CGSCC-NEXT:    [[TOBOOL:%.*]] = icmp eq ptr [[A]], null
240; CGSCC-NEXT:    br i1 [[TOBOOL]], label [[RETURN:%.*]], label [[IF_END:%.*]]
241; CGSCC:       if.end:
242; CGSCC-NEXT:    store i8 7, ptr [[A]], align 1
243; CGSCC-NEXT:    br label [[RETURN]]
244; CGSCC:       return:
245; CGSCC-NEXT:    [[RETVAL_0:%.*]] = phi ptr [ [[A]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ]
246; CGSCC-NEXT:    ret ptr [[RETVAL_0]]
247;
248entry:
249  %A = call noalias ptr @malloc(i64 4) nounwind
250  %tobool = icmp eq ptr %A, null
251  br i1 %tobool, label %return, label %if.end
252
253if.end:
254  store i8 7, ptr %A
255  br label %return
256
257return:
258  %retval.0 = phi ptr [ %A, %if.end ], [ null, %entry ]
259  ret ptr %retval.0
260}
261
262; TEST 8
263
264define ptr @test8(ptr %0) nounwind uwtable {
265; CHECK: Function Attrs: nounwind uwtable
266; CHECK-LABEL: define {{[^@]+}}@test8
267; CHECK-SAME: (ptr [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] {
268; CHECK-NEXT:    [[TMP2:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
269; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne ptr [[TMP0]], null
270; CHECK-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
271; CHECK:       4:
272; CHECK-NEXT:    store i8 10, ptr [[TMP2]], align 1
273; CHECK-NEXT:    br label [[TMP5]]
274; CHECK:       5:
275; CHECK-NEXT:    ret ptr [[TMP2]]
276;
277  %2 = tail call noalias ptr @malloc(i64 4)
278  %3 = icmp ne ptr %0, null
279  br i1 %3, label %4, label %5
280
2814:                                                ; preds = %1
282  store i8 10, ptr %2
283  br label %5
284
2855:                                                ; preds = %1, %4
286  ret ptr %2
287}
288
289; TEST 9
290; Simple Argument Test
291declare void @use_i8(ptr nocapture)
292define internal void @test9a(ptr %a, ptr %b) {
293; TUNIT: Function Attrs: memory(readwrite, argmem: none)
294; TUNIT-LABEL: define {{[^@]+}}@test9a
295; TUNIT-SAME: () #[[ATTR4:[0-9]+]] {
296; TUNIT-NEXT:    call void @use_i8(ptr noundef align 4294967296 null)
297; TUNIT-NEXT:    ret void
298;
299; CGSCC: Function Attrs: memory(readwrite, argmem: none)
300; CGSCC-LABEL: define {{[^@]+}}@test9a
301; CGSCC-SAME: () #[[ATTR5:[0-9]+]] {
302; CGSCC-NEXT:    call void @use_i8(ptr noundef align 4294967296 null)
303; CGSCC-NEXT:    ret void
304;
305  call void @use_i8(ptr null)
306  ret void
307}
308define internal void @test9b(ptr %a, ptr %b) {
309; FIXME: %b should be noalias
310; CHECK-LABEL: define {{[^@]+}}@test9b
311; CHECK-SAME: (ptr noalias captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) {
312; CHECK-NEXT:    call void @use_i8(ptr noalias captures(none) [[A]])
313; CHECK-NEXT:    call void @use_i8(ptr captures(none) [[B]])
314; CHECK-NEXT:    ret void
315;
316  call void @use_i8(ptr %a)
317  call void @use_i8(ptr %b)
318  ret void
319}
320define internal void @test9c(ptr %a, ptr %b, ptr %c) {
321; CHECK-LABEL: define {{[^@]+}}@test9c
322; CHECK-SAME: (ptr noalias captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]], ptr captures(none) [[C:%.*]]) {
323; CHECK-NEXT:    call void @use_i8(ptr noalias captures(none) [[A]])
324; CHECK-NEXT:    call void @use_i8(ptr captures(none) [[B]])
325; CHECK-NEXT:    call void @use_i8(ptr captures(none) [[C]])
326; CHECK-NEXT:    ret void
327;
328  call void @use_i8(ptr %a)
329  call void @use_i8(ptr %b)
330  call void @use_i8(ptr %c)
331  ret void
332}
333define void @test9_helper(ptr %a, ptr %b) {
334; CHECK-LABEL: define {{[^@]+}}@test9_helper
335; CHECK-SAME: (ptr captures(none) [[A:%.*]], ptr captures(none) [[B:%.*]]) {
336; CHECK-NEXT:    tail call void @test9a()
337; CHECK-NEXT:    tail call void @test9a()
338; CHECK-NEXT:    tail call void @test9b(ptr noalias captures(none) [[A]], ptr captures(none) [[B]])
339; CHECK-NEXT:    tail call void @test9b(ptr noalias captures(none) [[B]], ptr noalias captures(none) [[A]])
340; CHECK-NEXT:    tail call void @test9c(ptr noalias captures(none) [[A]], ptr captures(none) [[B]], ptr captures(none) [[B]])
341; CHECK-NEXT:    tail call void @test9c(ptr noalias captures(none) [[B]], ptr noalias captures(none) [[A]], ptr noalias captures(none) [[A]])
342; CHECK-NEXT:    ret void
343;
344  tail call void @test9a(ptr noalias %a, ptr %b)
345  tail call void @test9a(ptr noalias %b, ptr noalias %a)
346  tail call void @test9b(ptr noalias %a, ptr %b)
347  tail call void @test9b(ptr noalias %b, ptr noalias %a)
348  tail call void @test9c(ptr noalias %a, ptr %b, ptr %b)
349  tail call void @test9c(ptr noalias %b, ptr noalias %a, ptr noalias %a)
350  ret void
351}
352
353
354; TEST 10
355; Simple CallSite Test
356
357declare void @test10_helper_1(ptr %a)
358define void @test10_helper_2(ptr noalias %a) {
359; CHECK-LABEL: define {{[^@]+}}@test10_helper_2
360; CHECK-SAME: (ptr noalias [[A:%.*]]) {
361; CHECK-NEXT:    tail call void @test10_helper_1(ptr [[A]])
362; CHECK-NEXT:    ret void
363;
364  tail call void @test10_helper_1(ptr %a)
365  ret void
366}
367define void @test10(ptr noalias %a) {
368; CHECK-LABEL: define {{[^@]+}}@test10
369; CHECK-SAME: (ptr noalias [[A:%.*]]) {
370; CHECK-NEXT:    tail call void @test10_helper_1(ptr [[A]])
371; CHECK-NEXT:    tail call void @test10_helper_2(ptr [[A]])
372; CHECK-NEXT:    ret void
373;
374; FIXME: missing noalias
375  tail call void @test10_helper_1(ptr %a)
376
377  tail call void @test10_helper_2(ptr %a)
378  ret void
379}
380
381; TEST 11
382; CallSite Test
383
384declare void @test11_helper(ptr %a, ptr %b)
385define void @test11(ptr noalias %a) {
386; CHECK-LABEL: define {{[^@]+}}@test11
387; CHECK-SAME: (ptr noalias [[A:%.*]]) {
388; CHECK-NEXT:    tail call void @test11_helper(ptr [[A]], ptr [[A]])
389; CHECK-NEXT:    ret void
390;
391  tail call void @test11_helper(ptr %a, ptr %a)
392  ret void
393}
394
395
396; TEST 12
397; CallSite Argument
398declare void @use_nocapture(ptr nocapture)
399declare void @use(ptr)
400define void @test12_1() {
401; CHECK-LABEL: define {{[^@]+}}@test12_1() {
402; CHECK-NEXT:    [[A:%.*]] = alloca i8, align 4
403; CHECK-NEXT:    [[B:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
404; CHECK-NEXT:    tail call void @use_nocapture(ptr noalias noundef nonnull align 4 captures(none) dereferenceable(1) [[A]])
405; CHECK-NEXT:    tail call void @use_nocapture(ptr noalias noundef nonnull align 4 captures(none) dereferenceable(1) [[A]])
406; CHECK-NEXT:    tail call void @use_nocapture(ptr noalias captures(none) [[B]])
407; CHECK-NEXT:    tail call void @use_nocapture(ptr noalias captures(none) [[B]])
408; CHECK-NEXT:    ret void
409;
410  %A = alloca i8, align 4
411  %B = tail call noalias ptr @malloc(i64 4)
412  tail call void @use_nocapture(ptr %A)
413  tail call void @use_nocapture(ptr %A)
414  tail call void @use_nocapture(ptr %B)
415  tail call void @use_nocapture(ptr %B)
416  ret void
417}
418
419define void @test12_2(){
420; CHECK-LABEL: define {{[^@]+}}@test12_2() {
421; CHECK-NEXT:    [[A:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
422; CHECK-NEXT:    tail call void @use_nocapture(ptr captures(none) [[A]])
423; CHECK-NEXT:    tail call void @use_nocapture(ptr captures(none) [[A]])
424; CHECK-NEXT:    tail call void @use(ptr [[A]])
425; CHECK-NEXT:    tail call void @use_nocapture(ptr captures(none) [[A]])
426; CHECK-NEXT:    ret void
427;
428; FIXME: This should be @use_nocapture(ptr noalias [[A]])
429; FIXME: This should be @use_nocapture(ptr noalias nocapture [[A]])
430  %A = tail call noalias ptr @malloc(i64 4)
431  tail call void @use_nocapture(ptr %A)
432  tail call void @use_nocapture(ptr %A)
433  tail call void @use(ptr %A)
434  tail call void @use_nocapture(ptr %A)
435  ret void
436}
437
438declare void @two_args(ptr nocapture , ptr nocapture)
439define void @test12_3(){
440; CHECK-LABEL: define {{[^@]+}}@test12_3() {
441; CHECK-NEXT:    [[A:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
442; CHECK-NEXT:    tail call void @two_args(ptr captures(none) [[A]], ptr captures(none) [[A]])
443; CHECK-NEXT:    ret void
444;
445  %A = tail call noalias ptr @malloc(i64 4)
446  tail call void @two_args(ptr %A, ptr %A)
447  ret void
448}
449
450define void @test12_4(){
451; CHECK-LABEL: define {{[^@]+}}@test12_4() {
452; CHECK-NEXT:    [[A:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
453; CHECK-NEXT:    [[B:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
454; CHECK-NEXT:    [[A_1:%.*]] = getelementptr i8, ptr [[A]], i64 1
455; CHECK-NEXT:    tail call void @two_args(ptr noalias captures(none) [[A]], ptr noalias captures(none) [[B]])
456; CHECK-NEXT:    tail call void @two_args(ptr captures(none) [[A]], ptr captures(none) [[A]])
457; CHECK-NEXT:    tail call void @two_args(ptr captures(none) [[A]], ptr captures(none) [[A_1]])
458; CHECK-NEXT:    tail call void @two_args(ptr noalias captures(none) [[A]], ptr noalias captures(none) [[B]])
459; CHECK-NEXT:    ret void
460;
461  %A = tail call noalias ptr @malloc(i64 4)
462  %B = tail call noalias ptr @malloc(i64 4)
463  %A_1 = getelementptr i8, ptr %A, i64 1
464
465  tail call void @two_args(ptr %A, ptr %B)
466
467  tail call void @two_args(ptr %A, ptr %A)
468
469  tail call void @two_args(ptr %A, ptr %A_1)
470
471; FIXME: This should be @two_args(ptr noalias nocapture %A, ptr noalias nocapture %B)
472  tail call void @two_args(ptr %A, ptr %B)
473  ret void
474}
475
476; TEST 13
477define void @use_i8_internal(ptr %a) {
478; CHECK-LABEL: define {{[^@]+}}@use_i8_internal
479; CHECK-SAME: (ptr captures(none) [[A:%.*]]) {
480; CHECK-NEXT:    call void @use_i8(ptr captures(none) [[A]])
481; CHECK-NEXT:    ret void
482;
483  call void @use_i8(ptr %a)
484  ret void
485}
486
487define void @test13_use_noalias(){
488; CHECK-LABEL: define {{[^@]+}}@test13_use_noalias() {
489; CHECK-NEXT:    [[M1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
490; CHECK-NEXT:    call void @use_i8_internal(ptr noalias captures(none) [[M1]])
491; CHECK-NEXT:    ret void
492;
493; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test13_use_noalias()
494; IS__CGSCC_OPM-NEXT:    [[M1:%.*]] = tail call noalias ptr @malloc(i64 4)
495; IS__CGSCC_OPM-NEXT:    call void @use_i8_internal(ptr noalias [[M1]])
496; IS__CGSCC_OPM-NEXT:    ret void
497  %m1 = tail call noalias ptr @malloc(i64 4)
498  call void @use_i8_internal(ptr %m1)
499  ret void
500}
501
502define void @test13_use_alias(){
503; CHECK-LABEL: define {{[^@]+}}@test13_use_alias() {
504; CHECK-NEXT:    [[M1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4)
505; CHECK-NEXT:    call void @use_i8_internal(ptr noalias captures(none) [[M1]])
506; CHECK-NEXT:    call void @use_i8_internal(ptr noalias captures(none) [[M1]])
507; CHECK-NEXT:    ret void
508;
509  %m1 = tail call noalias ptr @malloc(i64 4)
510  call void @use_i8_internal(ptr %m1)
511  call void @use_i8_internal(ptr %m1)
512  ret void
513}
514
515; TEST 14 i2p casts
516define internal i32 @p2i(ptr %arg) {
517; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
518; CHECK-LABEL: define {{[^@]+}}@p2i
519; CHECK-SAME: (ptr noalias nofree readnone [[ARG:%.*]]) #[[ATTR0]] {
520; CHECK-NEXT:    [[P2I:%.*]] = ptrtoint ptr [[ARG]] to i32
521; CHECK-NEXT:    ret i32 [[P2I]]
522;
523  %p2i = ptrtoint ptr %arg to i32
524  ret i32 %p2i
525}
526
527define i32 @i2p(ptr %arg) {
528; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
529; TUNIT-LABEL: define {{[^@]+}}@i2p
530; TUNIT-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR5:[0-9]+]] {
531; TUNIT-NEXT:    [[C:%.*]] = call i32 @p2i(ptr noalias nofree readnone [[ARG]]) #[[ATTR11:[0-9]+]]
532; TUNIT-NEXT:    [[I2P:%.*]] = inttoptr i32 [[C]] to ptr
533; TUNIT-NEXT:    [[CALL:%.*]] = call i32 @ret(ptr nofree noundef readonly align 4 captures(none) [[I2P]]) #[[ATTR12:[0-9]+]]
534; TUNIT-NEXT:    ret i32 [[CALL]]
535;
536; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read)
537; CGSCC-LABEL: define {{[^@]+}}@i2p
538; CGSCC-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR6:[0-9]+]] {
539; CGSCC-NEXT:    [[C:%.*]] = call i32 @p2i(ptr noalias nofree readnone [[ARG]]) #[[ATTR12]]
540; CGSCC-NEXT:    [[I2P:%.*]] = inttoptr i32 [[C]] to ptr
541; CGSCC-NEXT:    [[CALL:%.*]] = call i32 @ret(ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[I2P]]) #[[ATTR13:[0-9]+]]
542; CGSCC-NEXT:    ret i32 [[CALL]]
543;
544  %c = call i32 @p2i(ptr %arg)
545  %i2p = inttoptr i32 %c to ptr
546  %call = call i32 @ret(ptr %i2p)
547  ret i32 %call
548}
549define internal i32 @ret(ptr %arg) {
550; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
551; TUNIT-LABEL: define {{[^@]+}}@ret
552; TUNIT-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR6:[0-9]+]] {
553; TUNIT-NEXT:    [[L:%.*]] = load i32, ptr [[ARG]], align 4
554; TUNIT-NEXT:    ret i32 [[L]]
555;
556; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
557; CGSCC-LABEL: define {{[^@]+}}@ret
558; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR7:[0-9]+]] {
559; CGSCC-NEXT:    [[L:%.*]] = load i32, ptr [[ARG]], align 4
560; CGSCC-NEXT:    ret i32 [[L]]
561;
562  %l = load i32, ptr %arg
563  ret i32 %l
564}
565
566; Test to propagate noalias where value is assumed to be no-capture in all the
567; uses possibly executed before this callsite.
568; IR referred from musl/src/strtod.c file
569
570%struct._IO_FILE = type { i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i32, ptr, ptr, i32, i32, i32, i16, i8, i8, i32, i32, ptr, i64, ptr, ptr, ptr, [4 x i8], i64, i64, ptr, ptr, ptr, [4 x i8] }
571%struct.__locale_struct = type { [6 x ptr] }
572%struct.__locale_map = type opaque
573
574; Function Attrs: nounwind optsize
575define internal fastcc double @strtox(ptr %s, ptr %p, i32 %prec) unnamed_addr {
576; TUNIT-LABEL: define {{[^@]+}}@strtox
577; TUNIT-SAME: (ptr [[S:%.*]]) unnamed_addr {
578; TUNIT-NEXT:  entry:
579; TUNIT-NEXT:    [[F:%.*]] = alloca [[STRUCT__IO_FILE:%.*]], align 8
580; TUNIT-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 144, ptr nofree noundef nonnull align 8 captures(none) dereferenceable(240) [[F]]) #[[ATTR13:[0-9]+]]
581; TUNIT-NEXT:    [[CALL:%.*]] = call i32 @sh_fromstring(ptr noundef nonnull align 8 dereferenceable(240) [[F]], ptr [[S]])
582; TUNIT-NEXT:    call void @__shlim(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i64 noundef 0)
583; TUNIT-NEXT:    [[CALL1:%.*]] = call double @__floatscan(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i32 noundef 1, i32 noundef 1)
584; TUNIT-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 144, ptr nofree noundef nonnull align 8 captures(none) dereferenceable(240) [[F]])
585; TUNIT-NEXT:    ret double [[CALL1]]
586;
587; CGSCC-LABEL: define {{[^@]+}}@strtox
588; CGSCC-SAME: (ptr [[S:%.*]]) unnamed_addr {
589; CGSCC-NEXT:  entry:
590; CGSCC-NEXT:    [[F:%.*]] = alloca [[STRUCT__IO_FILE:%.*]], align 8
591; CGSCC-NEXT:    call void @llvm.lifetime.start.p0(i64 noundef 144, ptr nofree noundef nonnull align 8 captures(none) dereferenceable(240) [[F]]) #[[ATTR14:[0-9]+]]
592; CGSCC-NEXT:    [[CALL:%.*]] = call i32 @sh_fromstring(ptr noundef nonnull align 8 dereferenceable(240) [[F]], ptr [[S]])
593; CGSCC-NEXT:    call void @__shlim(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i64 noundef 0)
594; CGSCC-NEXT:    [[CALL1:%.*]] = call double @__floatscan(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i32 noundef 1, i32 noundef 1)
595; CGSCC-NEXT:    call void @llvm.lifetime.end.p0(i64 noundef 144, ptr nofree noundef nonnull align 8 captures(none) dereferenceable(240) [[F]])
596; CGSCC-NEXT:    ret double [[CALL1]]
597;
598entry:
599  %f = alloca %struct._IO_FILE, align 8
600  call void @llvm.lifetime.start.p0(i64 144, ptr nonnull %f)
601  %call = call i32 @sh_fromstring(ptr nonnull %f, ptr %s)
602  call void @__shlim(ptr nonnull %f, i64 0)
603  %call1 = call double @__floatscan(ptr nonnull %f, i32 %prec, i32 1)
604  call void @llvm.lifetime.end.p0(i64 144, ptr nonnull %f)
605
606  ret double %call1
607}
608
609; Function Attrs: nounwind optsize
610define dso_local double @strtod(ptr noalias %s, ptr noalias %p) {
611; CHECK-LABEL: define {{[^@]+}}@strtod
612; CHECK-SAME: (ptr noalias [[S:%.*]], ptr noalias nofree readnone captures(none) [[P:%.*]]) {
613; CHECK-NEXT:  entry:
614; CHECK-NEXT:    [[CALL:%.*]] = tail call fastcc double @strtox(ptr [[S]])
615; CHECK-NEXT:    ret double [[CALL]]
616;
617entry:
618  %call = tail call fastcc double @strtox(ptr %s, ptr %p, i32 1)
619  ret double %call
620}
621
622; Function Attrs: argmemonly nounwind willreturn
623declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
624
625; Function Attrs: optsize
626declare dso_local i32 @sh_fromstring(...) local_unnamed_addr
627
628; Function Attrs: optsize
629declare dso_local void @__shlim(ptr, i64) local_unnamed_addr
630
631; Function Attrs: optsize
632declare dso_local double @__floatscan(ptr, i32, i32) local_unnamed_addr
633
634; Function Attrs: argmemonly nounwind willreturn
635declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
636
637; Test 15
638; propagate noalias to some callsite arguments that there is no possibly reachable capture before it
639
640@alias_of_p = external global ptr
641
642define void @make_alias(ptr %p) {
643; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
644; TUNIT-LABEL: define {{[^@]+}}@make_alias
645; TUNIT-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR8:[0-9]+]] {
646; TUNIT-NEXT:    store ptr [[P]], ptr @alias_of_p, align 8
647; TUNIT-NEXT:    ret void
648;
649; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
650; CGSCC-LABEL: define {{[^@]+}}@make_alias
651; CGSCC-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR9:[0-9]+]] {
652; CGSCC-NEXT:    store ptr [[P]], ptr @alias_of_p, align 8
653; CGSCC-NEXT:    ret void
654;
655  store ptr %p, ptr @alias_of_p
656  ret void
657}
658
659define void @only_store(ptr %p) {
660; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
661; TUNIT-LABEL: define {{[^@]+}}@only_store
662; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR9:[0-9]+]] {
663; TUNIT-NEXT:    store i32 0, ptr [[P]], align 4
664; TUNIT-NEXT:    ret void
665;
666; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
667; CGSCC-LABEL: define {{[^@]+}}@only_store
668; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P:%.*]]) #[[ATTR10:[0-9]+]] {
669; CGSCC-NEXT:    store i32 0, ptr [[P]], align 4
670; CGSCC-NEXT:    ret void
671;
672  store i32 0, ptr %p
673  ret void
674}
675
676define void @test15_caller(ptr noalias %p, i32 %c) {
677; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
678; TUNIT-LABEL: define {{[^@]+}}@test15_caller
679; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] {
680; TUNIT-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0
681; TUNIT-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
682; TUNIT:       if.then:
683; TUNIT-NEXT:    tail call void @only_store(ptr noalias nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14:[0-9]+]]
684; TUNIT-NEXT:    br label [[IF_END]]
685; TUNIT:       if.end:
686; TUNIT-NEXT:    tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR14]]
687; TUNIT-NEXT:    ret void
688;
689; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
690; CGSCC-LABEL: define {{[^@]+}}@test15_caller
691; CGSCC-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11:[0-9]+]] {
692; CGSCC-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0
693; CGSCC-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
694; CGSCC:       if.then:
695; CGSCC-NEXT:    tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15:[0-9]+]]
696; CGSCC-NEXT:    br label [[IF_END]]
697; CGSCC:       if.end:
698; CGSCC-NEXT:    tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR15]]
699; CGSCC-NEXT:    ret void
700;
701  %tobool = icmp eq i32 %c, 0
702  br i1 %tobool, label %if.end, label %if.then
703
704
705if.then:
706  tail call void @only_store(ptr %p)
707  br label %if.end
708
709if.end:
710  tail call void @make_alias(ptr %p)
711  ret void
712}
713
714; Test 16
715;
716; __attribute__((noinline)) static void test16_sub(int * restrict p, int c1, int c2) {
717;   if (c1) {
718;     only_store(p);
719;     make_alias(p);
720;   }
721;   if (!c2) {
722;     only_store(p);
723;   }
724; }
725; void test16_caller(int * restrict p, int c) {
726;   test16_sub(p, c, c);
727; }
728;
729; FIXME: this should be tail @only_store(ptr noalias %p)
730;        when test16_caller is called, c1 always equals to c2. (Note that linkage is internal)
731;        Therefore, only one of the two conditions of if statementes will be fulfilled.
732
733define internal void @test16_sub(ptr noalias %p, i32 %c1, i32 %c2) {
734; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
735; TUNIT-LABEL: define {{[^@]+}}@test16_sub
736; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C1:%.*]], i32 [[C2:%.*]]) #[[ATTR8]] {
737; TUNIT-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C1]], 0
738; TUNIT-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
739; TUNIT:       if.then:
740; TUNIT-NEXT:    tail call void @only_store(ptr nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14]]
741; TUNIT-NEXT:    tail call void @make_alias(ptr nofree writeonly align 4 [[P]]) #[[ATTR14]]
742; TUNIT-NEXT:    br label [[IF_END]]
743; TUNIT:       if.end:
744; TUNIT-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C2]], 0
745; TUNIT-NEXT:    br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]]
746; TUNIT:       if.then2:
747; TUNIT-NEXT:    tail call void @only_store(ptr nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14]]
748; TUNIT-NEXT:    br label [[IF_END3]]
749; TUNIT:       if.end3:
750; TUNIT-NEXT:    ret void
751;
752; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
753; CGSCC-LABEL: define {{[^@]+}}@test16_sub
754; CGSCC-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C1:%.*]], i32 [[C2:%.*]]) #[[ATTR11]] {
755; CGSCC-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C1]], 0
756; CGSCC-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
757; CGSCC:       if.then:
758; CGSCC-NEXT:    tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15]]
759; CGSCC-NEXT:    tail call void @make_alias(ptr nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]]
760; CGSCC-NEXT:    br label [[IF_END]]
761; CGSCC:       if.end:
762; CGSCC-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C2]], 0
763; CGSCC-NEXT:    br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]]
764; CGSCC:       if.then2:
765; CGSCC-NEXT:    tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15]]
766; CGSCC-NEXT:    br label [[IF_END3]]
767; CGSCC:       if.end3:
768; CGSCC-NEXT:    ret void
769;
770  %tobool = icmp eq i32 %c1, 0
771  br i1 %tobool, label %if.end, label %if.then
772
773if.then:
774  tail call void @only_store(ptr %p)
775  tail call void @make_alias(ptr %p)
776  br label %if.end
777if.end:
778
779  %tobool1 = icmp eq i32 %c2, 0
780  br i1 %tobool1, label %if.then2, label %if.end3
781
782if.then2:
783  tail call void @only_store(ptr %p)
784  br label %if.end3
785if.end3:
786
787  ret void
788}
789
790define void @test16_caller(ptr %p, i32 %c) {
791; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
792; TUNIT-LABEL: define {{[^@]+}}@test16_caller
793; TUNIT-SAME: (ptr nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] {
794; TUNIT-NEXT:    tail call void @test16_sub(ptr nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR14]]
795; TUNIT-NEXT:    ret void
796;
797; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
798; CGSCC-LABEL: define {{[^@]+}}@test16_caller
799; CGSCC-SAME: (ptr nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11]] {
800; CGSCC-NEXT:    tail call void @test16_sub(ptr nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR15]]
801; CGSCC-NEXT:    ret void
802;
803  tail call void @test16_sub(ptr %p, i32 %c, i32 %c)
804  ret void
805}
806
807; test 17
808;
809; only_store is not called after make_alias is called.
810;
811; void test17_caller(int* p, int c) {
812;   if(c) {
813;     make_alias(p);
814;     if(0 == 0) {
815;       goto l3;
816;     } else {
817;       goto l2;
818;     }
819;   }
820;   l2:
821;     only_store(p);
822;   l3:
823;   return;
824; }
825
826define void @test17_caller(ptr noalias %p, i32 %c) {
827; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
828; TUNIT-LABEL: define {{[^@]+}}@test17_caller
829; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] {
830; TUNIT-NEXT:  entry:
831; TUNIT-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0
832; TUNIT-NEXT:    br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]]
833; TUNIT:       l1:
834; TUNIT-NEXT:    tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR14]]
835; TUNIT-NEXT:    br label [[L3:%.*]]
836; TUNIT:       l2:
837; TUNIT-NEXT:    tail call void @only_store(ptr noalias nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14]]
838; TUNIT-NEXT:    br label [[L3]]
839; TUNIT:       l3:
840; TUNIT-NEXT:    ret void
841;
842; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
843; CGSCC-LABEL: define {{[^@]+}}@test17_caller
844; CGSCC-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11]] {
845; CGSCC-NEXT:  entry:
846; CGSCC-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0
847; CGSCC-NEXT:    br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]]
848; CGSCC:       l1:
849; CGSCC-NEXT:    tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR15]]
850; CGSCC-NEXT:    br label [[L3:%.*]]
851; CGSCC:       l2:
852; CGSCC-NEXT:    tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15]]
853; CGSCC-NEXT:    br label [[L3]]
854; CGSCC:       l3:
855; CGSCC-NEXT:    ret void
856;
857entry:
858  %tobool = icmp eq i32 %c, 0
859  br i1 %tobool, label %l1, label %l2
860
861l1:
862  tail call void @make_alias(ptr %p)
863  %tobool2 = icmp eq i32 0, 0
864  br i1 %tobool2, label %l3, label %l2
865
866l2:
867  tail call void @only_store(ptr %p)
868  br label %l3
869
870l3:
871  ret void
872}
873
874; test 18
875; void test18_caller(int* p, int c) {
876;   if(c) {
877;     make_alias(p);
878;     noreturn();
879;   }
880;   only_store(p);
881;   return;
882; }
883
884define void @noreturn() {
885; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
886; TUNIT-LABEL: define {{[^@]+}}@noreturn
887; TUNIT-SAME: () #[[ATTR10:[0-9]+]] {
888; TUNIT-NEXT:    ret void
889;
890; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
891; CGSCC-LABEL: define {{[^@]+}}@noreturn
892; CGSCC-SAME: () #[[ATTR2]] {
893; CGSCC-NEXT:    ret void
894;
895  call void @noreturn()
896  ret void
897}
898
899define void @test18_caller(ptr noalias %p, i32 %c) {
900; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
901; TUNIT-LABEL: define {{[^@]+}}@test18_caller
902; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] {
903; TUNIT-NEXT:  entry:
904; TUNIT-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0
905; TUNIT-NEXT:    br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]]
906; TUNIT:       l1:
907; TUNIT-NEXT:    tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR14]]
908; TUNIT-NEXT:    br label [[L2]]
909; TUNIT:       l2:
910; TUNIT-NEXT:    tail call void @only_store(ptr nofree noundef writeonly align 4 captures(none) [[P]]) #[[ATTR14]]
911; TUNIT-NEXT:    ret void
912;
913; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)
914; CGSCC-LABEL: define {{[^@]+}}@test18_caller
915; CGSCC-SAME: (ptr noalias nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11]] {
916; CGSCC-NEXT:  entry:
917; CGSCC-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0
918; CGSCC-NEXT:    br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]]
919; CGSCC:       l1:
920; CGSCC-NEXT:    tail call void @make_alias(ptr nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]]
921; CGSCC-NEXT:    br label [[L2]]
922; CGSCC:       l2:
923; CGSCC-NEXT:    tail call void @only_store(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[P]]) #[[ATTR15]]
924; CGSCC-NEXT:    ret void
925;
926entry:
927  %tobool = icmp eq i32 %c, 0
928  br i1 %tobool, label %l1, label %l2
929
930l1:
931  tail call void @make_alias(ptr %p)
932  tail call void @noreturn()
933  br label %l2
934
935l2:
936  tail call void @only_store(ptr %p)
937  ret void
938}
939;.
940; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
941; TUNIT: attributes #[[ATTR1]] = { nounwind uwtable }
942; TUNIT: attributes #[[ATTR2]] = { nounwind }
943; TUNIT: attributes #[[ATTR3]] = { nounwind ssp uwtable }
944; TUNIT: attributes #[[ATTR4]] = { memory(readwrite, argmem: none) }
945; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(read) }
946; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
947; TUNIT: attributes #[[ATTR7:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
948; TUNIT: attributes #[[ATTR8]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
949; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
950; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
951; TUNIT: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn memory(none) }
952; TUNIT: attributes #[[ATTR12]] = { nofree nosync nounwind willreturn memory(read) }
953; TUNIT: attributes #[[ATTR13]] = { nofree willreturn memory(readwrite) }
954; TUNIT: attributes #[[ATTR14]] = { nofree nosync nounwind willreturn memory(write) }
955;.
956; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
957; CGSCC: attributes #[[ATTR1]] = { nounwind uwtable }
958; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
959; CGSCC: attributes #[[ATTR3]] = { nounwind }
960; CGSCC: attributes #[[ATTR4]] = { nounwind ssp uwtable }
961; CGSCC: attributes #[[ATTR5]] = { memory(readwrite, argmem: none) }
962; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree nosync nounwind willreturn memory(read) }
963; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
964; CGSCC: attributes #[[ATTR8:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
965; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
966; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
967; CGSCC: attributes #[[ATTR11]] = { mustprogress nofree nosync nounwind willreturn memory(write) }
968; CGSCC: attributes #[[ATTR12]] = { nofree nosync willreturn }
969; CGSCC: attributes #[[ATTR13]] = { nofree willreturn memory(read) }
970; CGSCC: attributes #[[ATTR14]] = { nofree willreturn memory(readwrite) }
971; CGSCC: attributes #[[ATTR15]] = { nofree nounwind willreturn memory(write) }
972;.
973