xref: /llvm-project/llvm/test/Transforms/Inline/always-inline.ll (revision deab451e7a7f2dff42097049274637052c87eabd)
1; The new pass manager doesn't re-use any threshold based infrastructure for
2; the always inliner, but test that we get the correct result.
3; RUN: opt < %s -inline-threshold=0 -passes=always-inline -S | FileCheck %s --check-prefix=CHECK
4; RUN: opt < %s -inline-threshold=20000000 -passes=always-inline -S | FileCheck %s --check-prefix=CHECK
5; RUN: opt < %s -inline-threshold=-20000000 -passes=always-inline -S | FileCheck %s --check-prefix=CHECK
6
7define internal i32 @inner1() alwaysinline {
8; CHECK-NOT: @inner1(
9  ret i32 1
10}
11define i32 @outer1() {
12; CHECK-LABEL: @outer1(
13; CHECK-NOT: call
14; CHECK: ret
15
16   %r = call i32 @inner1()
17   ret i32 %r
18}
19
20; The always inliner can't DCE arbitrary internal functions. PR2945
21define internal i32 @pr2945() nounwind {
22; CHECK-LABEL: @pr2945(
23  ret i32 0
24}
25
26define internal void @inner2(i32 %N) alwaysinline {
27; CHECK-NOT: @inner2(
28  %P = alloca i32, i32 %N
29  ret void
30}
31define void @outer2(i32 %N) {
32; The always inliner (unlike the normal one) should be willing to inline
33; a function with a dynamic alloca into one without a dynamic alloca.
34; rdar://6655932
35;
36; CHECK-LABEL: @outer2(
37; CHECK-NOT: call void @inner2
38; CHECK: ret void
39
40  call void @inner2( i32 %N )
41  ret void
42}
43
44declare i32 @a() returns_twice
45declare i32 @b() returns_twice
46
47; Cannot alwaysinline when that would introduce a returns_twice call.
48define internal i32 @inner3() alwaysinline {
49; CHECK-LABEL: @inner3(
50entry:
51  %call = call i32 @a() returns_twice
52  %add = add nsw i32 1, %call
53  ret i32 %add
54}
55define i32 @outer3() {
56entry:
57; CHECK-LABEL: @outer3(
58; CHECK-NOT: call i32 @a
59; CHECK: ret
60
61  %call = call i32 @inner3()
62  %add = add nsw i32 1, %call
63  ret i32 %add
64}
65
66define internal i32 @inner4() alwaysinline returns_twice {
67; CHECK-NOT: @inner4(
68entry:
69  %call = call i32 @b() returns_twice
70  %add = add nsw i32 1, %call
71  ret i32 %add
72}
73
74define i32 @outer4() {
75entry:
76; CHECK-LABEL: @outer4(
77; CHECK: call i32 @b()
78; CHECK: ret
79
80  %call = call i32 @inner4() returns_twice
81  %add = add nsw i32 1, %call
82  ret i32 %add
83}
84
85; We can't inline this even though it has alwaysinline!
86define internal i32 @inner5(ptr %addr) alwaysinline {
87; CHECK-LABEL: @inner5(
88entry:
89  indirectbr ptr %addr, [ label %one, label %two ]
90
91one:
92  ret i32 42
93
94two:
95  ret i32 44
96}
97define i32 @outer5(i32 %x) {
98; CHECK-LABEL: @outer5(
99; CHECK: call i32 @inner5
100; CHECK: ret
101
102  %cmp = icmp slt i32 %x, 42
103  %addr = select i1 %cmp, ptr blockaddress(@inner5, %one), ptr blockaddress(@inner5, %two)
104  %call = call i32 @inner5(ptr %addr)
105  ret i32 %call
106}
107
108; We never inline a function that calls itself recursively.
109define internal void @inner6(i32 %x) alwaysinline {
110; CHECK-LABEL: @inner6(
111entry:
112  %icmp = icmp slt i32 %x, 0
113  br i1 %icmp, label %return, label %bb
114
115bb:
116  %sub = sub nsw i32 %x, 1
117  call void @inner6(i32 %sub)
118  ret void
119
120return:
121  ret void
122}
123define void @outer6() {
124; CHECK-LABEL: @outer6(
125; CHECK: call void @inner6(i32 42)
126; CHECK: ret
127
128entry:
129  call void @inner6(i32 42)
130  ret void
131}
132
133; This is not an alwaysinline function and is actually external.
134define i32 @inner7() {
135; CHECK-LABEL: @inner7(
136  ret i32 1
137}
138define i32 @outer7() {
139; CHECK-LABEL: @outer7(
140; CHECK-NOT: call
141; CHECK: ret
142   %r = call i32 @inner7() alwaysinline
143   ret i32 %r
144}
145
146define internal ptr @inner8(ptr nocapture align 128 %a) alwaysinline {
147; CHECK-NOT: @inner8(
148  ret ptr %a
149}
150define float @outer8(ptr nocapture %a) {
151; CHECK-LABEL: @outer8(
152; CHECK-NOT: call ptr @inner8
153; CHECK: ret
154
155  %inner_a = call ptr @inner8(ptr %a)
156  %f = load float, ptr %inner_a, align 4
157  ret float %f
158}
159
160
161; The 'inner9*' and 'outer9' functions are designed to check that we remove
162; a function that is inlined by the always inliner even when it is used by
163; a complex constant expression prior to being inlined.
164
165; The 'a' function gets used in a complex constant expression that, despite
166; being constant folded, means it isn't dead. As a consequence it shouldn't be
167; deleted. If it is, then the constant expression needs to become more complex
168; to accurately test this scenario.
169define internal void @inner9a(i1 %b) alwaysinline {
170; CHECK-LABEL: @inner9a(
171entry:
172  ret void
173}
174
175define internal void @inner9b(i64 %b) alwaysinline {
176; CHECK-NOT: @inner9b(
177entry:
178  ret void
179}
180
181declare void @dummy9(i1 %b)
182
183define void @outer9() {
184; CHECK-LABEL: @outer9(
185entry:
186  ; First we use @inner9a in a complex constant expression that may get folded
187  ; but won't get removed, and then we call it which will get inlined. Despite
188  ; this the function can't be deleted because of the constant expression
189  ; usage.
190  %sink = alloca i1
191  %cmp = icmp eq i64 ptrtoint (ptr @inner9a to i64), ptrtoint(ptr @dummy9 to i64)
192  store volatile i1 %cmp, ptr %sink
193; CHECK: store volatile
194  call void @inner9a(i1 false)
195; CHECK-NOT: call void @inner9a
196
197  ; Next we call @inner9b passing in a constant expression. This constant
198  ; expression will in fact be removed by inlining, so we should also be able
199  ; to delete the function.
200  call void @inner9b(i64 ptrtoint (ptr @inner9b to i64))
201; CHECK-NOT: @inner9b
202
203  ret void
204; CHECK: ret void
205}
206
207; The 'inner10' and 'outer10' functions test a frustrating consequence of the
208; current 'alwaysinline' semantic model. Because such functions are allowed to
209; be external functions, it may be necessary to both inline all of their uses
210; and leave them in the final output. These tests can be removed if and when
211; we restrict alwaysinline further.
212define void @inner10() alwaysinline {
213; CHECK-LABEL: @inner10(
214entry:
215  ret void
216}
217
218define void @outer10() {
219; CHECK-LABEL: @outer10(
220entry:
221  call void @inner10()
222; CHECK-NOT: call void @inner10
223
224  ret void
225; CHECK: ret void
226}
227
228; The 'inner11' and 'outer11' functions test another dimension of non-internal
229; functions with alwaysinline. These functions use external linkages that we can
230; actually remove safely and so we should.
231define linkonce void @inner11a() alwaysinline {
232; CHECK-NOT: @inner11a(
233entry:
234  ret void
235}
236
237define available_externally void @inner11b() alwaysinline {
238; CHECK-NOT: @inner11b(
239entry:
240  ret void
241}
242
243define void @outer11() {
244; CHECK-LABEL: @outer11(
245entry:
246  call void @inner11a()
247  call void @inner11b()
248; CHECK-NOT: call void @inner11a
249; CHECK-NOT: call void @inner11b
250
251  ret void
252; CHECK: ret void
253}
254
255; The 'inner12' and 'outer12' functions test that we don't remove functions
256; which are part of a comdat group even if they otherwise seem dead.
257$comdat12 = comdat any
258
259define linkonce void @inner12() alwaysinline comdat($comdat12) {
260; CHECK-LABEL: @inner12(
261  ret void
262}
263
264define void @outer12() comdat($comdat12) {
265; CHECK-LABEL: @outer12(
266entry:
267  call void @inner12()
268; CHECK-NOT: call void @inner12
269
270  ret void
271; CHECK: ret void
272}
273
274; The 'inner13*' and 'outer13' functions test that we do remove functions
275; which are part of a comdat group where all of the members are removed during
276; always inlining.
277$comdat13 = comdat any
278
279define linkonce void @inner13a() alwaysinline comdat($comdat13) {
280; CHECK-NOT: @inner13a(
281  ret void
282}
283
284define linkonce void @inner13b() alwaysinline comdat($comdat13) {
285; CHECK-NOT: @inner13b(
286  ret void
287}
288
289define void @outer13() {
290; CHECK-LABEL: @outer13(
291entry:
292  call void @inner13a()
293  call void @inner13b()
294; CHECK-NOT: call void @inner13a
295; CHECK-NOT: call void @inner13b
296
297  ret void
298; CHECK: ret void
299}
300
301define void @inner14() readnone nounwind {
302; CHECK: define void @inner14
303  ret void
304}
305
306define void @outer14() {
307; CHECK: call void @inner14
308  call void @inner14()
309  ret void
310}
311
312define internal i32 @inner15() {
313; CHECK: @inner15(
314  ret i32 1
315}
316
317define i32 @outer15() {
318; CHECK-LABEL: @outer15(
319; CHECK: call
320
321   %r = call i32 @inner15() noinline
322   ret i32 %r
323}
324
325define internal i32 @inner16() alwaysinline {
326; CHECK: @inner16(
327  ret i32 1
328}
329
330define i32 @outer16() {
331; CHECK-LABEL: @outer16(
332; CHECK: call
333
334   %r = call i32 @inner16() noinline
335   ret i32 %r
336}
337
338define i32 @inner17() alwaysinline {
339; CHECK: @inner17(
340  ret i32 1
341}
342
343define i32 @outer17() {
344; CHECK-LABEL: @outer17(
345; CHECK: call
346
347   %r = call i32 @inner17() noinline
348   ret i32 %r
349}
350
351define i32 @inner18() noinline {
352; CHECK: @inner18(
353  ret i32 1
354}
355
356define i32 @outer18() {
357; CHECK-LABEL: @outer18(
358; CHECK-NOT: call
359; CHECK: ret
360
361   %r = call i32 @inner18() alwaysinline
362
363   ret i32 %r
364}
365