1; RUN: opt < %s -inline -S | FileCheck %s
2; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
3target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
4
5define i32 @noattr_callee(i32 %i) {
6  ret i32 %i
7}
8
9define i32 @sanitize_address_callee(i32 %i) sanitize_address {
10  ret i32 %i
11}
12
13define i32 @sanitize_thread_callee(i32 %i) sanitize_thread {
14  ret i32 %i
15}
16
17define i32 @sanitize_memory_callee(i32 %i) sanitize_memory {
18  ret i32 %i
19}
20
21define i32 @safestack_callee(i32 %i) safestack {
22  ret i32 %i
23}
24
25define i32 @alwaysinline_callee(i32 %i) alwaysinline {
26  ret i32 %i
27}
28
29define i32 @alwaysinline_sanitize_address_callee(i32 %i) alwaysinline sanitize_address {
30  ret i32 %i
31}
32
33define i32 @alwaysinline_sanitize_thread_callee(i32 %i) alwaysinline sanitize_thread {
34  ret i32 %i
35}
36
37define i32 @alwaysinline_sanitize_memory_callee(i32 %i) alwaysinline sanitize_memory {
38  ret i32 %i
39}
40
41define i32 @alwaysinline_safestack_callee(i32 %i) alwaysinline safestack {
42  ret i32 %i
43}
44
45
46; Check that:
47;  * noattr callee is inlined into noattr caller,
48;  * sanitize_(address|memory|thread) callee is not inlined into noattr caller,
49;  * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.
50
51define i32 @test_no_sanitize_address(i32 %arg) {
52  %x1 = call i32 @noattr_callee(i32 %arg)
53  %x2 = call i32 @sanitize_address_callee(i32 %x1)
54  %x3 = call i32 @alwaysinline_callee(i32 %x2)
55  %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)
56  ret i32 %x4
57; CHECK-LABEL: @test_no_sanitize_address(
58; CHECK-NEXT: @sanitize_address_callee
59; CHECK-NEXT: ret i32
60}
61
62define i32 @test_no_sanitize_memory(i32 %arg) {
63  %x1 = call i32 @noattr_callee(i32 %arg)
64  %x2 = call i32 @sanitize_memory_callee(i32 %x1)
65  %x3 = call i32 @alwaysinline_callee(i32 %x2)
66  %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)
67  ret i32 %x4
68; CHECK-LABEL: @test_no_sanitize_memory(
69; CHECK-NEXT: @sanitize_memory_callee
70; CHECK-NEXT: ret i32
71}
72
73define i32 @test_no_sanitize_thread(i32 %arg) {
74  %x1 = call i32 @noattr_callee(i32 %arg)
75  %x2 = call i32 @sanitize_thread_callee(i32 %x1)
76  %x3 = call i32 @alwaysinline_callee(i32 %x2)
77  %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)
78  ret i32 %x4
79; CHECK-LABEL: @test_no_sanitize_thread(
80; CHECK-NEXT: @sanitize_thread_callee
81; CHECK-NEXT: ret i32
82}
83
84
85; Check that:
86;  * noattr callee is not inlined into sanitize_(address|memory|thread) caller,
87;  * sanitize_(address|memory|thread) callee is inlined into the caller with the same attribute,
88;  * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.
89
90define i32 @test_sanitize_address(i32 %arg) sanitize_address {
91  %x1 = call i32 @noattr_callee(i32 %arg)
92  %x2 = call i32 @sanitize_address_callee(i32 %x1)
93  %x3 = call i32 @alwaysinline_callee(i32 %x2)
94  %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)
95  ret i32 %x4
96; CHECK-LABEL: @test_sanitize_address(
97; CHECK-NEXT: @noattr_callee
98; CHECK-NEXT: ret i32
99}
100
101define i32 @test_sanitize_memory(i32 %arg) sanitize_memory {
102  %x1 = call i32 @noattr_callee(i32 %arg)
103  %x2 = call i32 @sanitize_memory_callee(i32 %x1)
104  %x3 = call i32 @alwaysinline_callee(i32 %x2)
105  %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)
106  ret i32 %x4
107; CHECK-LABEL: @test_sanitize_memory(
108; CHECK-NEXT: @noattr_callee
109; CHECK-NEXT: ret i32
110}
111
112define i32 @test_sanitize_thread(i32 %arg) sanitize_thread {
113  %x1 = call i32 @noattr_callee(i32 %arg)
114  %x2 = call i32 @sanitize_thread_callee(i32 %x1)
115  %x3 = call i32 @alwaysinline_callee(i32 %x2)
116  %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)
117  ret i32 %x4
118; CHECK-LABEL: @test_sanitize_thread(
119; CHECK-NEXT: @noattr_callee
120; CHECK-NEXT: ret i32
121}
122
123define i32 @test_safestack(i32 %arg) safestack {
124  %x1 = call i32 @noattr_callee(i32 %arg)
125  %x2 = call i32 @safestack_callee(i32 %x1)
126  %x3 = call i32 @alwaysinline_callee(i32 %x2)
127  %x4 = call i32 @alwaysinline_safestack_callee(i32 %x3)
128  ret i32 %x4
129; CHECK-LABEL: @test_safestack(
130; CHECK-NEXT: @noattr_callee
131; CHECK-NEXT: ret i32
132}
133
134; Check that a function doesn't get inlined if target-cpu strings don't match
135; exactly.
136define i32 @test_target_cpu_callee0(i32 %i) "target-cpu"="corei7" {
137  ret i32 %i
138}
139
140define i32 @test_target_cpu0(i32 %i) "target-cpu"="corei7" {
141  %1 = call i32 @test_target_cpu_callee0(i32 %i)
142  ret i32 %1
143; CHECK-LABEL: @test_target_cpu0(
144; CHECK-NOT: @test_target_cpu_callee0
145}
146
147define i32 @test_target_cpu_callee1(i32 %i) "target-cpu"="x86-64" {
148  ret i32 %i
149}
150
151define i32 @test_target_cpu1(i32 %i) "target-cpu"="corei7" {
152  %1 = call i32 @test_target_cpu_callee1(i32 %i)
153  ret i32 %1
154; CHECK-LABEL: @test_target_cpu1(
155; CHECK-NEXT: @test_target_cpu_callee1
156; CHECK-NEXT: ret i32
157}
158
159; Check that a function doesn't get inlined if target-features strings don't
160; match exactly.
161define i32 @test_target_features_callee0(i32 %i)  "target-features"="+sse4.2" {
162  ret i32 %i
163}
164
165define i32 @test_target_features0(i32 %i) "target-features"="+sse4.2" {
166  %1 = call i32 @test_target_features_callee0(i32 %i)
167  ret i32 %1
168; CHECK-LABEL: @test_target_features0(
169; CHECK-NOT: @test_target_features_callee0
170}
171
172define i32 @test_target_features_callee1(i32 %i) "target-features"="+avx2" {
173  ret i32 %i
174}
175
176define i32 @test_target_features1(i32 %i) "target-features"="+sse4.2" {
177  %1 = call i32 @test_target_features_callee1(i32 %i)
178  ret i32 %1
179; CHECK-LABEL: @test_target_features1(
180; CHECK-NEXT: @test_target_features_callee1
181; CHECK-NEXT: ret i32
182}
183
184define i32 @less-precise-fpmad_callee0(i32 %i) "less-precise-fpmad"="false" {
185  ret i32 %i
186; CHECK: @less-precise-fpmad_callee0(i32 %i) [[FPMAD_FALSE:#[0-9]+]] {
187; CHECK-NEXT: ret i32
188}
189
190define i32 @less-precise-fpmad_callee1(i32 %i) "less-precise-fpmad"="true" {
191  ret i32 %i
192; CHECK: @less-precise-fpmad_callee1(i32 %i) [[FPMAD_TRUE:#[0-9]+]] {
193; CHECK-NEXT: ret i32
194}
195
196define i32 @test_less-precise-fpmad0(i32 %i) "less-precise-fpmad"="false" {
197  %1 = call i32 @less-precise-fpmad_callee0(i32 %i)
198  ret i32 %1
199; CHECK: @test_less-precise-fpmad0(i32 %i) [[FPMAD_FALSE]] {
200; CHECK-NEXT: ret i32
201}
202
203define i32 @test_less-precise-fpmad1(i32 %i) "less-precise-fpmad"="false" {
204  %1 = call i32 @less-precise-fpmad_callee1(i32 %i)
205  ret i32 %1
206; CHECK: @test_less-precise-fpmad1(i32 %i) [[FPMAD_FALSE]] {
207; CHECK-NEXT: ret i32
208}
209
210define i32 @test_less-precise-fpmad2(i32 %i) "less-precise-fpmad"="true" {
211  %1 = call i32 @less-precise-fpmad_callee0(i32 %i)
212  ret i32 %1
213; CHECK: @test_less-precise-fpmad2(i32 %i) [[FPMAD_FALSE]] {
214; CHECK-NEXT: ret i32
215}
216
217define i32 @test_less-precise-fpmad3(i32 %i) "less-precise-fpmad"="true" {
218  %1 = call i32 @less-precise-fpmad_callee1(i32 %i)
219  ret i32 %1
220; CHECK: @test_less-precise-fpmad3(i32 %i) [[FPMAD_TRUE]] {
221; CHECK-NEXT: ret i32
222}
223
224define i32 @no-implicit-float_callee0(i32 %i) {
225  ret i32 %i
226; CHECK: @no-implicit-float_callee0(i32 %i) {
227; CHECK-NEXT: ret i32
228}
229
230define i32 @no-implicit-float_callee1(i32 %i) noimplicitfloat {
231  ret i32 %i
232; CHECK: @no-implicit-float_callee1(i32 %i) [[NOIMPLICITFLOAT:#[0-9]+]] {
233; CHECK-NEXT: ret i32
234}
235
236define i32 @test_no-implicit-float0(i32 %i) {
237  %1 = call i32 @no-implicit-float_callee0(i32 %i)
238  ret i32 %1
239; CHECK: @test_no-implicit-float0(i32 %i) {
240; CHECK-NEXT: ret i32
241}
242
243define i32 @test_no-implicit-float1(i32 %i) {
244  %1 = call i32 @no-implicit-float_callee1(i32 %i)
245  ret i32 %1
246; CHECK: @test_no-implicit-float1(i32 %i) [[NOIMPLICITFLOAT]] {
247; CHECK-NEXT: ret i32
248}
249
250define i32 @test_no-implicit-float2(i32 %i) noimplicitfloat {
251  %1 = call i32 @no-implicit-float_callee0(i32 %i)
252  ret i32 %1
253; CHECK: @test_no-implicit-float2(i32 %i) [[NOIMPLICITFLOAT]] {
254; CHECK-NEXT: ret i32
255}
256
257define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat {
258  %1 = call i32 @no-implicit-float_callee1(i32 %i)
259  ret i32 %1
260; CHECK: @test_no-implicit-float3(i32 %i) [[NOIMPLICITFLOAT]] {
261; CHECK-NEXT: ret i32
262}
263
264; Check that no-jump-tables flag propagates from inlined callee to caller
265
266define i32 @no-use-jump-tables_callee0(i32 %i) {
267  ret i32 %i
268; CHECK: @no-use-jump-tables_callee0(i32 %i) {
269; CHECK-NEXT: ret i32
270}
271
272define i32 @no-use-jump-tables_callee1(i32 %i) "no-jump-tables"="true" {
273  ret i32 %i
274; CHECK: @no-use-jump-tables_callee1(i32 %i) [[NOUSEJUMPTABLES:#[0-9]+]] {
275; CHECK-NEXT: ret i32
276}
277
278define i32 @test_no-use-jump-tables0(i32 %i) {
279  %1 = call i32 @no-use-jump-tables_callee0(i32 %i)
280  ret i32 %1
281; CHECK: @test_no-use-jump-tables0(i32 %i) {
282; CHECK-NEXT: ret i32
283}
284
285define i32 @test_no-use-jump-tables1(i32 %i) {
286  %1 = call i32 @no-use-jump-tables_callee1(i32 %i)
287  ret i32 %1
288; CHECK: @test_no-use-jump-tables1(i32 %i) [[NOUSEJUMPTABLES]] {
289; CHECK-NEXT: ret i32
290}
291
292define i32 @test_no-use-jump-tables2(i32 %i) "no-jump-tables"="true" {
293  %1 = call i32 @no-use-jump-tables_callee0(i32 %i)
294  ret i32 %1
295; CHECK: @test_no-use-jump-tables2(i32 %i) [[NOUSEJUMPTABLES]] {
296; CHECK-NEXT: ret i32
297}
298
299define i32 @test_no-use-jump-tables3(i32 %i) "no-jump-tables"="true" {
300  %1 = call i32 @no-use-jump-tables_callee1(i32 %i)
301  ret i32 %1
302; CHECK: @test_no-use-jump-tables3(i32 %i) [[NOUSEJUMPTABLES]] {
303; CHECK-NEXT: ret i32
304}
305
306; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" }
307; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" }
308; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat }
309; CHECK: attributes [[NOUSEJUMPTABLES]] = { "no-jump-tables"="true" }
310