1 ; RUN: opt < %s -inline -S | FileCheck %s
2 ; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
3 target 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"
5 define i32 @noattr_callee(i32 %i) {
9 define i32 @sanitize_address_callee(i32 %i) sanitize_address {
13 define i32 @sanitize_hwaddress_callee(i32 %i) sanitize_hwaddress {
17 define i32 @sanitize_thread_callee(i32 %i) sanitize_thread {
21 define i32 @sanitize_memory_callee(i32 %i) sanitize_memory {
25 define i32 @safestack_callee(i32 %i) safestack {
29 define i32 @slh_callee(i32 %i) speculative_load_hardening {
33 define i32 @alwaysinline_callee(i32 %i) alwaysinline {
37 define i32 @alwaysinline_sanitize_address_callee(i32 %i) alwaysinline sanitize_address {
41 define i32 @alwaysinline_sanitize_hwaddress_callee(i32 %i) alwaysinline sanitize_hwaddress {
45 define i32 @alwaysinline_sanitize_thread_callee(i32 %i) alwaysinline sanitize_thread {
49 define i32 @alwaysinline_sanitize_memory_callee(i32 %i) alwaysinline sanitize_memory {
53 define i32 @alwaysinline_safestack_callee(i32 %i) alwaysinline safestack {
59 ; * noattr callee is inlined into noattr caller,
60 ; * sanitize_(address|memory|thread) callee is not inlined into noattr caller,
61 ; * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.
63 define i32 @test_no_sanitize_address(i32 %arg) {
64 %x1 = call i32 @noattr_callee(i32 %arg)
65 %x2 = call i32 @sanitize_address_callee(i32 %x1)
66 %x3 = call i32 @alwaysinline_callee(i32 %x2)
67 %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)
69 ; CHECK-LABEL: @test_no_sanitize_address(
70 ; CHECK-NEXT: @sanitize_address_callee
74 define i32 @test_no_sanitize_hwaddress(i32 %arg) {
75 %x1 = call i32 @noattr_callee(i32 %arg)
76 %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
77 %x3 = call i32 @alwaysinline_callee(i32 %x2)
78 %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
80 ; CHECK-LABEL: @test_no_sanitize_hwaddress(
81 ; CHECK-NEXT: @sanitize_hwaddress_callee
85 define i32 @test_no_sanitize_memory(i32 %arg) {
86 %x1 = call i32 @noattr_callee(i32 %arg)
87 %x2 = call i32 @sanitize_memory_callee(i32 %x1)
88 %x3 = call i32 @alwaysinline_callee(i32 %x2)
89 %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)
91 ; CHECK-LABEL: @test_no_sanitize_memory(
92 ; CHECK-NEXT: @sanitize_memory_callee
96 define i32 @test_no_sanitize_thread(i32 %arg) {
97 %x1 = call i32 @noattr_callee(i32 %arg)
98 %x2 = call i32 @sanitize_thread_callee(i32 %x1)
99 %x3 = call i32 @alwaysinline_callee(i32 %x2)
100 %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)
102 ; CHECK-LABEL: @test_no_sanitize_thread(
103 ; CHECK-NEXT: @sanitize_thread_callee
104 ; CHECK-NEXT: ret i32
109 ; * noattr callee is not inlined into sanitize_(address|memory|thread) caller,
110 ; * sanitize_(address|memory|thread) callee is inlined into the caller with the same attribute,
111 ; * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.
113 define i32 @test_sanitize_address(i32 %arg) sanitize_address {
114 %x1 = call i32 @noattr_callee(i32 %arg)
115 %x2 = call i32 @sanitize_address_callee(i32 %x1)
116 %x3 = call i32 @alwaysinline_callee(i32 %x2)
117 %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)
119 ; CHECK-LABEL: @test_sanitize_address(
120 ; CHECK-NEXT: @noattr_callee
121 ; CHECK-NEXT: ret i32
124 define i32 @test_sanitize_hwaddress(i32 %arg) sanitize_hwaddress {
125 %x1 = call i32 @noattr_callee(i32 %arg)
126 %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
127 %x3 = call i32 @alwaysinline_callee(i32 %x2)
128 %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
130 ; CHECK-LABEL: @test_sanitize_hwaddress(
131 ; CHECK-NEXT: @noattr_callee
132 ; CHECK-NEXT: ret i32
135 define i32 @test_sanitize_memory(i32 %arg) sanitize_memory {
136 %x1 = call i32 @noattr_callee(i32 %arg)
137 %x2 = call i32 @sanitize_memory_callee(i32 %x1)
138 %x3 = call i32 @alwaysinline_callee(i32 %x2)
139 %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)
141 ; CHECK-LABEL: @test_sanitize_memory(
142 ; CHECK-NEXT: @noattr_callee
143 ; CHECK-NEXT: ret i32
146 define i32 @test_sanitize_thread(i32 %arg) sanitize_thread {
147 %x1 = call i32 @noattr_callee(i32 %arg)
148 %x2 = call i32 @sanitize_thread_callee(i32 %x1)
149 %x3 = call i32 @alwaysinline_callee(i32 %x2)
150 %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)
152 ; CHECK-LABEL: @test_sanitize_thread(
153 ; CHECK-NEXT: @noattr_callee
154 ; CHECK-NEXT: ret i32
157 define i32 @test_safestack(i32 %arg) safestack {
158 %x1 = call i32 @noattr_callee(i32 %arg)
159 %x2 = call i32 @safestack_callee(i32 %x1)
160 %x3 = call i32 @alwaysinline_callee(i32 %x2)
161 %x4 = call i32 @alwaysinline_safestack_callee(i32 %x3)
163 ; CHECK-LABEL: @test_safestack(
164 ; CHECK-NEXT: @noattr_callee
165 ; CHECK-NEXT: ret i32
168 ; Can inline a normal function into an SLH'ed function.
169 define i32 @test_caller_slh(i32 %i) speculative_load_hardening {
170 ; CHECK-LABEL: @test_caller_slh(
171 ; CHECK-SAME: ) [[SLH:.*]] {
175 %callee = call i32 @noattr_callee(i32 %i)
179 ; Can inline a SLH'ed function into a normal one, propagating SLH.
180 define i32 @test_callee_slh(i32 %i) {
181 ; CHECK-LABEL: @test_callee_slh(
182 ; CHECK-SAME: ) [[SLH:.*]] {
186 %callee = call i32 @slh_callee(i32 %i)
190 ; Check that a function doesn't get inlined if target-cpu strings don't match
192 define i32 @test_target_cpu_callee0(i32 %i) "target-cpu"="corei7" {
196 define i32 @test_target_cpu0(i32 %i) "target-cpu"="corei7" {
197 %1 = call i32 @test_target_cpu_callee0(i32 %i)
199 ; CHECK-LABEL: @test_target_cpu0(
200 ; CHECK-NOT: @test_target_cpu_callee0
203 define i32 @test_target_cpu_callee1(i32 %i) "target-cpu"="x86-64" {
207 define i32 @test_target_cpu1(i32 %i) "target-cpu"="corei7" {
208 %1 = call i32 @test_target_cpu_callee1(i32 %i)
210 ; CHECK-LABEL: @test_target_cpu1(
211 ; CHECK-NEXT: @test_target_cpu_callee1
212 ; CHECK-NEXT: ret i32
215 ; Check that a function doesn't get inlined if target-features strings don't
217 define i32 @test_target_features_callee0(i32 %i) "target-features"="+sse4.2" {
221 define i32 @test_target_features0(i32 %i) "target-features"="+sse4.2" {
222 %1 = call i32 @test_target_features_callee0(i32 %i)
224 ; CHECK-LABEL: @test_target_features0(
225 ; CHECK-NOT: @test_target_features_callee0
228 define i32 @test_target_features_callee1(i32 %i) "target-features"="+avx2" {
232 define i32 @test_target_features1(i32 %i) "target-features"="+sse4.2" {
233 %1 = call i32 @test_target_features_callee1(i32 %i)
235 ; CHECK-LABEL: @test_target_features1(
236 ; CHECK-NEXT: @test_target_features_callee1
237 ; CHECK-NEXT: ret i32
240 define i32 @less-precise-fpmad_callee0(i32 %i) "less-precise-fpmad"="false" {
242 ; CHECK: @less-precise-fpmad_callee0(i32 %i) [[FPMAD_FALSE:#[0-9]+]] {
243 ; CHECK-NEXT: ret i32
246 define i32 @less-precise-fpmad_callee1(i32 %i) "less-precise-fpmad"="true" {
248 ; CHECK: @less-precise-fpmad_callee1(i32 %i) [[FPMAD_TRUE:#[0-9]+]] {
249 ; CHECK-NEXT: ret i32
252 define i32 @test_less-precise-fpmad0(i32 %i) "less-precise-fpmad"="false" {
253 %1 = call i32 @less-precise-fpmad_callee0(i32 %i)
255 ; CHECK: @test_less-precise-fpmad0(i32 %i) [[FPMAD_FALSE]] {
256 ; CHECK-NEXT: ret i32
259 define i32 @test_less-precise-fpmad1(i32 %i) "less-precise-fpmad"="false" {
260 %1 = call i32 @less-precise-fpmad_callee1(i32 %i)
262 ; CHECK: @test_less-precise-fpmad1(i32 %i) [[FPMAD_FALSE]] {
263 ; CHECK-NEXT: ret i32
266 define i32 @test_less-precise-fpmad2(i32 %i) "less-precise-fpmad"="true" {
267 %1 = call i32 @less-precise-fpmad_callee0(i32 %i)
269 ; CHECK: @test_less-precise-fpmad2(i32 %i) [[FPMAD_FALSE]] {
270 ; CHECK-NEXT: ret i32
273 define i32 @test_less-precise-fpmad3(i32 %i) "less-precise-fpmad"="true" {
274 %1 = call i32 @less-precise-fpmad_callee1(i32 %i)
276 ; CHECK: @test_less-precise-fpmad3(i32 %i) [[FPMAD_TRUE]] {
277 ; CHECK-NEXT: ret i32
280 define i32 @no-implicit-float_callee0(i32 %i) {
282 ; CHECK: @no-implicit-float_callee0(i32 %i) {
283 ; CHECK-NEXT: ret i32
286 define i32 @no-implicit-float_callee1(i32 %i) noimplicitfloat {
288 ; CHECK: @no-implicit-float_callee1(i32 %i) [[NOIMPLICITFLOAT:#[0-9]+]] {
289 ; CHECK-NEXT: ret i32
292 define i32 @test_no-implicit-float0(i32 %i) {
293 %1 = call i32 @no-implicit-float_callee0(i32 %i)
295 ; CHECK: @test_no-implicit-float0(i32 %i) {
296 ; CHECK-NEXT: ret i32
299 define i32 @test_no-implicit-float1(i32 %i) {
300 %1 = call i32 @no-implicit-float_callee1(i32 %i)
302 ; CHECK: @test_no-implicit-float1(i32 %i) [[NOIMPLICITFLOAT]] {
303 ; CHECK-NEXT: ret i32
306 define i32 @test_no-implicit-float2(i32 %i) noimplicitfloat {
307 %1 = call i32 @no-implicit-float_callee0(i32 %i)
309 ; CHECK: @test_no-implicit-float2(i32 %i) [[NOIMPLICITFLOAT]] {
310 ; CHECK-NEXT: ret i32
313 define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat {
314 %1 = call i32 @no-implicit-float_callee1(i32 %i)
316 ; CHECK: @test_no-implicit-float3(i32 %i) [[NOIMPLICITFLOAT]] {
317 ; CHECK-NEXT: ret i32
320 ; Check that no-jump-tables flag propagates from inlined callee to caller
322 define i32 @no-use-jump-tables_callee0(i32 %i) {
324 ; CHECK: @no-use-jump-tables_callee0(i32 %i) {
325 ; CHECK-NEXT: ret i32
328 define i32 @no-use-jump-tables_callee1(i32 %i) "no-jump-tables"="true" {
330 ; CHECK: @no-use-jump-tables_callee1(i32 %i) [[NOUSEJUMPTABLES:#[0-9]+]] {
331 ; CHECK-NEXT: ret i32
334 define i32 @test_no-use-jump-tables0(i32 %i) {
335 %1 = call i32 @no-use-jump-tables_callee0(i32 %i)
337 ; CHECK: @test_no-use-jump-tables0(i32 %i) {
338 ; CHECK-NEXT: ret i32
341 define i32 @test_no-use-jump-tables1(i32 %i) {
342 %1 = call i32 @no-use-jump-tables_callee1(i32 %i)
344 ; CHECK: @test_no-use-jump-tables1(i32 %i) [[NOUSEJUMPTABLES]] {
345 ; CHECK-NEXT: ret i32
348 define i32 @test_no-use-jump-tables2(i32 %i) "no-jump-tables"="true" {
349 %1 = call i32 @no-use-jump-tables_callee0(i32 %i)
351 ; CHECK: @test_no-use-jump-tables2(i32 %i) [[NOUSEJUMPTABLES]] {
352 ; CHECK-NEXT: ret i32
355 define i32 @test_no-use-jump-tables3(i32 %i) "no-jump-tables"="true" {
356 %1 = call i32 @no-use-jump-tables_callee1(i32 %i)
358 ; CHECK: @test_no-use-jump-tables3(i32 %i) [[NOUSEJUMPTABLES]] {
359 ; CHECK-NEXT: ret i32
362 ; Callee with "null-pointer-is-valid"="true" attribute should not be inlined
363 ; into a caller without this attribute.
364 ; Exception: alwaysinline callee can still be inlined but
365 ; "null-pointer-is-valid"="true" should get copied to caller.
367 define i32 @null-pointer-is-valid_callee0(i32 %i) "null-pointer-is-valid"="true" {
369 ; CHECK: @null-pointer-is-valid_callee0(i32 %i)
370 ; CHECK-NEXT: ret i32
373 define i32 @null-pointer-is-valid_callee1(i32 %i) alwaysinline "null-pointer-is-valid"="true" {
375 ; CHECK: @null-pointer-is-valid_callee1(i32 %i)
376 ; CHECK-NEXT: ret i32
379 define i32 @null-pointer-is-valid_callee2(i32 %i) {
381 ; CHECK: @null-pointer-is-valid_callee2(i32 %i)
382 ; CHECK-NEXT: ret i32
385 ; No inlining since caller does not have "null-pointer-is-valid"="true" attribute.
386 define i32 @test_null-pointer-is-valid0(i32 %i) {
387 %1 = call i32 @null-pointer-is-valid_callee0(i32 %i)
389 ; CHECK: @test_null-pointer-is-valid0(
390 ; CHECK: call i32 @null-pointer-is-valid_callee0
391 ; CHECK-NEXT: ret i32
394 ; alwaysinline should force inlining even when caller does not have
395 ; "null-pointer-is-valid"="true" attribute. However, the attribute should be
397 define i32 @test_null-pointer-is-valid1(i32 %i) "null-pointer-is-valid"="false" {
398 %1 = call i32 @null-pointer-is-valid_callee1(i32 %i)
400 ; CHECK: @test_null-pointer-is-valid1(i32 %i) [[NULLPOINTERISVALID:#[0-9]+]] {
401 ; CHECK-NEXT: ret i32
404 ; Can inline since both caller and callee have "null-pointer-is-valid"="true"
406 define i32 @test_null-pointer-is-valid2(i32 %i) "null-pointer-is-valid"="true" {
407 %1 = call i32 @null-pointer-is-valid_callee2(i32 %i)
409 ; CHECK: @test_null-pointer-is-valid2(i32 %i) [[NULLPOINTERISVALID]] {
410 ; CHECK-NEXT: ret i32
413 ; CHECK: attributes [[SLH]] = { speculative_load_hardening }
414 ; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" }
415 ; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" }
416 ; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat }
417 ; CHECK: attributes [[NOUSEJUMPTABLES]] = { "no-jump-tables"="true" }
418 ; CHECK: attributes [[NULLPOINTERISVALID]] = { "null-pointer-is-valid"="true" }