Skip to content

Commit 01d4b8e

Browse files
committed
[FunctionAttrs] Add additional tests (NFC)
Add test coverage for noalias, and for unknown function calls.
1 parent a6532c2 commit 01d4b8e

File tree

5 files changed

+429
-41
lines changed

5 files changed

+429
-41
lines changed
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=function-attrs < %s | FileCheck %s
3+
4+
declare noalias ptr @malloc(i64 %size)
5+
declare ptr @not_malloc(i64 %size)
6+
declare void @capture(ptr)
7+
8+
@g = external global i8
9+
10+
define ptr @return_malloc(i64 %size) {
11+
; CHECK-LABEL: define noalias ptr @return_malloc(
12+
; CHECK-SAME: i64 [[SIZE:%.*]]) {
13+
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 [[SIZE]])
14+
; CHECK-NEXT: ret ptr [[A]]
15+
;
16+
%a = call ptr @malloc(i64 %size)
17+
ret ptr %a
18+
}
19+
20+
define ptr @return_not_malloc(i64 %size) {
21+
; CHECK-LABEL: define ptr @return_not_malloc(
22+
; CHECK-SAME: i64 [[SIZE:%.*]]) {
23+
; CHECK-NEXT: [[A:%.*]] = call ptr @not_malloc(i64 [[SIZE]])
24+
; CHECK-NEXT: ret ptr [[A]]
25+
;
26+
%a = call ptr @not_malloc(i64 %size)
27+
ret ptr %a
28+
}
29+
30+
define ptr @return_null() {
31+
; CHECK-LABEL: define noalias noundef ptr @return_null(
32+
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
33+
; CHECK-NEXT: ret ptr null
34+
;
35+
ret ptr null
36+
}
37+
38+
define ptr @return_poison() {
39+
; CHECK-LABEL: define noalias ptr @return_poison(
40+
; CHECK-SAME: ) #[[ATTR0]] {
41+
; CHECK-NEXT: ret ptr poison
42+
;
43+
ret ptr poison
44+
}
45+
46+
define ptr @return_alloca() {
47+
; CHECK-LABEL: define noalias noundef nonnull ptr @return_alloca(
48+
; CHECK-SAME: ) #[[ATTR0]] {
49+
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
50+
; CHECK-NEXT: ret ptr [[A]]
51+
;
52+
%a = alloca i8
53+
ret ptr %a
54+
}
55+
56+
; noalias arg does not imply noalias return
57+
define ptr @return_noalias_arg(ptr noalias %arg) {
58+
; CHECK-LABEL: define ptr @return_noalias_arg(
59+
; CHECK-SAME: ptr noalias readnone returned captures(ret: address, provenance) [[ARG:%.*]]) #[[ATTR0]] {
60+
; CHECK-NEXT: ret ptr [[ARG]]
61+
;
62+
ret ptr %arg
63+
}
64+
65+
define ptr @return_global() {
66+
; CHECK-LABEL: define noundef nonnull ptr @return_global(
67+
; CHECK-SAME: ) #[[ATTR0]] {
68+
; CHECK-NEXT: ret ptr @g
69+
;
70+
ret ptr @g
71+
}
72+
73+
define ptr @no_return() {
74+
; CHECK-LABEL: define noalias noundef nonnull ptr @no_return(
75+
; CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
76+
; CHECK-NEXT: unreachable
77+
;
78+
unreachable
79+
}
80+
81+
define ptr @return_multiple(i1 %c, i64 %size) {
82+
; CHECK-LABEL: define noalias ptr @return_multiple(
83+
; CHECK-SAME: i1 [[C:%.*]], i64 [[SIZE:%.*]]) {
84+
; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[ELSE:.*]]
85+
; CHECK: [[IF]]:
86+
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 [[SIZE]])
87+
; CHECK-NEXT: ret ptr [[A]]
88+
; CHECK: [[ELSE]]:
89+
; CHECK-NEXT: [[B:%.*]] = call ptr @malloc(i64 [[SIZE]])
90+
; CHECK-NEXT: ret ptr [[B]]
91+
;
92+
br i1 %c, label %if, label %else
93+
94+
if:
95+
%a = call ptr @malloc(i64 %size)
96+
ret ptr %a
97+
98+
else:
99+
%b = call ptr @malloc(i64 %size)
100+
ret ptr %b
101+
}
102+
103+
define ptr @return_select(i1 %c, i64 %size) {
104+
; CHECK-LABEL: define noalias ptr @return_select(
105+
; CHECK-SAME: i1 [[C:%.*]], i64 [[SIZE:%.*]]) {
106+
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 [[SIZE]])
107+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], ptr [[A]], ptr null
108+
; CHECK-NEXT: ret ptr [[SEL]]
109+
;
110+
%a = call ptr @malloc(i64 %size)
111+
%sel = select i1 %c, ptr %a, ptr null
112+
ret ptr %sel
113+
}
114+
115+
define ptr @return_phi(i1 %c, i64 %size) {
116+
; CHECK-LABEL: define noalias ptr @return_phi(
117+
; CHECK-SAME: i1 [[C:%.*]], i64 [[SIZE:%.*]]) {
118+
; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[ELSE:.*]]
119+
; CHECK: [[IF]]:
120+
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 [[SIZE]])
121+
; CHECK-NEXT: br label %[[JOIN:.*]]
122+
; CHECK: [[ELSE]]:
123+
; CHECK-NEXT: br label %[[JOIN]]
124+
; CHECK: [[JOIN]]:
125+
; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], %[[IF]] ], [ null, %[[ELSE]] ]
126+
; CHECK-NEXT: ret ptr [[PHI]]
127+
;
128+
br i1 %c, label %if, label %else
129+
130+
if:
131+
%a = call ptr @malloc(i64 %size)
132+
br label %join
133+
134+
else:
135+
br label %join
136+
137+
join:
138+
%phi = phi ptr [ %a, %if ], [ null, %else ]
139+
ret ptr %phi
140+
}
141+
142+
define ptr @return_phi_wrong(i1 %c, i64 %size) {
143+
; CHECK-LABEL: define ptr @return_phi_wrong(
144+
; CHECK-SAME: i1 [[C:%.*]], i64 [[SIZE:%.*]]) {
145+
; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[ELSE:.*]]
146+
; CHECK: [[IF]]:
147+
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 [[SIZE]])
148+
; CHECK-NEXT: br label %[[JOIN:.*]]
149+
; CHECK: [[ELSE]]:
150+
; CHECK-NEXT: [[B:%.*]] = call ptr @not_malloc(i64 [[SIZE]])
151+
; CHECK-NEXT: br label %[[JOIN]]
152+
; CHECK: [[JOIN]]:
153+
; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], %[[IF]] ], [ [[B]], %[[ELSE]] ]
154+
; CHECK-NEXT: ret ptr [[PHI]]
155+
;
156+
br i1 %c, label %if, label %else
157+
158+
if:
159+
%a = call ptr @malloc(i64 %size)
160+
br label %join
161+
162+
else:
163+
%b = call ptr @not_malloc(i64 %size)
164+
br label %join
165+
166+
join:
167+
%phi = phi ptr [ %a, %if ], [ %b, %else ]
168+
ret ptr %phi
169+
}
170+
171+
define ptr @return_malloc_with_store(i64 %size) {
172+
; CHECK-LABEL: define noalias noundef ptr @return_malloc_with_store(
173+
; CHECK-SAME: i64 [[SIZE:%.*]]) {
174+
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 [[SIZE]])
175+
; CHECK-NEXT: store i8 0, ptr [[A]], align 1
176+
; CHECK-NEXT: ret ptr [[A]]
177+
;
178+
%a = call ptr @malloc(i64 %size)
179+
store i8 0, ptr %a
180+
ret ptr %a
181+
}
182+
183+
define ptr @return_malloc_captured(i64 %size) {
184+
; CHECK-LABEL: define ptr @return_malloc_captured(
185+
; CHECK-SAME: i64 [[SIZE:%.*]]) {
186+
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 [[SIZE]])
187+
; CHECK-NEXT: call void @capture(ptr [[A]])
188+
; CHECK-NEXT: ret ptr [[A]]
189+
;
190+
%a = call ptr @malloc(i64 %size)
191+
call void @capture(ptr %a)
192+
ret ptr %a
193+
}
194+
195+
define ptr @scc1(i1 %c) {
196+
; CHECK-LABEL: define noalias ptr @scc1(
197+
; CHECK-SAME: i1 [[C:%.*]]) {
198+
; CHECK-NEXT: br i1 [[C]], label %[[IF:.*]], label %[[ELSE:.*]]
199+
; CHECK: [[IF]]:
200+
; CHECK-NEXT: [[A:%.*]] = call ptr @malloc(i64 4)
201+
; CHECK-NEXT: ret ptr [[A]]
202+
; CHECK: [[ELSE]]:
203+
; CHECK-NEXT: [[B:%.*]] = call ptr @scc2(i1 [[C]])
204+
; CHECK-NEXT: ret ptr [[B]]
205+
;
206+
br i1 %c, label %if, label %else
207+
208+
if:
209+
%a = call ptr @malloc(i64 4)
210+
ret ptr %a
211+
212+
else:
213+
%b = call ptr @scc2(i1 %c)
214+
ret ptr %b
215+
}
216+
217+
define ptr @scc2(i1 %c) {
218+
; CHECK-LABEL: define noalias ptr @scc2(
219+
; CHECK-SAME: i1 [[C:%.*]]) {
220+
; CHECK-NEXT: [[A:%.*]] = call ptr @scc1(i1 [[C]])
221+
; CHECK-NEXT: ret ptr [[A]]
222+
;
223+
%a = call ptr @scc1(i1 %c)
224+
ret ptr %a
225+
}
226+
227+
define ptr @return_unknown_call(ptr %fn) {
228+
; CHECK-LABEL: define ptr @return_unknown_call(
229+
; CHECK-SAME: ptr readonly captures(none) [[FN:%.*]]) {
230+
; CHECK-NEXT: [[A:%.*]] = call ptr [[FN]]()
231+
; CHECK-NEXT: ret ptr [[A]]
232+
;
233+
%a = call ptr %fn()
234+
ret ptr %a
235+
}
236+
237+
define ptr @return_unknown_noalias_call(ptr %fn) {
238+
; CHECK-LABEL: define ptr @return_unknown_noalias_call(
239+
; CHECK-SAME: ptr readonly captures(none) [[FN:%.*]]) {
240+
; CHECK-NEXT: [[A:%.*]] = call noalias ptr [[FN]]()
241+
; CHECK-NEXT: ret ptr [[A]]
242+
;
243+
%a = call noalias ptr %fn()
244+
ret ptr %a
245+
}

llvm/test/Transforms/FunctionAttrs/nofree.ll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,24 @@ entry:
156156
ret void
157157
}
158158

159+
define void @unknown_call(ptr %fn) {
160+
; CHECK-LABEL: @unknown_call(
161+
; CHECK-NEXT: call void [[FN:%.*]]()
162+
; CHECK-NEXT: ret void
163+
;
164+
call void %fn()
165+
ret void
166+
}
167+
168+
define void @unknown_nofree_call(ptr %fn) {
169+
; CHECK-LABEL: @unknown_nofree_call(
170+
; CHECK-NEXT: call void [[FN:%.*]]() #[[ATTR5]]
171+
; CHECK-NEXT: ret void
172+
;
173+
call void %fn() nofree
174+
ret void
175+
}
176+
159177
declare void @_ZdaPv(ptr) local_unnamed_addr #4
160178

161179
attributes #0 = { uwtable }

llvm/test/Transforms/FunctionAttrs/nonnull.ll

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,5 +1396,35 @@ define ptr @pr91177_non_inbounds_gep(ptr nonnull %arg) {
13961396
ret ptr %res
13971397
}
13981398

1399+
define ptr @unknown_func(ptr %fn) {
1400+
; FNATTRS-LABEL: define ptr @unknown_func(
1401+
; FNATTRS-SAME: ptr readonly captures(none) [[FN:%.*]]) {
1402+
; FNATTRS-NEXT: [[RES:%.*]] = call ptr [[FN]]()
1403+
; FNATTRS-NEXT: ret ptr [[RES]]
1404+
;
1405+
; ATTRIBUTOR-LABEL: define ptr @unknown_func(
1406+
; ATTRIBUTOR-SAME: ptr nofree nonnull captures(none) [[FN:%.*]]) {
1407+
; ATTRIBUTOR-NEXT: [[RES:%.*]] = call ptr [[FN]]()
1408+
; ATTRIBUTOR-NEXT: ret ptr [[RES]]
1409+
;
1410+
%res = call ptr %fn()
1411+
ret ptr %res
1412+
}
1413+
1414+
define ptr @unknown_nonnull_func(ptr %fn) {
1415+
; FNATTRS-LABEL: define ptr @unknown_nonnull_func(
1416+
; FNATTRS-SAME: ptr readonly captures(none) [[FN:%.*]]) {
1417+
; FNATTRS-NEXT: [[RES:%.*]] = call nonnull ptr [[FN]]()
1418+
; FNATTRS-NEXT: ret ptr [[RES]]
1419+
;
1420+
; ATTRIBUTOR-LABEL: define nonnull ptr @unknown_nonnull_func(
1421+
; ATTRIBUTOR-SAME: ptr nofree nonnull captures(none) [[FN:%.*]]) {
1422+
; ATTRIBUTOR-NEXT: [[RES:%.*]] = call nonnull ptr [[FN]]()
1423+
; ATTRIBUTOR-NEXT: ret ptr [[RES]]
1424+
;
1425+
%res = call nonnull ptr %fn()
1426+
ret ptr %res
1427+
}
1428+
13991429
attributes #0 = { null_pointer_is_valid }
14001430
attributes #1 = { nounwind willreturn}

llvm/test/Transforms/FunctionAttrs/norecurse.ll

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,37 @@ define void @r() norecurse {
241241
call void @q()
242242
ret void
243243
}
244+
245+
define void @unknown_call(ptr %fn) {
246+
; FNATTRS-LABEL: define {{[^@]+}}@unknown_call
247+
; FNATTRS-SAME: (ptr readonly captures(none) [[FN:%.*]]) {
248+
; FNATTRS-NEXT: call void [[FN]]()
249+
; FNATTRS-NEXT: ret void
250+
;
251+
; ATTRIBUTOR-LABEL: define {{[^@]+}}@unknown_call
252+
; ATTRIBUTOR-SAME: (ptr nofree nonnull captures(none) [[FN:%.*]]) {
253+
; ATTRIBUTOR-NEXT: call void [[FN]]()
254+
; ATTRIBUTOR-NEXT: ret void
255+
;
256+
call void %fn()
257+
ret void
258+
}
259+
260+
define void @unknown_norecurse_call(ptr %fn) {
261+
; FNATTRS-LABEL: define {{[^@]+}}@unknown_norecurse_call
262+
; FNATTRS-SAME: (ptr readonly captures(none) [[FN:%.*]]) {
263+
; FNATTRS-NEXT: call void [[FN]]() #[[ATTR7:[0-9]+]]
264+
; FNATTRS-NEXT: ret void
265+
;
266+
; ATTRIBUTOR-LABEL: define {{[^@]+}}@unknown_norecurse_call
267+
; ATTRIBUTOR-SAME: (ptr nofree nonnull captures(none) [[FN:%.*]]) {
268+
; ATTRIBUTOR-NEXT: call void [[FN]]() #[[ATTR9:[0-9]+]]
269+
; ATTRIBUTOR-NEXT: ret void
270+
;
271+
call void %fn() norecurse
272+
ret void
273+
}
274+
244275
;.
245276
; FNATTRS: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
246277
; FNATTRS: attributes #[[ATTR1]] = { nofree nosync nounwind memory(none) }
@@ -249,6 +280,7 @@ define void @r() norecurse {
249280
; FNATTRS: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
250281
; FNATTRS: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
251282
; FNATTRS: attributes #[[ATTR6]] = { nofree norecurse nosync memory(none) }
283+
; FNATTRS: attributes #[[ATTR7]] = { norecurse }
252284
;.
253285
; ATTRIBUTOR: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
254286
; ATTRIBUTOR: attributes #[[ATTR1]] = { nofree nosync nounwind memory(none) }
@@ -259,6 +291,7 @@ define void @r() norecurse {
259291
; ATTRIBUTOR: attributes #[[ATTR6]] = { norecurse nosync memory(none) }
260292
; ATTRIBUTOR: attributes #[[ATTR7]] = { nosync }
261293
; ATTRIBUTOR: attributes #[[ATTR8]] = { nofree willreturn }
294+
; ATTRIBUTOR: attributes #[[ATTR9]] = { norecurse }
262295
;.
263296
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
264297
; COMMON: {{.*}}

0 commit comments

Comments
 (0)